Иногда конфигурация кажется специфической для модуля, например, у MyApp.Endpoint ниже.
Это просто разбивает конфигурацию на разделы вроде?
tldr;
Да.С помощью вашего конфигурационного файла вы создаете что-то вроде этого:
[
{:ecto_repos, [MyApp.Repo]},
{.Repo,
[
username: "postgres",
password: "postgres",
database: "myapp_dev",
hostname: "localhost",
pool_size: 10
]},
{:http, [port: 4000]}, <===**** HERE ****
{:included_applications, []},
{MyAppWeb.Endpoint, <====**** HERE ****
[
url: [host: "localhost"],
secret_key_base: "rchq5yMDPqqEBzFR+wIoqpc+kNquiyNDYUp/K8aF2Yj6POl/gjfj0H0rljE06LI5",
render_errors: [view: MyAppWeb.ErrorView, accepts: ["html", "json"]],
pubsub: [name: Rum.PubSub, adapter: Phoenix.PubSub.PG2],
http: [port: 4000],
debug_errors: true,
code_reloader: true,
check_origin: false,
watchers: [
node: [
"node_modules/webpack/bin/webpack.js",
"--mode",
"development",
"--watch-stdin",
{:cd, "/Users/7stud/phoenix_apps/book/myapp/assets"}
]
],
live_reload: [
patterns: [~r/priv\/static\/.*(js|css|png|jpeg|jpg|gif|svg)$/,
~r/priv\/gettext\/.*(po)$/, ~r/lib\/myapp_web\/views\/.*(ex)$/,
~r/lib\/myapp_web\/templates\/.*(eex)$/]
]
]},
Как мне ссылаться на порт http, как показано ниже в моем коде, если мне это тоже нужно?
config :myapp, MyApp.Endpoint,
http: [port: 4000],
debug_errors: true
Если вы посмотрите на этот раздел конфигурации и удалите символы новой строки, вы получите:
config :myapp, MyApp.Endpoint, http: [port: 4000], debug_errors: true
И, если вы добавите несколько скобок, вы получите:
config(:myapp, MyApp.Endpoint, http: [port: 4000], debug_errors: true)
Этовызов функции, где первый аргумент :myapp
, второй аргумент MyApp.Endpoint
, а затем эта часть:
http: [port: 4000], debug_errors: true
является Keyword list
.Отступив на мгновение ... в эликсире вы можете определить функции следующим образом:
def go(x, y, z) do
IO.puts x
IO.puts y
IO.inspect z
end
и вызывать их следующим образом:
My.go(10, 20, a: 1, b: 2)
, что выдаст:
10
20
[a: 1, b: 2]
Это показывает, что если последние аргументы в вызове функции имеют определенный синтаксис, то все последние аргументы будут собраны в нечто, называемое Keyword list
, и переданы функции в качестве одного аргумента.Таким образом, несмотря на то, что, похоже, вы вызываете My.go()
с четырьмя аргументами, вы действительно вызываете его с тремя аргументами.
В результате этот вызов функции:
config(:myapp, MyApp.Endpoint, http: [port: 4000], debug_errors: true)
вызывает определение функции config/3
.
Почему вы можете вызывать функцию config/3
, если такая функция не определена в файле конфигурации?Эта строка:
use Mix.Config
вставляет определение функции config/3
в файл.Это проблема с эликсиром: происходит много волшебных вещей, которые затрудняют выяснение, откуда берутся определения функций.
На данный момент вы знаете, что функция config/3
выполняетсявызывается в файле конфигурации:
config :myapp, MyApp.Endpoint,
http: [port: 4000],
debug_errors: true
Кроме того, строка use Mix.Config
в верхней части файла конфигурации является подсказкой, что config/3
может быть определено в этом модуле, так что вы можете просмотреть Mix.Config docs .Конечно же, есть функция config/3
, которая описана в документации.В документах также описана функция config/2
, которая вызывается здесь:
config :myapp,
http: 4000
Если вы читаете документы для config/2
, то, кажется, довольно легко понять, как все работает: когда вы устанавливаете ключи изначения с config/2
, вы можете получить определенное значение, связанное с ключом, вызвав:
Application.get_env(:myapp, key)
Например,
Application.get_env(:myapp, :http)
#=> 4000
Однако, когда вы устанавливаете ключи и значения с помощью config/3
, вы не можете получить конкретное значение, связанное с ключом - вместо этого вы в конечном итоге получаете полный список пар ключ / значение:
keyword_list = Application.get_env(:myapp, module)
config/3
создает вложенную структуру, где модуль являетсяkey и его значение - это список ключевых слов, составленный из пар ключ / значение, которые вы указываете в файле конфигурации, например:
http: [port: 4000],
debug_errors: true
Еще один способ обдумать это, подумав о вложенной карте:
%{
myapp: %{
http: 4000, #<== config/2
my_app_endpoint: %{http: [port: 4000, debug_errors: true]} #<== config/3
}
... и Application.get_env()
позволяет указывать только два ключа, например:
Application.get_env(:myapp, :http) #=> 4000
или:
Application.get_env(:myapp, :my_app_endpoint) #=> %{http: [port: 4000, debug_errors: true]}
После получениясписок ключевых слов:
keyword_list = Application.get_env(:myapp, module)
тогда вы должны использовать свой гензнание elixir для извлечения значения, связанного с определенным ключом, из списка ключевых слов:
all = Application.get_all_env(:myapp)
IO.inspect all #=> lots of stuff (which is not a keyword list)
keyword_list = Application.get_env(:myapp, MyApp.Endpoint)
IO.inspect keyword_list #=> a keyword list with lots of key/value pairs
http = Keyword.get(keyword_list, :http)
IO.inspect http #=> [port: 4000]
port = Keyword.get(http_keyword_list, :port)
IO.inspect port #=>4000