Scopes
Scope Definitions
NoBrainer allows named scopes to be defined on Models. Scopes are defined by declaring a class method on a model. Such method must return a criterion. Example:
class Model
def self.active
where(:active => true)
end
endYou can also use the scope method which defines a class method with
whatever you pass as a block. Example:
class Model
scope(:active) { where(:active => true }
endWhen a class method is found in a chain of criteria, the method is executed and the returned criterion is merged with the chain. Example with the previously declared scope:
Model.where(:email => /@gmail/).active.count
# Equivalent to
Model.where(:email => /@gmail/).where(:active => true).countScopes can accept arguments. Example:
class Model
scope(:in_category) { |category| where(:category => category) }
def self.created_before(time)
where(:created_at.lt => time)
end
end
Model.in_category('games').created_before(1.week.ago).countDefault Scopes
Default scopes are scopes that are merged in criteria when constructing a query.
Adding unscoped in the criteria will disable the use of the default scope.
class Model
default_scope { where(:active => true) }
end
Model.count # returns only active models
Model.unscoped.count # returns all modelsNote that many default scopes can be declared. All of them are applied, in the order of declaration. This can come in handy when using polymorphic models with different default scopes declared in parents and subclasses. Example:
class Parent
default_scope { order_by(:created_at) }
default_scope { where(:active => true) }
end
class Child < Parent
default_scope { where(:created_by => :admin) }
endDefault scopes are applied at the beginning of the chain when building a query.
The unscoped keyword has no effect on has_many associations have a custom :scope defined.
Unlike the ActiveRecord behavior, where() filters in default scopes are not overridable.
For example, consider a Model with a default scope of where(:active => true).
With ActiveRecord, Model.where(:active => false) will yield all inactive
models, while NoBrainer will return nothing. This is because NoBrainer
evaluates
Model.where(:active => true).where(:active => false), which evaluates to
Model.where(:and => [:active => true, :active => false]).
Default Scopes are sometimes ignored
NoBrainer will not use the default scopes in the following cases:
- When using a
dependentoption on an association, such as
has_many :stuff, :dependent => :destroy, the Stuff model is used unscoped. For example, upon destroy, NoBrainer will perform aStuff.unscoped.destroy_all. - When using
validates_uniqueness_of :some_field, NoBrainer will not use the default scope to find any duplicates ofsome_field. - When using
belongs_toassociations.