Last Updated: February 18, 2020
·
2.124K
· raysrashmi

Beware of using default scope

Default Scope is used to apply scope to all queries by default.

class User < ActiveRecord::Base
  default_scope {where(state: 'pending')}
end

User.all #=> User Load (0.2ms)  SELECT "users".* FROM "users"  WHERE "users"."status" = 'pending'

Lets add one more scope

class User < ActiveRecord::Base
  default_scope {where(state: 'pending')}
  scope :active, ->{where(state: 'active')}
end

User.active #=> SELECT "users".* FROM "users"  WHERE "users"."status" = 'pending' AND "users"."status" = 'active'
User.where(state: 'active')  #=> SELECT "users".* FROM "users"  WHERE "users"."status" = 'pending' AND "users"."status" = 'active'

As you can see It hasn't override default scope which we thought it should because we are scoping on same column

So if you have default scope and want to remove default scope behaviour from other scope you can user unscope, unscoped or rewhere and except

class User < ActiveRecord::Base
  default_scope {where(state: 'pending')} 
  scope :active, ->{unscope(where: :state).where(state: 'active')}
end

class User < ActiveRecord::Base
  default_scope {where(state: 'pending')}
  scope :active, ->{where(state: 'active')}
end

User.unscoped.active #=> SELECT "users".* FROM "users"  WHERE "users"."state" = 'active'
User.rewhere(state: 'active') #=> SELECT "users".* FROM "users"  WHERE "users"."state" = 'active'
User.except(:default_scope).active #=> SELECT "users".* FROM "users"  WHERE "users"."state" = 'active'

You can find more detail here
https://github.com/rails/rails/issues/13875#issuecomment-35430595

So Beware of using Default Scope.

3 Responses
Add your response

Creating new objects will have a pending state too.

over 1 year ago ·

true

over 1 year ago ·

Ya both can have their specific default scope

over 1 year ago ·