Яркие ассоциации загрузки с активными сериализаторами модели
Фон
У меня есть приложение 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.