elixir-toniq / vapor

Runtime configuration system for Elixir

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Configuring based on the Mix environment

QuinnWilton opened this issue · comments

What's the most idiomatic way of using the Mix environment (dev, prod, test, etc) to configure the application?

For context, I'm using Vapor to perform some lightweight dependency injection, where I can either call out to real external services, or swap out their clients with mock implementations for tests, using code approximately like this:

    providers = [
      %Vapor.Provider.Env{
        bindings: [
          {:mock_backend_services?, "MOCK_SERVICES", default: "true"}
        ]
      }
    ]

    translations = [
      mock_services?: fn s -> Mix.env() == :test or String.downcase(s) == "true" end
    ]

I want to always use my mock implementations in tests, but should be able to control which implementation to use in all other contexts (using environment variables, etc). Obviously that call to Mix.env() doesn't work, because Mix isn't available in releases. Since I'd like to be able to use my real services or my mock services in development, but always use the mock implementations in tests, it would be nice to have that case automatically handled without needing to change any configuration files or environment variables.

I can work around this by defining a configuration provider that pulls from Application.get_env, so that some environments (like test) are able to overwrite other configuration providers.

Is this the most idiomatic way of accomplishing what I want? Would such a configuration provider be worth including in Vapor? If so, I'm happy to clean up what I have and pull request it to the project.

One way that I've gotten around this before is to define a module attribute like @env Mix.env(). You can then use it like so: if @env && @env == :test, do: # stuff.... This is reasonably safe because it'll be set during compilation and should still work in a release.

That's a great idea! That'll definitely work for my use-case, and is preferable to polluting the global application config.

Thank you!

closing this for now.