In the aims of avoiding an X -> Y problem, here's the context:
I am working on a Phoenix application, and have a mailer module for sending (you guessed it!) emails.
The thing is, I would like my application code to not directly reference the mailer module, I would prefer it got injected into the application module instead so I can supply a different implementation based on the environment.
My current setup is:
defmodule App.Behaviour do
@callback do_thing() :: :ok
end
defmodule AppWeb.Implementation do
@behaviour App.Behaviour
def do_thing(), do: :ok
end
defmodule App.Context do
@service Application.compile_env!(:app, :service)
def do_magic do
@service.do_thing()
end
end
and in config.exs:
config :app, :service, AppWeb.Implementation
And... it works... but I get zero intellisense/docs when using the module attribute in my code... is there a way to fix that?
I tried supplying a default value to compile_env in the hopes this would help the compiler know what to expect for that attribute... no success.
Isn't this being injected comp-time, why is the compiler not aware of the value? Is it a bug with my language server maybe? Am I overthinking it and I should instead just use the module directly in my app code and instead do the mocking as part of my implementation based on some config value?
Help a brotha out 😅 thanks in advance all!