#elixir #phoenix-framework #dry
#elixir #phoenix-framework #dry
Вопрос:
Мне нужно настроить протокол OAuth, и логичное место для этого находится внутри /config/dev.exs
, не так ли?
Прямо выше я настраиваю Endpoint
. Итак, в моем приложении я могу написать Project.Endpoint.static_url()
и получить, например. http://localhost:4000
.
Каким был бы ПРОСТОЙ способ получить это значение в конфигурации?
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:
Прежде всего, вы должны знать, что 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
, но тогда вам нужно позаботиться об объединении значений самостоятельно.
Комментарии:
1. Отличный ответ! Это действительно продвинуло меня на шаг вперед в Elixir / Phoenix. 🙂