Search code examples
ruby-on-railsperformanceactiverecordpolymorphic-associations

Rails: includes with polymorphic association


I read this interesting article about Using Polymorphism to Make a Better Activity Feed in Rails.

We end up with something like

class Activity < ActiveRecord::Base
  belongs_to :subject, polymorphic: true
end

Now, if two of those subjects are for example:

class Event < ActiveRecord::Base
  has_many :guests
  after_create :create_activities
  has_one :activity, as: :subject, dependent: :destroy 
end

class Image < ActiveRecord::Base
  has_many :tags
  after_create :create_activities
  has_one :activity, as: :subject, dependent: :destroy 
end

With create_activities defined as

def create_activities
  Activity.create(subject: self)
end

And with guests and tags defined as:

class Guest < ActiveRecord::Base
  belongs_to :event
end

class Tag < ActiveRecord::Base
  belongs_to :image
end

If we query the last 20 activities logged, we can do:

Activity.order(created_at: :desc).limit(20)

We have a first N+1 query issue that we can solve with:

Activity.includes(:subject).order(created_at: :desc).limit(20)

But then, when we call guests or tags, we have another N+1 query problem.

What's the proper way to solve that in order to be able to use pagination ?


Solution

  • This will hopefully be fixed in rails 5.0. There is already an issue and a pull request for it.

    https://github.com/rails/rails/pull/17479

    https://github.com/rails/rails/issues/8005

    I have forked rails and applied the patch to 4.2-stable and it works for me. Feel free to use my fork, even though I cannot guarantee to sync with upstream on a regular basis.

    https://github.com/ttosch/rails/tree/4-2-stable