NoBrainer

A Ruby ORM for RethinkDB

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
end

You 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 }
end

When 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).count

Scopes 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).count

Default 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 models

Note 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) }
end

Default 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:

  1. When using a dependent option on an association, such as
    has_many :stuff, :dependent => :destroy, the Stuff model is used unscoped. For example, upon destroy, NoBrainer will perform a Stuff.unscoped.destroy_all.
  2. When using validates_uniqueness_of :some_field, NoBrainer will not use the default scope to find any duplicates of some_field.
  3. When using belongs_to associations.