From d4da07d735493e714f1b59b7bae831c7e349ee14 Mon Sep 17 00:00:00 2001 From: Timothy N. Tsvetkov Date: Sat, 15 Jan 2011 03:50:55 +0300 Subject: [PATCH] Fixes ticket #6290: Except doesn't work in different scopes. --- .../test/fixtures/layout_tests/layouts/symlinked | 1 - activerecord/lib/active_record/relation.rb | 7 ++++++- .../lib/active_record/relation/spawn_methods.rb | 6 ++++++ activerecord/test/cases/relation_scoping_test.rb | 12 ++++++++++++ activerecord/test/models/developer.rb | 4 ++++ 5 files changed, 28 insertions(+), 2 deletions(-) delete mode 120000 actionpack/test/fixtures/layout_tests/layouts/symlinked diff --git a/actionpack/test/fixtures/layout_tests/layouts/symlinked b/actionpack/test/fixtures/layout_tests/layouts/symlinked deleted file mode 120000 index 0ddc115..0000000 --- a/actionpack/test/fixtures/layout_tests/layouts/symlinked +++ /dev/null @@ -1 +0,0 @@ -../../symlink_parent \ No newline at end of file diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 1441e97..e8a3e1c 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -15,14 +15,19 @@ module ActiveRecord delegate :table_name, :primary_key, :to => :klass attr_reader :table, :klass, :loaded - attr_accessor :extensions + attr_accessor :extensions, :is_except, :skips, :is_default_scope alias :loaded? :loaded + alias :is_except? :is_except + alias :is_default_scope? :is_default_scope def initialize(klass, table) @klass, @table = klass, table @implicit_readonly = nil @loaded = false + @is_except = false + @skips = [] + @is_default_scope = false 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 db5f1af..ba9f5b9 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") @@ -74,6 +77,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 1bdf313..6ce418d 100644 --- a/activerecord/test/cases/relation_scoping_test.rb +++ b/activerecord/test/cases/relation_scoping_test.rb @@ -143,6 +143,18 @@ 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 + end end class NestedRelationScopingTest < ActiveRecord::TestCase diff --git a/activerecord/test/models/developer.rb b/activerecord/test/models/developer.rb index 32d060c..db34c1a 100644 --- a/activerecord/test/models/developer.rb +++ b/activerecord/test/models/developer.rb @@ -45,6 +45,10 @@ 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") + validates_inclusion_of :salary, :in => 50000..200000 validates_length_of :name, :within => 3..20 -- 1.7.1