在配置文件中调用Project.Endpoint.static_url()

时间:2019-03-28 15:17:39

标签: elixir phoenix-framework dry

我需要配置OAuth协议,这样做的逻辑位置是在/config/dev.exs之内,是吗?

在上方,我配置了Endpoint。因此,在我的应用中,我可以编写Project.Endpoint.static_url()并获取例如。 http://localhost:4000

在配置中获取此值的DRY方法是什么?

config :project, Project.Endpoint,
  http: [port: 4000],
  url: [scheme: "http", host: "localhost", port: 4000]

config :project, authentication: [
    client_id: System.get_env("CLIENT_ID"),
    client_secret: System.get_env("CLIENT_SECRET"),
    site: "https://example.com",
    authorize_url: "/connexion/oauth2/authorize",
    redirect_uri: "http://localhost:4000/oauth/callback"
    # This version fails: Project.Endpoint.static_url/0 is undefined (module Project.Endpoint is not available)
    # redirect_uri: "#{Project.Endpoint.static_url()}/oauth/callback"
  ]

谢谢

1 个答案:

答案 0 :(得分:1)

首先,您应该知道Elixir将在编译时解析配置文件,这意味着System.get_env将在编译应用程序时进行评估。在已编译的代码中,值将是固定的。

Elixir团队正在努力简化此过程,但是目前建议的解决方法是将环境变量的读取推迟到应用程序启动之前。

通常,这可以在应用程序模块中通过调用Application.put_env/3-4并放入从System.get_env读取的值来启动子级之前完成。

诸如Ecto之类的某些库还提供init回调,使您可以进入引导过程进行动态配置。参见https://hexdocs.pm/ecto/Ecto.Repo.html#module-urls

这也将是摆脱重复的地方。毕竟,配置只是Elixir代码,您可以根据需要简单地基于其他值设置值:

defmodule Project.Application do
  use Application

  def start(_type, _args) do
    Application.put_env :project, authentication: [
      redirect_uri: "#{Project.Endpoint.static_url()}/oauth/callback",
      ...
    ]

    children = [
      Project.Repo,
      ProjectWeb.Endpoint,
      ...
    ]
    opts = [strategy: :one_for_one, name: Project.Supervisor]
    Supervisor.start_link(children, opts)
  end
end

您还可以同时对配置文件和Application.put_env进行混合匹配,但是您需要自己合并这些值。