pigusan
pigusan

Reputation: 99

How to query polymorphic associations when I have to join another table on the polymorphic association?

Given assessments and messages sent by a member, I'd like to find all the logs associated to a member with a specific email. I am running into issues joining polymorphic associations EagerLoadPolymorphicError Cannot eagerly load the polymorphic association . I assume I should join Log with the consumer association and then add a conditional for the members email.

I am using Rails 6.0.3.7

My models are the following:

class Assessment
    belongs_to :member, foreign_key: 'sender_id'
    has_one :log, as: :consumer
end

class Message
    belongs_to :member, foreign_key: 'sender_id'
    has_one :log, as: :consumer
end

class Log

   belongs_to :consumer, polymorphic: true
end

class Member
   has_many :assessments
   has_many :messages
end  

I have tried various forms of the following:

Log.joins(consumer: :member).where(members: {email: '[email protected]'})
#ActiveRecord::EagerLoadPolymorphicError (Cannot eagerly load the polymorphic association :consumer)

I then thought perhaps I could do a belongs_to :through but apparently that's no good either belongs_to through associations. Is what I am trying to do even possible?

Upvotes: 0

Views: 1577

Answers (2)

Mosaaleb
Mosaaleb

Reputation: 1089

Since there is no table called consumer, joins will fail on this. To solve this problem you can write a custom join.

Try this:

member = Member.find_by(email: '[email protected]')
Log.joins("LEFT JOIN messages ON (messages.id = logs.consumer_id AND consumer_type='Message')")
   .joins("LEFT JOIN assessments ON (assessments.id = logs.consumer_id AND consumer_type='Assessment')")
   .where('messages.member_id = ? or assessments.member_id = ?', member.id, member.id)

You can nested joins as well to join with members table, notice the AS in the second nested join:

Log.joins("LEFT JOIN messages ON (messages.id = logs.consumer_id AND consumer_type='Message')")
   .joins("LEFT JOIN assessments ON (assessments.id = logs.consumer_id AND consumer_type='Assessment')")
   .joins('LEFT JOIN members ON members.id = messages.member_id')
   .joins('LEFT JOIN members AS mmbrs ON mmbrs.id = assessments.member_id')
   .where('members.email = ? OR mmbrs.email = ?', 
          '[email protected]', '[email protected]')

Upvotes: 1

Joel Blum
Joel Blum

Reputation: 7878

You can try using includes which perhaps can deal with polymorphic associations. Joins actually looks for a consumers table which doesn't exist.

Log.includes(consumer: :member).where(members: {email: '[email protected]'})

Upvotes: 0

Related Questions