Override A Default Scope In Rails

Posted By Weston Ganger

I have been frustrated and angered by many default_scopes. They should usually be avoided but sometimes are necessary and useful. I knew there must be a better way to override default scopes. Fortunately in Rails 4.1+ they added the unscope method. This makes unscoping much more sane.

class User < ActiveRecord::Base
  default_scope { active.order(first_name: :asc, last_name: :asc) }
  scope :active, -> { where(enabled: true) }

# Three ways to fail at reordering these records
User.order(created_at: :desc) # order is not applied because of the default scopes order
User.unscoped.order(created_at: :desc) # all previous scopes are lost in this case the active scope is lost
User.reorder(created_at: :desc) # re-sorts the collection in Ruby after the DB returns it which is very slow

# Correct method
User.unscope(:order).order(created_at: :desc)
# OR
User.unscope(order: [:first_name, :last_name]).order(created_at: :desc)

The same thing applies to all ActiveRecord statements such as where, joins, includes, etc.

Related External Links:

Article Topic:Software Development - Ruby / Rails

Date:December 01, 2016