Somewhat a legacy project. There’re Application.get_env(...) and Application.get_env(...)[:some_key] as the module attributes here and there. I’ve replaced releases.exs with runtime.exs.
Yet I’m confused: will Application.get_env(...) as the module attributes work properly then? Will they point to the compile time config values or the runtime ones?
Another option is to use Application.compile_env!/3 if you want to keep the module attributes with compile time config values instead of replacing them with runtime evaluated functions.
Is there a way to use both - compile-time and runtime values - such that the runtime ones will have the preferance? If a runtime value has been provided, use it, otherwise - fallback to the one specified statically, in config/{dev,prod,qa,test,etc}.exs
The following should work, but I would not encourage it. Now your code is linked to 2 configs and in the future it’s hard to know which env returns the value.
def get_value() do
Application.get_env(runtime_value...) || Application.compile_env!(compiletime_value...)
end
That said, you cannot expect the module attributes to respect this, because they are generated at compile time and the runtime config does not yet exist.
I would switch to functions to save on disk and memory usage, anyways. See this from Sara Juric about how module attributes as constants have a potential gotcha: Blog Post: 10 Elixir gotchas - #16 by sasajuric
a) I have to use a module attribute – in order to embed it into other modules via a macro.
b) Yet I also want to be able to pass a variable that a said module attribute reads from config dynamically, at runtime.
?
defmodule MyMod1 do
defmacro __using__(_) do
quote do
# @a1 Application.compile_env(:my_app, My.App)[:key1]
@a1 Application.get_env(:my_app, My.App)[:key1]
# ............