1.9.2 / Polymorphic has_many / calling .size

Group
has_many :topics, :as => :discussable (via a module)

Topic
belongs_to :discussable, :polymorphic => true
named_scope :unhidden, { :conditions => [‘hidden = ?’, false] }

Under rails 1.9.2 without the named_scope this works properly:

reload! ; Group.find(56).topics.size
Reloading…
…snip show tables etc…
Group Load (12.8ms) SELECT * FROM groups WHERE (groups.id =

Topic Columns (13.6ms) SHOW FIELDS FROM topics
SQL (81.7ms) SELECT count(*) AS count_all FROM topics WHERE
(topics.discussable_id = 56 AND topics.discussable_type = ‘Group’)

However with the named scope in there:

reload! ; Group.find(56).topics.unhidden.size
Group Load (14.3ms) SELECT * FROM groups WHERE (groups.id =

Topic Load (40.1ms) SELECT * FROM topics WHERE
(topics.discussable_id = 56 AND topics.discussable_type = ‘Group’) *
Topic Columns (13.5ms) SHOW FIELDS FROM topics
SQL (11.8ms) SELECT count(
) AS count_all FROM topics WHERE
(((hidden
= 0) AND (topics.discussable_id = 56 AND topics.discussable_type =
‘Group’)) AND (topics.discussable_id = 56 AND
topics.discussable_type =
‘Group’))

So the problem is under the seond one, it selects all the topics and
then
does select count(*).

Under rails 1.9.1p243 this worked correctly in both cases.

Any ideas?

Stephen wrote in post #955565:

Group
has_many :topics, :as => :discussable (via a module)

Topic
belongs_to :discussable, :polymorphic => true
named_scope :unhidden, { :conditions => [‘hidden = ?’, false] }

Under rails 1.9.2
[…]

There is no such version. Do you mean Ruby 1.9.2? And with what
version of Rails?

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]

Yes yes, thats what I meant =) Ruby 1.9.2 and Rails 2.3.9 it causes a
double query. Under Ruby 1.9.1p243 and Rails 2.3.9 it correctly only
does the count query.

I found a bug for it in Lighthouse although no solutions…
https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/5410-multiple-database-queries-when-chaining-named-scopes-with-rails-238-and-ruby-192#ticket-5410-2

Here’s the problem.

1.9.2 defines a new way of handling method_missing/responds_to
responds_to_missing?

This seems to get called automatically and triggers the method_missing
in
association_collection.

AssociationCollection calls “super” in method and passes it to
AssociationProxy which also triggers method_missing…

The first line of method_missing in AssociationProxy is load_target
which
causes the extra DB load…

This is a workaround:

— a/association_collection.rb 2010-10-20 13:22:58.629947001 -0400
+++ b/association_collection.rb 2010-10-20 13:22:54.509947004 -0400
@@ -390,7 +390,7 @@
if block_given?
super { |*block_args| yield(*block_args) }
else

  •          super
    
  •          super unless method.to_s == "respond_to_missing?"
           end
         elsif @reflection.klass.scopes.include?(method)
           @reflection.klass.scopes[method].call(self, *args)