This project is archived and is in readonly mode.

#3233 ✓resolved
Matt D

Query built wrong for preloading associations nested under polymorphic belongs_to

Reported by Matt D | September 19th, 2009 @ 12:36 AM

Relevant model code:

class Subscription < ActiveRecord::Base
  belongs_to :subscribable, :polymorphic => true
end

class Article < ActiveRecord::Base
  has_many :notifications, :as => :notifiable, :dependent => :destroy
  has_many :subscriptions, :as => :subscribable, :dependent => :destroy
end

class Planner < ActiveRecord::Base
  has_many :notifications, :as => :notifiable, :dependent => :destroy
  has_many :subscriptions, :as => :subscribable, :dependent => :destroy
end

class Notification < ActiveRecord::Base
  belongs_to :notifiable, :polymorphic => true
end

As such, the following sample code acts as expected to get all notifications, but is query-heavy:

all_notifications = Subscription.all.inject([]) { |n, s| n + s.notifications }

However, the following seems ideal for reducing query count, but the queries are incorrect:

some_notifications = Subscription.all(:include => {:subscribable => :notifications}).inject([]) { |n, s| n + s.notifications }

That call returns some notifications, but not all the ones the previous call did. Turns out, with test data of 2 articles and 6 planners, the following queries are run:

Notification Load (0.2ms)   SELECT `notifications`.* FROM `notifications` WHERE (`notifications`.`notifiable_id` IN (1,2) and `notifications`.`notifiable_type` = 'Article') 
Notification Load (0.2ms)   SELECT `notifications`.* FROM `notifications` WHERE (`notifications`.`notifiable_id` IN (1,2,3,4,5,6) and `notifications`.`notifiable_type` = 'Article')

As you can see, the notifiable (polymorphic association) class does not change. I'd be tempted to think I'm doing something wrong, except I can't imagine anything I could do that would cause something like that to happen at the very core of ActiveRecord...

The two things about this setup that look like they might cause an issue are the fact that I'm preloading what's nested under a polymorphic association, and that the "middle-man" classes are polymorphic in both directions (they have a polymorphic relationship with both subscriptions, and notifications).

On Rails version 2.3.4, Ruby 1.8.

Comments and changes to this ticket

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2 style="font-size: 14px">Tickets have moved to Github</h2>

The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>

Attachments

Referenced by

Pages