diff options
author | Jon Leighton <j@jonathanleighton.com> | 2011-08-13 16:37:44 +0100 |
---|---|---|
committer | Jon Leighton <j@jonathanleighton.com> | 2011-08-13 16:54:05 +0100 |
commit | 24f902b1bcfa5dca4bfc7f2b978a4b0dece73894 (patch) | |
tree | 97f3ce1357170746f7ecd22f2dd9630408468d05 /activerecord/lib/active_record | |
parent | 291072a64a2b191816f395b25aae4a50d2dcfe16 (diff) | |
download | rails-24f902b1bcfa5dca4bfc7f2b978a4b0dece73894.tar.gz rails-24f902b1bcfa5dca4bfc7f2b978a4b0dece73894.tar.bz2 rails-24f902b1bcfa5dca4bfc7f2b978a4b0dece73894.zip |
Fix default scope thread safety. Thanks @thedarkone for reporting.
Diffstat (limited to 'activerecord/lib/active_record')
-rw-r--r-- | activerecord/lib/active_record/base.rb | 41 |
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 |