Skip to content

Instantly share code, notes, and snippets.

@jmglov
Created May 18, 2016 11:53
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save jmglov/ff2a827b2e15fb9c3da8249d916e2415 to your computer and use it in GitHub Desktop.
Save jmglov/ff2a827b2e15fb9c3da8249d916e2415 to your computer and use it in GitHub Desktop.
Elixir: override Mix config with environment variables
defmodule Config do
defmacro __using__(_) do
quote do
import unquote(__MODULE__), only: :macros
end
end
defmacro cfg(key, type \\ :string) do
quote do
defp unquote(key)() do
unquote(__MODULE__).get(__MODULE__, unquote(key), unquote(type))
end
end
end
@app_name :my_app
def get(module, key, type \\ :string) do
case System.get_env(env_var(module, key)) do
nil -> Application.get_env(@app_name, module)[key]
str -> parse_val(str, type)
end
end
def get_all do
Application.get_all_env(@app_name)
|> Enum.map(fn {module, _} -> {module_name(module), get_module(module)} end)
|> Enum.into(Map.new)
end
def get_module(module) do
Application.get_env(@app_name, module)
|> Enum.map(fn {key, _} -> {key, get(module, key)} end)
|> Enum.into(Map.new)
end
defp env_var(module, key) do
String.upcase "#{stringify module}_#{stringify key}"
end
defp module_name(module) do
module
|> to_string
|> String.replace_leading("Elixir.", "")
end
defp stringify(atom) do
atom
|> module_name
|> String.replace(".", "_")
|> String.replace_trailing("?", "")
end
defp parse_val(str, type) do
fun =
case type do
:atom -> &String.to_atom/1
:boolean -> &to_boolean/1
:float -> &String.to_float/1
:integer -> &String.to_integer/1
{:list, element_type} -> &to_list(&1, element_type)
{:set, element_type} -> &to_set(&1, element_type)
:string -> &(&1)
end
fun.(str)
end
defp to_boolean(str) do
String.downcase(str) == "true"
end
defp to_list(str, element_type) do
str |> String.split(",") |> Enum.map(&parse_val(&1, element_type))
end
defp to_set(str, element_type) do
str |> to_list(element_type) |> MapSet.new
end
end
@seeekr
Copy link

seeekr commented Aug 14, 2017

Enhanced yours so one doesn't have to edit config.ex in order to change the app that is being configured. Renamed to "confix.ex" as well as the module, because there's already a "config.ex" in my (and everyone's) project. Put usage code in a new file into same gist so it's all in one place. Cheers, thanks for making this!

https://gist.github.com/seeekr/9f781ee081836e081638df209ac60928

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment