aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib
diff options
context:
space:
mode:
authorJon Leighton <j@jonathanleighton.com>2013-04-05 12:46:56 +0100
committerJon Leighton <j@jonathanleighton.com>2013-04-05 13:14:28 +0100
commit8606a7fbe9367e9ae37ad058dd07f0dd38daf015 (patch)
treea83a09299de6ccb87a4efcec8d06c2d23c9fa8f8 /activerecord/lib
parentf029fb07c210dd384f8ad02b5ce8903911c540d3 (diff)
downloadrails-8606a7fbe9367e9ae37ad058dd07f0dd38daf015.tar.gz
rails-8606a7fbe9367e9ae37ad058dd07f0dd38daf015.tar.bz2
rails-8606a7fbe9367e9ae37ad058dd07f0dd38daf015.zip
Fix scope chaining + STI
See #9869 and #9929. The problem arises from the following example: class Project < ActiveRecord::Base scope :completed, -> { where completed: true } end class MajorProject < Project end When calling: MajorProject.where(tasks_count: 10).completed This expands to: MajorProject.where(tasks_count: 10).scoping { MajorProject.completed } However the lambda for the `completed` scope is defined on Project. This means that when it is called, `self` is Project rather than MajorProject. So it expands to: MajorProject.where(tasks_count: 10).scoping { Project.where(completed: true) } Since the scoping was applied on MajorProject, and not Project, this fails to apply the tasks_count condition. The solution is to make scoping apply across STI classes. I am slightly concerned about the possible side-effects of this, but no tests fail and it seems ok. I guess we'll see.
Diffstat (limited to 'activerecord/lib')
-rw-r--r--activerecord/lib/active_record/scoping.rb4
-rw-r--r--activerecord/lib/active_record/scoping/named.rb9
2 files changed, 4 insertions, 9 deletions
diff --git a/activerecord/lib/active_record/scoping.rb b/activerecord/lib/active_record/scoping.rb
index 9746b1c3c2..886182f534 100644
--- a/activerecord/lib/active_record/scoping.rb
+++ b/activerecord/lib/active_record/scoping.rb
@@ -9,11 +9,11 @@ module ActiveRecord
module ClassMethods
def current_scope #:nodoc:
- Thread.current["#{self}_current_scope"]
+ Thread.current["#{base_class}_current_scope"]
end
def current_scope=(scope) #:nodoc:
- Thread.current["#{self}_current_scope"] = scope
+ Thread.current["#{base_class}_current_scope"] = scope
end
end
diff --git a/activerecord/lib/active_record/scoping/named.rb b/activerecord/lib/active_record/scoping/named.rb
index 12317601b6..da73bead32 100644
--- a/activerecord/lib/active_record/scoping/named.rb
+++ b/activerecord/lib/active_record/scoping/named.rb
@@ -160,13 +160,8 @@ module ActiveRecord
singleton_class.send(:define_method, name) do |*args|
if body.respond_to?(:call)
- scope = extension ? body.call(*args).extending(extension) : body.call(*args)
-
- if scope
- default_scoped = scope.default_scoped
- scope = relation.merge(scope)
- scope.default_scoped = default_scoped
- end
+ scope = all.scoping { body.call(*args) }
+ scope = scope.extending(extension) if extension
else
scope = body
end