Created
September 5, 2010 22:13
-
-
Save spastorino/566374 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb | |
index c3a34ae..14f166b 100644 | |
--- a/activerecord/lib/active_record/base.rb | |
+++ b/activerecord/lib/active_record/base.rb | |
@@ -887,7 +887,7 @@ module ActiveRecord #:nodoc: | |
def scoped_methods #:nodoc: | |
key = :"#{self}_scoped_methods" | |
- Thread.current[key] = Thread.current[key].presence || self.default_scoping.dup | |
+ Thread.current[key] = Thread.current[key].presence || [] | |
end | |
def before_remove_const #:nodoc: | |
@@ -1412,7 +1412,7 @@ MSG | |
ensure_proper_type | |
- if scope = self.class.send(:current_scoped_methods) | |
+ if scope = self.class.send(:current_scoped_methods) || self.class.send(:default_scoping).dup.last | |
create_with = scope.scope_for_create | |
create_with.each { |att,value| self.send("#{att}=", value) } if create_with | |
end | |
diff --git a/activerecord/lib/active_record/named_scope.rb b/activerecord/lib/active_record/named_scope.rb | |
index 3de4c40..a6b198c 100644 | |
--- a/activerecord/lib/active_record/named_scope.rb | |
+++ b/activerecord/lib/active_record/named_scope.rb | |
@@ -29,7 +29,9 @@ module ActiveRecord | |
if options | |
scoped.apply_finder_options(options) | |
else | |
- current_scoped_methods ? relation.merge(current_scoped_methods) : relation.clone | |
+ result = current_scoped_methods ? relation.merge(current_scoped_methods) : relation.clone | |
+ result = default_scoping.dup.last.override(result) unless default_scoping.empty? | |
+ result | |
end | |
end | |
diff --git a/activerecord/lib/active_record/relation/spawn_methods.rb b/activerecord/lib/active_record/relation/spawn_methods.rb | |
index a6cf59f..dc7367d 100644 | |
--- a/activerecord/lib/active_record/relation/spawn_methods.rb | |
+++ b/activerecord/lib/active_record/relation/spawn_methods.rb | |
@@ -61,6 +61,54 @@ module ActiveRecord | |
alias :& :merge | |
+ def override(r) | |
+ merged_relation = clone | |
+ return merged_relation unless r | |
+ | |
+ Relation::ASSOCIATION_METHODS.each do |method| | |
+ value = r.send(:"#{method}_values") | |
+ | |
+ unless value.empty? | |
+ if method == :includes | |
+ merged_relation = merged_relation.includes(value) | |
+ else | |
+ merged_relation.send(:"#{method}_values=", value) | |
+ end | |
+ end | |
+ end | |
+ | |
+ (Relation::MULTI_VALUE_METHODS - [:joins, :where]).each do |method| | |
+ value = r.send(:"#{method}_values") | |
+ merged_relation.send(:"#{method}_values=", value) if value.present? | |
+ end | |
+ | |
+ merged_relation = merged_relation.joins(r.joins_values) | |
+ | |
+ merged_wheres = @where_values | |
+ | |
+ r.where_values.each do |w| | |
+ if w.respond_to?(:operator) && w.operator == :== | |
+ merged_wheres = merged_wheres.reject {|p| p.respond_to?(:operator) && p.operator == :== && p.operand1.name == w.operand1.name } | |
+ end | |
+ | |
+ merged_wheres += [w] | |
+ end | |
+ | |
+ merged_relation.where_values = merged_wheres | |
+ | |
+ Relation::SINGLE_VALUE_METHODS.reject {|m| m == :lock}.each do |method| | |
+ value = r.send(:"#{method}_value") | |
+ merged_relation.send(:"#{method}_value=", value) unless value.nil? | |
+ end | |
+ | |
+ merged_relation.lock_value = r.lock_value unless merged_relation.lock_value | |
+ | |
+ # Apply scope extension modules | |
+ merged_relation.send :apply_modules, r.extensions | |
+ | |
+ merged_relation | |
+ end | |
+ | |
def except(*skips) | |
result = self.class.new(@klass, table) | |
diff --git a/activerecord/test/cases/relation_scoping_test.rb b/activerecord/test/cases/relation_scoping_test.rb | |
index f538d2a..f350e4f 100644 | |
--- a/activerecord/test/cases/relation_scoping_test.rb | |
+++ b/activerecord/test/cases/relation_scoping_test.rb | |
@@ -396,6 +396,12 @@ class DefaultScopingTest < ActiveRecord::TestCase | |
assert not_expected.id != received.id | |
end | |
+ def test_named_scope_overwrites_default_with_method_syntax | |
+ expected = Developer.order('name DESC').collect { |dev| dev.name } | |
+ received = DeveloperOrderedBySalaryWithMethodSyntax.by_name.collect { |dev| dev.name } | |
+ assert_equal expected, received | |
+ end | |
+ | |
def test_nested_exclusive_scope | |
expected = Developer.find(:all, :limit => 100).collect { |dev| dev.salary } | |
received = DeveloperOrderedBySalary.send(:with_exclusive_scope, :find => { :limit => 100 }) do | |
diff --git a/activerecord/test/models/developer.rb b/activerecord/test/models/developer.rb | |
index 947583a..331318f 100644 | |
--- a/activerecord/test/models/developer.rb | |
+++ b/activerecord/test/models/developer.rb | |
@@ -97,6 +97,12 @@ class DeveloperOrderedBySalary < ActiveRecord::Base | |
end | |
end | |
+class DeveloperOrderedBySalaryWithMethodSyntax < ActiveRecord::Base | |
+ self.table_name = 'developers' | |
+ default_scope order('salary DESC') | |
+ scope :by_name, order('name DESC') | |
+end | |
+ | |
class DeveloperCalledDavid < ActiveRecord::Base | |
self.table_name = 'developers' | |
default_scope :conditions => "name = 'David'" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment