aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib
diff options
context:
space:
mode:
authorJon Leighton <j@jonathanleighton.com>2011-08-13 16:37:44 +0100
committerJon Leighton <j@jonathanleighton.com>2011-08-13 16:54:05 +0100
commit24f902b1bcfa5dca4bfc7f2b978a4b0dece73894 (patch)
tree97f3ce1357170746f7ecd22f2dd9630408468d05 /activerecord/lib
parent291072a64a2b191816f395b25aae4a50d2dcfe16 (diff)
downloadrails-24f902b1bcfa5dca4bfc7f2b978a4b0dece73894.tar.gz
rails-24f902b1bcfa5dca4bfc7f2b978a4b0dece73894.tar.bz2
rails-24f902b1bcfa5dca4bfc7f2b978a4b0dece73894.zip
Fix default scope thread safety. Thanks @thedarkone for reporting.
Diffstat (limited to 'activerecord/lib')
-rw-r--r--activerecord/lib/active_record/base.rb41
1 files changed, 26 insertions, 15 deletions
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index 102d8f4175..5a57e1bc70 100644
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -1206,6 +1206,14 @@ MSG
Thread.current["#{self}_current_scope"] = scope
end
+ def ignore_default_scope? #:nodoc:
+ Thread.current["#{self}_ignore_default_scope"]
+ end
+
+ def ignore_default_scope=(ignore) #:nodoc:
+ Thread.current["#{self}_ignore_default_scope"] = ignore
+ end
+
# Use this macro in your model to set a default scope for all operations on
# the model.
#
@@ -1259,24 +1267,27 @@ MSG
# The @ignore_default_scope flag is used to prevent an infinite recursion situation where
# a default scope references a scope which has a default scope which references a scope...
def build_default_scope #:nodoc:
- return if defined?(@ignore_default_scope) && @ignore_default_scope
- @ignore_default_scope = true
-
- if method(:default_scope).owner != Base.singleton_class
- default_scope
- elsif default_scopes.any?
- default_scopes.inject(relation) do |default_scope, scope|
- if scope.is_a?(Hash)
- default_scope.apply_finder_options(scope)
- elsif !scope.is_a?(Relation) && scope.respond_to?(:call)
- default_scope.merge(scope.call)
- else
- default_scope.merge(scope)
+ return if ignore_default_scope?
+
+ begin
+ self.ignore_default_scope = true
+
+ if method(:default_scope).owner != Base.singleton_class
+ default_scope
+ elsif default_scopes.any?
+ default_scopes.inject(relation) do |default_scope, scope|
+ if scope.is_a?(Hash)
+ default_scope.apply_finder_options(scope)
+ elsif !scope.is_a?(Relation) && scope.respond_to?(:call)
+ default_scope.merge(scope.call)
+ else
+ default_scope.merge(scope)
+ end
end
end
+ ensure
+ self.ignore_default_scope = false
end
- ensure
- @ignore_default_scope = false
end
# Returns the class type of the record using the current module as a prefix. So descendants of