I’m experiencing an unexpected behaviour when accessing the application environment in an umbrella project with multiple children apps. It seems that Application.get_env/3 function doesn’t return the value stored in the config/config.exs
of the child application where the function is run. Instead it returns the valued stored in the config/config.exs
of the most recently added child app in the umbrella project.
To better test out the problem I’ve create a playground umbrella project adding some very basic Phoenix 1.3 apps: a shared context app (my_app
) and some web apps (my_app_web_one
, my_app_web_two
, …)
$ mix new my_umbrella --umbrella && cd my_umbrella/apps
$ mix phx.new.ecto my_app
$ mix phx.new.web my_app_web_one
$ mix phx.new.web my_app_web_two
and made these adjustements on the scaffold files:
my_umbrella
└── apps
│
├── my_app ## The shared Ecto/Context app
│
│
│
├── my_app_web_one ## The first web app
│ ├── config
│ │ └── config.exs # 1) changed to config :my_app_web_one, ..., ecto_repos: [MyApp.Repo]
│ │ # 2) changed to config :my_app_web_one, :generators, context_app: :my_app
│ │ # 3) add entry for config :mylib, endpoint: MyAppWebOne.Endpoint
│ │
│ ├── test
│ │ ├── my_app_web_one
│ │ │ └── my_test.exs # Add test for assert Application.get_env(:mylib, :endpoint) == MyAppWebOne.Endpoint
│ │ ├── support
│ │ │ ├── channel_case.exs # Changed occurrency of {MyAppWebOne.Repo} to {MyApp.Repo}
│ │ │ └── conn_case.exs # Changed occurrency of {MyAppWebOne.Repo} to {MyApp.Repo}
│ │ └── test_helper.exs # Changed occurrency of {MyAppWebOne.Repo, :manual} to {MyApp.Repo, :manual}
│ │
│ └── mix.exs # 1) add {:my_app, in_umbrella: true} to deps
│ # 2) add {:mylib, "~> 1.0"} to deps
│
│
│
└── my_app_web_two ## The second web app
├── config
│ ├── config.exs # 1) changed to config :my_app_web_two, ..., ecto_repos: [MyApp.Repo]
│ │ # 2) changed to config :my_app_web_two, :generators, context_app: :my_app
│ │ # 3) add entry for config :mylib, endpoint: MyAppWebTwo.Endpoint
│ └── dev.exs # Changed the http port to 4040
│
├── test
│ ├── my_app_web_one
│ │ └── my_test.exs # Add test for assert Application.get_env(:mylib, :endpoint) == MyAppWebTwo.Endpoint
│ ├── support
│ │ ├── channel_case.exs # Changed occurrency of {MyAppWebTwo.Repo} to {MyApp.Repo}
│ │ └── conn_case.exs # Changed occurrency of {MyAppWebTwo.Repo} to {MyApp.Repo}
│ └── test_helper.exs # Changed occurrency of {MyAppWebTwo.Repo, :manual} to {MyApp.Repo, :manual}
│
└── mix.exs # 1) add {:my_app, in_umbrella: true} to deps
# 2) add {:mylib, "~> 1.0"} to deps
The adjustements mainly regard setting the right references for the context app in the web applications, and configuring a dependency called mylib
.
the mylib
entry for apps/my_app_web_one/config/ config.exs
is
config :mylib,
endpoint: MyAppWebOne
while the mylib
entry for apps/my_app_web_two/config/ config.exs
is
config :mylib,
endpoint: MyAppWebTwo
And these are the tests for checking the value returned by Application.get_env
in each web app :
for apps/my_app_web_one:
# (the namespace is of course different for each app)
defmodule MyAppOne.MyTest do
use ExUnit.Case
test "test 'mylib' endpoint for MyAppOne" do
assert Application.get_env(:mylib, :endpoint) == MyAppOne.Endpoint
end
end
for apps/my_app_web_two:
defmodule MyAppTwo.MyTest do
use ExUnit.Case
test "test 'mylib' endpoint for MyAppTwo" do
assert Application.get_env(:mylib, :endpoint) == MyAppTwo.Endpoint
end
end
Running the tests for each web app give:
- test for
apps/my_app_web_one
fails becauseApplication.get_env(:mylib, :endpoint)
returnsMyAppTwo.Endpoint
instead ofMyAppOne.Endpoint
- test for
apps/my_app_web_two
succeded.
Adding a third web app to the project called my_app_web_three
, things go this way instead:
- test for
apps/my_app_web_one
fails becauseApplication.get_env(:mylib, :endpoint)
returnsMyAppThree.Endpoint
instead ofMyAppOne.Endpoint
- test for
apps/my_app_web_two
fails becauseApplication.get_env(:mylib, :endpoint)
returnsMyAppThree.Endpoint
instead ofMyAppTwo.Endpoint
- test for
apps/my_app_web_three
succeded
I’ve also tried to leave just one web app at time in the umbrella project, and test succeded every time for all the three apps.
I wasn’t able to find in the documentation for Elixir umbrella projects, for Application.get_env/3 or for the Phx generators anything that let me understand where can be the problem, neither googling on this forum or on stackoverflow.
So maybe is just me that don’t understand well how things have to work in these kinds of projects. Can you point me towards something I’ve missed?