Eager load associations with Active Model Serializers

Ryan picture Ryan · Aug 8, 2013 · Viewed 7.5k times · Source

Background

I have a rails application with deeply nested associations.

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

-<  (has many)

I'm using Active Model Serializer to build out the API.

On the client side I want to load a timecard and all it's associations in one shot.

Currently my serializers look like this,

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 ...

Problem

This all works find, except nothing gets eager-loaded. So it ends up making lots of calls to the database for each request. For each week, it makes a separate request for the days in that week. And for each day, it makes a separate request for it's work_periods, subtotals, and adjustments.

Answer

Ryan picture Ryan · Aug 8, 2013

One solution is to define your own weeks method on the TimecardSerializer. From there you can .includes() all the associations you want to eager load.

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

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

All the queries will still show up in the log but most will be a cached query instead of a real one.