diff options
Diffstat (limited to 'activerecord/lib/active_record/scoping/default.rb')
-rw-r--r-- | activerecord/lib/active_record/scoping/default.rb | 44 |
1 files changed, 23 insertions, 21 deletions
diff --git a/activerecord/lib/active_record/scoping/default.rb b/activerecord/lib/active_record/scoping/default.rb index 5f05d146f2..a2a85d4b96 100644 --- a/activerecord/lib/active_record/scoping/default.rb +++ b/activerecord/lib/active_record/scoping/default.rb @@ -1,4 +1,3 @@ -require 'active_support/concern' module ActiveRecord module Scoping @@ -7,7 +6,7 @@ module ActiveRecord included do # Stores the default scope for the class - config_attribute :default_scopes + class_attribute :default_scopes, instance_writer: false self.default_scopes = [] end @@ -30,14 +29,14 @@ module ActiveRecord # Post.limit(10) # Fires "SELECT * FROM posts LIMIT 10" # } # - # It is recommended to use the block form of unscoped because chaining - # unscoped with <tt>scope</tt> does not work. Assuming that + # It is recommended that you use the block form of unscoped because + # chaining unscoped with <tt>scope</tt> does not work. Assuming that # <tt>published</tt> is a <tt>scope</tt>, the following two statements - # are equal: the default_scope is applied on both. + # are equal: the <tt>default_scope</tt> is applied on both. # # Post.unscoped.published # Post.published - def unscoped #:nodoc: + def unscoped block_given? ? relation.scoping { yield } : relation end @@ -51,7 +50,7 @@ module ActiveRecord # the model. # # class Article < ActiveRecord::Base - # default_scope where(:published => true) + # default_scope { where(:published => true) } # end # # Article.all # => SELECT * FROM articles WHERE published = true @@ -62,12 +61,6 @@ module ActiveRecord # Article.new.published # => true # Article.create.published # => true # - # You can also use <tt>default_scope</tt> with a block, in order to have it lazily evaluated: - # - # class Article < ActiveRecord::Base - # default_scope { where(:published_at => Time.now - 1.week) } - # end - # # (You can also pass any object which responds to <tt>call</tt> to the <tt>default_scope</tt> # macro, and it will be called when building the default scope.) # @@ -75,8 +68,8 @@ module ActiveRecord # be merged together: # # class Article < ActiveRecord::Base - # default_scope where(:published => true) - # default_scope where(:rating => 'G') + # default_scope { where(:published => true) } + # default_scope { where(:rating => 'G') } # end # # Article.all # => SELECT * FROM articles WHERE published = true AND rating = 'G' @@ -92,21 +85,30 @@ module ActiveRecord # # Should return a scope, you can call 'super' here etc. # end # end - def default_scope(scope = {}) + def default_scope(scope = nil) scope = Proc.new if block_given? + + if scope.is_a?(Relation) || !scope.respond_to?(:call) + ActiveSupport::Deprecation.warn( + "Calling #default_scope without a block is deprecated. For example instead " \ + "of `default_scope where(color: 'red')`, please use " \ + "`default_scope { where(color: 'red') }`. (Alternatively you can just redefine " \ + "self.default_scope.)" + ) + end + self.default_scopes = default_scopes + [scope] end def build_default_scope #:nodoc: - if method(:default_scope).owner != ActiveRecord::Scoping::Default::ClassMethods + if !Base.is_a?(method(:default_scope).owner) + # The user has defined their own default scope method, so call that evaluate_default_scope { default_scope } elsif default_scopes.any? evaluate_default_scope do 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) + if !scope.is_a?(Relation) && scope.respond_to?(:call) + default_scope.merge(unscoped { scope.call }) else default_scope.merge(scope) end |