I recently had a problem (on Rails 4.1.2) trying to join on a polymorphic association where the polymorphic type was known ahead of time.
class EmailLog < ActiveRecord::Base
belongs_to :related_object
end
I had a query like this:
EmailLog.where(related_object_type: “FooBar”).joins(:related_object)
This fails because the related_object_type
in the where
doesn’t seem to carry through to the joins
, and since related_object
is a polymorphic association, it complains.
EmailLog.joins(:related_object).to_sql
ActiveRecord::EagerLoadPolymorphicError: Cannot eagerly load the polymorphic association :related_object
EmailLog.where(related_object_type: “FooBar”).joins(:related_object)
ActiveRecord::EagerLoadPolymorphicError: Cannot eagerly load the polymorphic association :related_object
I then discovered that there’s actually a way around this problem by specifying a relationship that piggy-backs on related_object
:
belongs_to :foo_bar, → { where(email_logs: { related_object_type: “FooBar” }) }, foreign_key: “related_object_id”
This is joins
able:
EmailLog.joins(:foo_bar).to_sql
#=> “SELECT email_logs
.* FROM email_logs
INNER JOIN foo_bars
ON foo_bars
.id
= email_logs
.related_object_id
AND email_logs
.related_object_type
= ‘FooBar’”
It would be nice if the where(related_object_type: "FooBar")
information could be carried forward to the joins
call automatically, so that the original attempted query could work. I had originally thought that maybe a syntax like this would be useful:
EmailLog.joins(related_object: :foo_bar)
But then I realised that this obviously conflicts with the existing syntax for nested joins. I’m sure there’s something expressive that would be equivalent to defining the belongs_to :foo_bar
and using EmailLog.joins(:foo_bar)
, though.
I’m not sure how possible this actually is. I also have no clue how to even start, otherwise I’d PR it!