When scoped collections are used as a value for some attribute
in :conditions clause, the generated SQL contains "attribute IN (
... )" clause, where "( ... )" is enumeration of values of scoped
collection. To do that an extra SQL clause is executed to get items
of scoped collection. But in fact scoped collection can be inserted
as a sub-SELECT.
Example:
@@@ ruby
class PaymentType < AR::Base
named_scope :credit_cards, :conditions => { :credit_card => true }
end
Orders.all(:conditions => { :payment_type_id => PaymentType.credit_cards })
@@@
This could be translated into a single query:
@@@ sql
SELECT * from `orders` WHERE payment_type_id IN (SELECT id FROM `payment_types` WHERE credit_card = 1)
@@@
Solution:
Specially treat AR::NamedScope::Scope values in
AR::Base#quote_bound_value
@@@ ruby
def quote_bound_value(value) #:nodoc:
if ActiveRecord::NamedScope::Scope === value
scope = value.scope(:find) || {}
field = (scope[:select] || value.primary_key).to_s.split(/,/).first.strip
return value.construct_finder_sql(:select => field)
end
...
@@@
This patch allows
1. Select #primary_key attribute by default.
2. If :select option is present, use first attribute specified.
If for some reason scoped collection should be embedded as
enumeration, one can e.g. instantiate it manually (by calling #all
or #to_a).