Яркие ассоциации загрузки с активными сериализаторами модели

Фон

У меня есть приложение rails с глубоко вложенными ассоциациями.

                          .-< WorkPeriod
Timecard -< Week -< Day -<--< Subtotal
                          `-< Adjustment

-<  (has many)

Я использую Active Serializer для создания API.

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

В настоящее время мои сериализаторы выглядят так:

class TimecardSerializer < ActiveModel::Serializer
  embed :ids, include: true
  has_many :weeks
end
class WeekSerializer < ActiveModel::Serializer
  embed :ids, include: true
  has_many :days
end
# ... etc ...

Проблема

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

Ответы

Ответ 1

Одним из решений является определение вашего собственного метода weeks на TimecardSerializer. Оттуда вы можете .includes() создать все ассоциации, которые вы хотите получить.

class TimecardSerializer < ActiveModel::Serializer
  embed :ids, include: true
  has_many :weeks

  def weeks
    object.weeks.includes(days: [:sub_totals, :work_periods, :adjustments])
  end
end

Все запросы будут отображаться в журнале, но большинство из них будет кэшированным, а не реальным.

Ответ 2

У меня была аналогичная проблема. Я исправил его в своем контроллере. Мне нравится идея поместить его в сериализатор, но наличие в контроллере проблемы n + 1 недели, созданной ArraySerializer тоже.

Timecard.find(params[:id]).includes(weeks: [{ days: [:sub_totals, :work_periods, :adjustments] }])

и

Timecard.includes(weeks: [{ days: [:sub_totals, :work_periods, :adjustments] }])

должен теперь получать нагрузку и ограничивать запрос только шестью ударами db.