如何在Elixir中基于命令行args加载配置文件

时间:2018-09-11 05:36:48

标签: elixir

如何使用提供的命令行标志覆盖Elixir中的配置?例如,通过运行以下命令来启动应用程序:

./my_app --mode=mode1 or ./my_app --mode=mode2

根据提供的模式,我想用config.exsmode1.exs覆盖mode2.exs,如下所示

use Mix.Config

# Configures the endpoint
config :my_app,
  env: Mix.env

import_config "#{Mix.env}.exs"
import_config "mode1.exs" or import_config "mode2.exs"

3 个答案:

答案 0 :(得分:2)

在编译时使用Env变量

基于不同的命令行参数具有不同配置的问题是Elixir应用程序已编译,因此打包该应用程序后,它将仅包含在编译时指定的模式的配置。

如果这不是问题,并且您仍要使用单独的配置,则最好使用环境变量而不是命令行标志。

use Mix.Config

# Get the Application Mode
default_mode = "1"
app_mode = System.get_env("APP_MODE") || default_mode
mode_config = "mode#{app_mode}.exs"

# Load external configs
import_config("#{Mix.env}.exs")
import_config(mode_config)

现在只需通过环境变量传递模式:

$ APP_MODE=1 mix run

答案 1 :(得分:0)

动态切换配置

就像我在其他答案中提到的那样,Elixir应用程序已编译,因此一旦打包应用程序,它将仅包含该模式的配置。更好的解决方案是将所有模式的配置保持在一起,并在应用程序中动态加载适当的配置。

您的config.exs文件如下所示:

use Mix.Config

config :my_app, :app_modes,
  default: :mode_1

config :my_app, :mode_1,
  x: 1, y: 2, z: 3

config :my_app, :mode_2,
  x: 6, y: 7, z: 8

您可以使用自定义的ModeConfig模块来加载模式配置:

defmodule MyApp.ModeConfig do
  @default_mode Application.get_env(:my_app, :app_modes)[:default_mode]

  # Get App Mode
  def mode do
    passed_mode = System.get_env("APP_MODE")
    # or you can use OptionParser for command-line flags

    String.to_atom(passed_mode) || @default_mode
  end

  def get,      do: Application.get_env(:my_app, mode())
  def get(key), do: get()[key]
end

您现在可以通过两种方式设置(和获取)模式:

使用自定义配置模块可以加载适当的配置:

# App started in Mode 2
MyApp.ModeConfig.get(:x)       # => 6

# App started in Mode 1
MyApp.ModeConfig.get(:y)       # => 2

注意::如果您的应用程序变得更加复杂(OTP和进程),则您甚至可以拥有与每种模式相对应的不同“适配器”,并在启动时切换到适当的模式。应用程序监督树。

答案 2 :(得分:0)

要解析命令行参数,请使用OptionParser

要覆盖配置文件中的值,应使用Application.put_env/4,因为配置文件是在编译时加载和处理的,而在编译期间甚至是Mix.Config,整个Mix应用程序在生产中不存在。因此,无论您选择这种方法,都是将mix应用程序引入prod(不推荐使用,强烈建议不要这样做),或者自己解析modeN文件并手动更新应用程序环境。< / p>

该主题在Elixir社区中已经largely discussed,并且核心团队非常了解使用编译时配置的弊端。

目前最好的解决方案(直到有适当的解决方案为止)是使用系统环境而不是配置和/或引入自己的JSON / YAML配置。