Путаница с использованием оператора pin (^) - PullRequest
2 голосов
/ 07 марта 2020

Я смотрю на некоторый код Elixir, который выглядит следующим образом:

  @to_preload [
    :last_modified_by,
    change_request: [application: [:app_definition]],
    comments: [:user]
  ]

  def preload(query) do
    preload(query, ^@to_preload)
  end

Я считаю, что вызов preload(query, ^@to_preload) на самом деле для макроса Query.preload / 3 как файл имеет import Ecto.Query.

Так что мой вопрос, что именно ^ делает перед атрибутом модуля @to_preload в этом вызове?

1 Ответ

3 голосов
/ 07 марта 2020

Ты прав. preload имеется в виду Ecto.Query.preload/3. Из документов Ecto:

При написании запроса вы находитесь в синтаксисе запроса Ecto. Чтобы получить доступ к значениям параметров или вызвать функции Elixir, вам нужно использовать оператор ^, который перегружен Ecto

. Именно поэтому используется оператор вывода (^). Вы должны использовать его для интерполяции атрибута модуля.

Если бы вы написали запрос без использования оператора pin, вы получили бы следующую ошибку:

** (Ecto.Query.CompileError) `@to_preload` is not a valid preload expression.
preload expects an atom, a list of atoms or a keyword list with more preloads as
values. Use ^ on the outermost preload to interpolate a value

Так код, которым вы поделились, будет эквивалентен:

def preload(query) do
  preload(query, [
    :last_modified_by,
    change_request: [application: [:app_definition]],
    comments: [:user]
  ])
end

На самом деле пример в документации предварительной загрузки использует оператор pin. Может быть странно, что определяемая функция также называется preload. Однако из-за хитрости нет путаницы, так как предварительная загрузка Ecto.Query может принимать 2 или 3 аргумента, в то время как определенный здесь принимает только 1.

...