Module: ActiveRecord::Scoping::Default::ClassMethods
| Relationships & Source Files | |
| Defined in: | activerecord/lib/active_record/scoping/default.rb |
Instance Attribute Summary
- #ignore_default_scope=(ignore) rw private
- #ignore_default_scope? ⇒ Boolean rw private
-
#has_default_scope? ⇒ Boolean
readonly
Internal use only
Whether the model has a default scope, either declared with #default_scope or by overriding the #default_scope method.
-
#scope_attributes? ⇒ Boolean
readonly
Internal use only
Are there attributes associated with this scope?
Instance Method Summary
-
#default_scopes?(all_queries: false) ⇒ Boolean
Checks if the model has any default scopes.
-
#unscoped(&block)
Returns a scope for the model without the previously set scopes.
- #build_default_scope(relation = relation(), all_queries: nil) private
-
#default_scope(scope = nil, all_queries: nil, &block)
private
Use this macro in your model to set a default scope for all operations on the model.
-
#evaluate_default_scope
private
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...
-
#execute_scope?(all_queries, default_scope_obj) ⇒ Boolean
private
If all_queries is nil, only execute on select and insert queries.
Instance Attribute Details
#has_default_scope? ⇒ Boolean (readonly)
Whether the model has a default scope, either declared with #default_scope or by overriding the #default_scope method.
# File 'activerecord/lib/active_record/scoping/default.rb', line 65
def has_default_scope? # :nodoc: default_scopes.any? || !Base.is_a?(method(:default_scope).owner) end
#ignore_default_scope=(ignore) (rw, private)
[ GitHub ]# File 'activerecord/lib/active_record/scoping/default.rb', line 203
def ignore_default_scope=(ignore) ScopeRegistry.set_ignore_default_scope(base_class, ignore) end
#ignore_default_scope? ⇒ Boolean (rw, private)
[ GitHub ]
# File 'activerecord/lib/active_record/scoping/default.rb', line 199
def ignore_default_scope? ScopeRegistry.ignore_default_scope(base_class) end
#scope_attributes? ⇒ Boolean (readonly)
Are there attributes associated with this scope?
# File 'activerecord/lib/active_record/scoping/default.rb', line 59
def scope_attributes? # :nodoc: super || has_default_scope? end
Instance Method Details
#build_default_scope(relation = relation(), all_queries: nil) (private)
[ GitHub ]# File 'activerecord/lib/active_record/scoping/default.rb', line 167
def build_default_scope(relation = relation(), all_queries: nil) return if abstract_class? if !Base.is_a?(method(:default_scope).owner) # The user has defined their own default scope method, so call that evaluate_default_scope do relation.scoping { default_scope } end elsif default_scopes.any? evaluate_default_scope do default_scopes.inject(relation) do |combined_scope, scope_obj| if execute_scope?(all_queries, scope_obj) scope = scope_obj.scope.respond_to?(:to_proc) ? scope_obj.scope : scope_obj.scope.method(:call) combined_scope.instance_exec(&scope) || combined_scope else combined_scope end end end end end
#default_scope(scope = nil, all_queries: nil, &block) (private)
Use this macro in your model to set a default scope for all operations on the model.
class Article < {ActiveRecord::Base}
default_scope { where(published: true) }
end
{Article.all}
#### SELECT * FROM articles WHERE published = true
The #default_scope is also applied while creating/building a record.
It is not applied while updating or deleting a record.
{Article.new}.published # => true
{Article.create}.published # => true
To apply a #default_scope when updating or deleting a record, add
all_queries: true:
class Article < {ActiveRecord::Base}
default_scope -> { where(blog_id: 1) }, all_queries: true
end
Applying a default scope to all queries will ensure that records are always queried by the additional conditions. Note that only where clauses apply, as it does not make sense to add order to queries that return a single object by primary key.
{Article.find}(1).destroy
#### DELETE ... FROM {articles} where ID = 1 AND blog_id = 1;
(You can also pass any object which responds to call to the
default_scope macro, and it will be called when building the
default scope.)
If you use multiple #default_scope declarations in your model then
they will be merged together:
class Article < {ActiveRecord::Base}
default_scope { where(published: true) }
default_scope { where(rating: 'G') }
end
{Article.all}
#### SELECT * FROM articles WHERE published = true AND rating = 'G'
This is also the case with inheritance and module includes where the
parent or module defines a #default_scope and the child or including
class defines a second one.
If you need to do more complex things with a default scope, you can alternatively define it as a class method:
class Article < {ActiveRecord::Base}
def self.default_scope
# Should return a scope, you can call 'super' here etc.
end
end
# File 'activerecord/lib/active_record/scoping/default.rb', line 151
def default_scope(scope = nil, all_queries: nil, &block) # :doc: scope = block if block_given? if scope.is_a?(Relation) || !scope.respond_to?(:call) raise ArgumentError, "Support for calling #default_scope without a block is removed. 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 default_scope = DefaultScope.new(scope, all_queries) self.default_scopes = [*default_scopes, default_scope].freeze end
#default_scopes?(all_queries: false) ⇒ Boolean
Checks if the model has any default scopes. If all_queries
is set to true, the method will check if there are any
default_scopes for the model where all_queries is true.
# File 'activerecord/lib/active_record/scoping/default.rb', line 72
def default_scopes?(all_queries: false) if all_queries self.default_scopes.any?(&:all_queries) else self.default_scopes.any? end end
#evaluate_default_scope (private)
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...
# File 'activerecord/lib/active_record/scoping/default.rb', line 210
def evaluate_default_scope return if ignore_default_scope? begin self.ignore_default_scope = true yield ensure self.ignore_default_scope = false end end
#execute_scope?(all_queries, default_scope_obj) ⇒ Boolean (private)
If all_queries is nil, only execute on select and insert queries.
If all_queries is true, check if the default_scope object has all_queries set, then execute on all queries; select, insert, update, delete, and reload.
# File 'activerecord/lib/active_record/scoping/default.rb', line 195
def execute_scope?(all_queries, default_scope_obj) all_queries.nil? || all_queries && default_scope_obj.all_queries end
#unscoped(&block)
Returns a scope for the model without the previously set scopes.
class Post < {ActiveRecord::Base}
belongs_to :user
def self.default_scope
where(published: true)
end
end
class User < {ActiveRecord::Base}
has_many :posts
end
{Post.all} # Fires "SELECT * FROM posts WHERE published = true"
{Post.unscoped}.all # Fires "SELECT * FROM posts"
{Post.where}(published: false).unscoped.all # Fires "SELECT * FROM posts"
{User.find}(1).posts # Fires "SELECT * FROM posts WHERE published = true AND posts.user_id = 1"
{User.find}(1).posts.unscoped # Fires "SELECT * FROM posts"
This method also accepts a block. All queries inside the block will not use the previously set scopes.
{Post.unscoped} {
Post.limit(10) # Fires "SELECT * FROM posts LIMIT 10"
}
# File 'activerecord/lib/active_record/scoping/default.rb', line 54
def unscoped(&block) block_given? ? relation.scoping(&block) : relation end