Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Struct default values random behaviour when using env var #3289

Closed
jonhkr opened this issue Apr 23, 2015 · 6 comments
Closed

Struct default values random behaviour when using env var #3289

jonhkr opened this issue Apr 23, 2015 · 6 comments

Comments

@jonhkr
Copy link

jonhkr commented Apr 23, 2015

I have the following scenario where a struct is defined with default values that come from Application.get_env function:

defmodule M do
  defstruct a: Application.get_env(:app, :a), b: Application.get_env(:app, :b)
end

These env values come from the config.exs as follows:

config :app,
  a: "value for a",
  b: "value for b"

Sometimes when the application starts, the struct receives the values from the config, sometimes it just receives nil, actually, most of the time it receives nil.

I think that this happens because the configuration is being evaluated after the struct definition, then when it tries to get the values they weren't defined yet.

@josevalim
Copy link
Member

This behavior is going to read the application configuration at compile
time. Is this what you really want?

José Valim
www.plataformatec.com.br
Skype: jv.ptec
Founder and Lead Developer

@jonhkr
Copy link
Author

jonhkr commented Apr 23, 2015

I don't know if I'm right, please correct me if not, I believe the struct default values are evaluated only once, when the struct is evaluated. In this case I think that the application configuration should be available so that the struct can receive its default values.

One use case for this is when I need to authenticate to an third party web service and want to have my authentication info in a struct without having to set it everytime. For instance, I can build the request like:

request = %Request{
  auth: %Auth{},
  foo: "bar"
}

Where Auth is defined like so:

defstruct key: Application.get_env(:app, :key), secret: Application.get_env(:app, :secret)

@ericmj
Copy link
Member

ericmj commented Apr 23, 2015

Struct default values are evaluated only once - at compile time. If you have the key and secret when compiling you should be fine, if not you need to fetch it every time you create a struct.

@josevalim
Copy link
Member

I could not reproduce this. The values are always there if they have been set at compilation time.

@jonhkr
Copy link
Author

jonhkr commented Apr 28, 2015

I'm sorry, I've not shown you the full scenario.

This behaviour happen when I have this struct in a project and I try to configure it from another project.

Say I have the project A that contains this struct that gets its default values from the application configuration. Then I create project B that depends on project A to work. Project B sets those environment variables which are not being read because project A is compiled before project B.

I think there should be a warning in the docs to tell people about this. It is documented here though, in case someone else runs in the same problem.

@josevalim
Copy link
Member

Your approach is fine but you need to configure it before you add A as a dependency. If it is done afterwards, you should do mix deps.clean a so it gets compiled again. You should definitely add this information to your project readme because, I agree, it is not super obvious. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants