Config variables only updated on package recompile.
Overview
Configuration variables are only updated on arangoex recompilation, thus if the main application's configuration files are updated and recompiled but arangoex is not, then arangoex has the wrong config variables.
Context
I was having problems getting arangoex to read my config file specifying my host, database, etc. Everything looked right and I was able to read the correct values calling Application.get_env(:arangoex, :hostname) in iex.
After being utterly confused for a while I looked into Elixir's attributes a bit more. It turns out that attributes are read during compilation. Since I compiled arangoex after I fetched the dependency, but before I changed my configuration file, the values never got updated. Keep in mind that my application gets recompiled with every change I make, but the packages don't have a reason to get recompiled.
Let me know if this doesn't make sense.
Proposed Solution
I think the configuration variables should be into a function that reads from Application.get_env/3. For example this is what Guardian does:
def config, do: Application.get_env(:guardian, Guardian)
I also checked how the Ecto library handles configuration values. It does use attributes, however, the difference is that the attributes are imported into the main application's module using the use keyword. Since the attributes then exist in the main application, they get updated when the application gets recompiled and not during the Ecto's package recompilation.
defmodule Ecto.Repo do
defmacro __using__(opts) do
quote bind_quoted: [opts: opts] do
@behaviour Ecto.Repo
{otp_app, adapter, config} = Ecto.Repo.Supervisor.compile_config(__MODULE__, opts)
@otp_app otp_app
@adapter adapter
@config config
@before_compile adapter
# ...
end
end
end
I don't mind making some changes and doing a PR, unless you'd rather do it yourself. I thought I'd discuss it with you before submitting a PR however.
@PerishableDave, thanks for the issue!
I understand what's happening, but I'm not sure if I want to address it right now. I only ever meant for arangoex to be a simple wrapper for the http api. Once, I have that functionality in place, I was going to work on a higher level library for working with the database. This would be the equivalent of ecto using low level drivers like postgrex and mariaex. That is where I would introduce a repo-like concept that would allow the application to easily configure multiple connections.
In the mean time, I'll think about how this might be possible with just the base Arangoex module. Otherwise, it seems like a simple note in the Readme to indicate changing configs requires a deps re-complie should suffice.
Totally understand, though I think it could be fixed without changing the code too much. If the config values were read in the same way Guardian does it, then it wouldn't require Arangoex to be recompiled.
To be specific, I mean moving away from attributes for holding the config values and reading them from a function that calls get_env directly.
def config, do: Application.get_env(:guardian, Guardian)
Thoughts on that?