diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 157716a..8017233 100755 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -1623,12 +1623,13 @@ module ActiveRecord end def construct_finder_sql_for_association_limiting(options, join_dependency) - scope = scope(:find) + scope = scope(:find) # 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 + tables_from_conditions = conditions_tables(options) + tables_from_order = order_tables(options) + tables_from_joins = join_dependency.join_associations_aliased_table_names + all_tables = tables_from_conditions + tables_from_order + tables_from_joins distinct_join_associations = all_tables.uniq.map{|table| join_dependency.joins_for_table_name(table) }.flatten.compact.uniq @@ -1638,7 +1639,7 @@ module ActiveRecord order = order ? "#{order}, #{scoped_order}" : scoped_order end - is_distinct = !options[:joins].blank? || include_eager_conditions?(options, tables_from_conditions) || include_eager_order?(options, tables_from_order) + is_distinct = !options[:joins].blank? || !tables_from_joins.blank? || include_eager_conditions?(options, tables_from_conditions) || include_eager_order?(options, tables_from_order) sql = "SELECT " if is_distinct sql << connection.distinct("#{connection.quote_table_name table_name}.#{primary_key}", order) @@ -1708,6 +1709,10 @@ module ActiveRecord tables_in_string(select) end + def includes_tables(join_dependency) + join_dependency.join_associations.collect{|join| join.aliased_join_table_name } + end + def joined_tables(options) scope = scope(:find) joins = options[:joins] @@ -1865,6 +1870,10 @@ module ActiveRecord result end + def join_associations_aliased_table_names + join_associations.collect{ |join| join.aliased_join_table_name } + end + protected def build(associations, parent = nil) parent ||= @joins.last diff --git a/activerecord/lib/active_record/calculations.rb b/activerecord/lib/active_record/calculations.rb index 727f4c1..cfc8e65 100644 --- a/activerecord/lib/active_record/calculations.rb +++ b/activerecord/lib/active_record/calculations.rb @@ -213,6 +213,7 @@ module ActiveRecord sql << joins unless joins.blank? add_conditions!(sql, options[:conditions], scope) + add_limited_ids_condition!(sql, options, join_dependency) if join_dependency && !using_limitable_reflections?(join_dependency.reflections) && ((scope && scope[:limit]) || options[:limit]) if options[:group] diff --git a/activerecord/test/cases/named_scope_test.rb b/activerecord/test/cases/named_scope_test.rb index 92fe48c..c74ef8d 100644 --- a/activerecord/test/cases/named_scope_test.rb +++ b/activerecord/test/cases/named_scope_test.rb @@ -2,13 +2,14 @@ require "cases/helper" require 'active_support/core_ext/array/random_access' require 'models/post' require 'models/topic' +require 'models/category' require 'models/comment' require 'models/reply' require 'models/author' require 'models/developer' class NamedScopeTest < ActiveRecord::TestCase - fixtures :posts, :authors, :topics, :comments, :author_addresses + fixtures :posts, :authors, :topics, :categories, :categories_posts, :comments, :author_addresses def test_implements_enumerable assert !Topic.find(:all).empty? @@ -156,6 +157,10 @@ class NamedScopeTest < ActiveRecord::TestCase assert_not_equal Post.top(5), authors(:david).posts.top(5) assert_equal authors(:david).posts.ranked_by_comments.limit(5), authors(:david).posts.top(5) assert_equal Post.ranked_by_comments.limit(5), Post.top(5) + + assert_equal Category.first.posts.limit(4).count, 4 + assert_equal Category.first.posts.including_special_categories.order_by("id desc").count, 4 + assert_equal Category.first.posts.including_special_categories.limit(3).count, 3 end def test_active_records_have_scope_named__all__ diff --git a/activerecord/test/models/post.rb b/activerecord/test/models/post.rb index 374e536..bcf0a26 100644 --- a/activerecord/test/models/post.rb +++ b/activerecord/test/models/post.rb @@ -2,6 +2,8 @@ class Post < ActiveRecord::Base named_scope :containing_the_letter_a, :conditions => "body LIKE '%a%'" named_scope :ranked_by_comments, :order => "comments_count DESC" named_scope :limit, lambda {|limit| {:limit => limit} } + named_scope :order_by, lambda {|order| {:order => order} } + named_scope :including_special_categories, :include => :special_categories named_scope :with_authors_at_address, lambda { |address| { :conditions => [ 'authors.author_address_id = ?', address.id ], :joins => 'JOIN authors ON authors.id = posts.author_id'