A variable from a config isn't visible in prod.exs during deploy

In my config/config.exs I have this

use Mix.Config

some_var = "fdsafdsfds"

And in config/prod.exs I’m refering to it:

config :my_app, MyApp.Endpoint,
  some_key: some_var

However, when I’m deploying it to a server, the error occurs stating that:

warning: variable "some_var" does not exist and is being expanded to "some_var()", please use parentheses to remove the ambiguity or change the variable name
  config/prod.exs:4

** (Mix.Config.LoadError) could not load config config/prod.exs
    ** (CompileError) config/prod.exs:4: undefined function some_var/0

Why is that? How to fix it?

1 Like

It is because all config files have their own scope. And you can’t fix that.

config.exs is usually used for configuration that is the same (or similar) across environments.

It feels a bit like the XY-Problame, so please tell us what and why you want to achieve, so we can tell you how to do it proper?

2 Likes

All feels like XY problem always.

What I need to do is described in my question – I need to be able to use a variable from confg.exs in dev.exs and prod.exs

dev.exs and prod.exs get included into config.exs, why aren’t the variable visible?

2 Likes

No they aren’t included in that sense that it usually would mean in C or PHP, they are loaded, evaluated and merged into the current config.

Thus, if you want to have some piece of config common in multiple environments, just configure it in config.exs, and overwrite it everywhere where you do need it defferently.

This is just how the config system works.

2 Likes

In fact sometimes it would be useful to be able to access previous config values in further configs. For example with Nerves, I ran into a situation where I was setting a list in the configuration and a further config would have added to that list. Copying the whole list to the second place makes it worse to maintain.

Does Application.get_env work in configs?

1 Like

I haven’t tried, but I’d guess that it is not working, as the config isn’*t loaded yet, we are still generating it…

1 Like

The thing is, some keys in the config files depend on it. That’s why I want to define it as a variable to which I want to refer from the config keys.

something like:

some_var = "my_var"

config :my_app, MyApp.Endpoint,
  some_key: "#{some_var}_aaaa"
  some_key2: "#{some_var}_fdafdsfadsfds"
  some_key3: "aaaabbbfds_#{some_var}_fdafdsfadsfds333"

Furthermore, if I define it as a key, how can I access it from other keys, even in the same config?

Should I instead create a module MyConfigEx where I can define such a variable?

# config/config.exs
config :my_app, MyApp.Endpoint,
  some_key: "#{MyConfigEx.some_var}_aaaa"
  some_key2: "#{MyConfigEx.some_var}_fdafdsfadsfds"
  some_key3: "aaaabbbfds_#{MyConfigEx.some_var}_fdafdsfadsfds333"


# config/prod.exs
config :my_app, MyApp.Endpoint,
  some_key: "#{MyConfigEx.some_var}_aaaa22"
  some_key2: "#{MyConfigEx.some_var}_fdafdsfadsfds222"
  some_key3: "aaaabbbfds_#{MyConfigEx.some_var}_fdafdsfadsfds333222"
1 Like

That should work as is, as long as config and variable are in the same file

2 Likes

Ok. But for the different config files?

1 Like

As I said earlier, that’s currently not possible.

2 Likes

Thinking more about it, it should be possible to use System.put_env/1/2 in the config.exs and System.get_env/0/1 in the ${MIX_ENV}.exs to circumvent the limitation.

I do not think this were a clean solution though…

As I see your use case here is an idea. Untested and maybe syntactically wrong.

It seems the only thing that needs configured is some_var = "my_var". The rest of the keys are derived from it. My guess is that there must be some default value for it since you seek to use your own config file. Based on that you can create a module that provides the calculated values and use the functions instead of variables.

defmodule MyApp.MyKeys do

   @default_var "my_var"

  defp get_var, do: Application.get_env(:myapp, :some_var, @default_var)

  def get_key1, do: "#{get_var()}_aaaa" 
  
  def get_key2: "#{get_var()}_fdafdsfadsfds"

  def get_key3: "aaaabbbfds_#{get_var()}_fdafdsfadsfds333"

end

I did understand the example, as if the variable is the same throughout the environments, but the surroundings change…

Where it is "#{my_var}_aaaa" in prod, it may be "#{my_var}_rumba" in dev…