Разработка экто-запросов на моих моделях схем для поддержки предварительной загрузки

Итак, я пытаюсь получить образец для всех моих моделей экто, имеющих дочерние ассоциации.

В своих контроллерах иногда я хочу загрузить только модель, а иногда я хочу загрузить ее со всеми или некоторыми ассоциациями.

def get_account!(id), do: Repo.get!(Account, id)

У учетной записи есть следующие ассоциации:

has_many :users
belongs_to :company

Что было бы хорошим способом изменить мой get_account! функция, которая дает мне возможность предварительно загрузить ассоциации?

Я не хочу, чтобы этот код предварительной загрузки был в моих контроллерах, мне нравится, когда все мои материалы, связанные с запросами, находятся в самом модуле и не просачиваются в мои контроллеры.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
47
2

Ответы 2

Один из способов сделать это - создать функции with_<association> в вашем контекстном модуле, например:

def get_account!(id), do: Repo.get!(Account, id)

def with_company(%Account{} = account), do: Repo.preload(account, :company)

def with_users(%Account{} = account), do: Repo.preload(account, :users)

поэтому вы можете использовать их в своем контроллере следующим образом:

def show(conn, %{"id" => id}) do
  account = 
    Context.get_account!(id)
    |> Context.with_company
    |> Context.with_users
  render(conn, "show.html", account: account)
end

и у вас есть полностью загруженная учетная запись, доступная в представлении.

Хорошая вещь в этом подходе заключается в том, что вы можете легко расширить его с помощью более конкретных предварительных загрузок, таких как account |> with_most_active_users(10).

Это приводит к нескольким запросам к базе данных (1 основной + количество вызовов Repo.preload), потому что Repo.get!/2 возвращает объект, а не запрос.

Aleksei Matiushkin 19.12.2018 06:36

Я обычно заимствую подход из того, как создаются области видимости Rails. Ecto query принимает в качестве источника другой запрос. Следует вызывать функции семейства Repo.get, фактически выполняя запрос к базе данных, в качестве последнего вызова, когда к запросу добавляются все предварительные загрузки и другие условия.

Итак, вы можете ввести простой шаблонный запрос, например:

defp do_get_account_query(id),
  do: from(a in Account, where: a.id == ^id)

И используйте его во всех своих запросах с Ecto.Repo.one!/2:

def get_account!(id, preloads \\ []) do
  preloads
  Enum.reduce(do_get_account_query(id), fn clause, query ->
    Repo.preload(query, clause)
  end)
  |> Repo.one!()
end

Для более сложных областей действия можно полагаться на универсальную функцию и выводить область действия на ее основе.

Другие вопросы по теме