THpubs
THpubs

Reputation: 8162

In Rails, How to Eager Load an Association only if the Association is not nil?

Im trying to use the public_activity gem to create an activity log. When I load the activities of a specific user, I use the following command :

@activity = PublicActivity::Activity.order("created_at desc").where(owner_id: @awardleader.authentication.id).includes(:trackable, trackable: :awardunit)

In here, the awardunit association won't be there all the time. Since Im tracking several models, sometimes the tracked model doesn't have an awardunit. So, how can we eager load the association only if its available?

PS : I want to get All activities... In that list, there can be activities from different models. Some models doesn't have Awardunit as association. So, the above code gives an error saying no Awardunit for that model!

PS : If I use the code I showed in my question, it gives me an error like this "Association named 'awardunit' was not found on Gold; perhaps you misspelled it?". The problem is I can't remove loading award_unit because some trackables have awardunit

Upvotes: 2

Views: 1501

Answers (1)

janfoeh
janfoeh

Reputation: 10328

Including a polymorphic association, as in

PublicActivity::Activity.includes(:trackable)

will return

  1. all activities, whether they have a trackable associated or not. If there is no trackable, simply nothing else will be loaded.
  2. include any kind of trackable that is present, regardless of its type

It does that by producing a LEFT OUTER JOIN for the database.

Declaring an association to be polymorphic, as in

class PublicActivity::Activity < ActiveRecord::Base
  belongs_to :trackable, polymorphic: true
end

adds two columns to your activities database table, trackables_type and trackables_id. You can use these in your queries.

If you want to get only activities that have any kind of trackable associated, use

PublicActivity::Activity.includes(:trackable).where.not(trackable_type: nil)

If you want to get only activities that have an AwardUnit associated to them, use

PublicActivity::Activity.includes(:trackable).where(trackable_type: :award_unit)

Upvotes: 2

Related Questions