From f2e4464407cbd63a6d8861d7a695cde01409e81b Mon Sep 17 00:00:00 2001 From: Timothy N. Tsvetkov Date: Mon, 21 Mar 2011 16:44:18 +0300 Subject: [PATCH] Fixes ticket #6290: Except doesn't work in different scopes. --- activerecord/lib/active_record/relation.rb | 5 +++- .../lib/active_record/relation/spawn_methods.rb | 6 +++++ activerecord/test/cases/relation_scoping_test.rb | 21 ++++++++++++++++++++ activerecord/test/models/developer.rb | 5 ++++ 4 files changed, 36 insertions(+), 1 deletions(-) diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 371403f..baf229b 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -15,14 +15,17 @@ module ActiveRecord delegate :table_name, :primary_key, :to => :klass attr_reader :table, :klass, :loaded - attr_accessor :extensions + attr_accessor :extensions, :is_except, :skips alias :loaded? :loaded + alias :is_except? :is_except def initialize(klass, table) @klass, @table = klass, table @implicit_readonly = nil @loaded = false + @is_except = false + @skips = [] SINGLE_VALUE_METHODS.each {|v| instance_variable_set(:"@#{v}_value", nil)} (ASSOCIATION_METHODS + MULTI_VALUE_METHODS).each {|v| instance_variable_set(:"@#{v}_values", [])} diff --git a/activerecord/lib/active_record/relation/spawn_methods.rb b/activerecord/lib/active_record/relation/spawn_methods.rb index 4150e36..686e5cd 100644 --- a/activerecord/lib/active_record/relation/spawn_methods.rb +++ b/activerecord/lib/active_record/relation/spawn_methods.rb @@ -7,6 +7,9 @@ module ActiveRecord return to_a & r if r.is_a?(Array) merged_relation = clone + merged_relation.is_except = false + + merged_relation = self.except(*r.skips) if r.is_except? Relation::ASSOCIATION_METHODS.each do |method| value = r.send(:"#{method}_values") @@ -79,6 +82,9 @@ module ActiveRecord result.send(:"#{method}_value=", send(:"#{method}_value")) end + result.is_except = true + result.skips = skips + result end diff --git a/activerecord/test/cases/relation_scoping_test.rb b/activerecord/test/cases/relation_scoping_test.rb index cda2850..976f26d 100644 --- a/activerecord/test/cases/relation_scoping_test.rb +++ b/activerecord/test/cases/relation_scoping_test.rb @@ -143,6 +143,27 @@ class RelationScopingTest < ActiveRecord::TestCase assert_equal scoped_methods, Developer.send(:current_scoped_methods) end + + def test_except_in_scope_overrides_order_from_other_scope + expected = Developer.order('name DESC').collect { |dev| dev.name } + received = Developer.by_salary.reorder_by_name.collect { |dev| dev.name } + assert_equal expected, received + end + + def test_except_in_scope_overrides_order_from_other_scope_with_lambda + expected = Developer.order('name DESC').collect { |dev| dev.name } + received = Developer.by_salary_with_lambda.reorder_by_name.collect { |dev| dev.name } + assert_equal expected, received + + received = Developer.by_salary.reorder_by_name_with_lambda.collect { |dev| dev.name } + assert_equal expected, received + end + + def test_except_in_scope_overrides_order_from_other_scope_with_lambdas + expected = Developer.order('name DESC').collect { |dev| dev.name } + received = Developer.by_salary_with_lambda.reorder_by_name_with_lambda.collect { |dev| dev.name } + assert_equal expected, received + end end class NestedRelationScopingTest < ActiveRecord::TestCase diff --git a/activerecord/test/models/developer.rb b/activerecord/test/models/developer.rb index 32d060c..09fd5ea 100644 --- a/activerecord/test/models/developer.rb +++ b/activerecord/test/models/developer.rb @@ -45,6 +45,11 @@ class Developer < ActiveRecord::Base scope :jamises, :conditions => {:name => 'Jamis'} + scope :by_salary, order("salary DESC") + scope :by_salary_with_lambda, lambda { order("salary DESC") } + scope :reorder_by_name, except(:order).order("name DESC") + scope :reorder_by_name_with_lambda, lambda { except(:order).order("name DESC") } + validates_inclusion_of :salary, :in => 50000..200000 validates_length_of :name, :within => 3..20 -- 1.7.1