I found this bug while writing my pagination plugin that uses named scopes. It's caused by an oversight in construct_finder_sql_for_association_limiting and manifests when the following three conditions are met:
- there is a has_many association being eager loaded
- the query is being limited
- there is order specified by a named scope
I fixed the bug by making modifications to construct_finder_sql_for_association_limiting. You can apply the fix by including the following code into your Rails project:
scope = scope(:find) || {}
order = [options[:order], scope[:order]].compact.join(', ')
# Only join tables referenced in order or conditions since this is particularly slow on the pre-query.
tables_from_conditions = conditions_tables(options)
tables_from_order = order_tables(options)
all_tables = tables_from_conditions + tables_from_order
distinct_join_associations = all_tables.uniq.map{|table|
join_dependency.joins_for_table_name(table)
}.flatten.compact.uniq
is_distinct = !options[:joins].blank? || include_eager_conditions?(options, tables_from_conditions) || include_eager_order?(options, tables_from_order)
sql = "SELECT "
if is_distinct
sql << connection.distinct(".", order)
else
sql << primary_key
end
sql << " FROM "
if is_distinct
sql << distinct_join_associations.collect(&:association_join).join
add_joins!(sql, options, scope)
end
add_conditions!(sql, options[:conditions], scope)
add_group!(sql, options[:group], scope)
if order and is_distinct
connection.add_order_by_for_association_limiting!(sql, :order => order)
else
add_order!(sql, options[:order], scope)
end
add_limit!(sql, options, scope)
return sanitize_sql(sql)
end
end
end
end
If you are curious about what exactly was changed, see this diff pastie.