Created
May 18, 2016 11:53
-
-
Save jmglov/ff2a827b2e15fb9c3da8249d916e2415 to your computer and use it in GitHub Desktop.
Elixir: override Mix config with environment variables
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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