Abhishek Aravindan
Abhishek Aravindan

Reputation: 1482

How to add condition for all where query for an ActiveRecordModel?

I have a user table in my rails application and the application uses many where conditions for this model throughout the application in many controller methods.

Now i have to add an extra attribute for the where condition. is there a way to do the following and how? instead of adding the extra attribute to all the where condition used in the entire application can i write a custom where to the user model so the condition will be pre-added to the where in entire application for the user model.

i found out the source for the where

def where(opts = :chain, *rest)
 if :chain == opts
  WhereChain.new(spawn)
 elsif opts.blank?
  self
 else
  spawn.where!(opts, *rest)
 end
end

my where condition in the controller methods now:

User.where(:status => true, :country => "IN")

this condition and similar conditions are used in many methods in application and i want to get the user who has not :deactivated.

i can make changes to all where condition like

User.where(:status => true, :country => "IN", :deactivated => false)

instead i thought of writing a custom where that precheck :deactivated => false

Upvotes: 1

Views: 467

Answers (1)

Surya
Surya

Reputation: 2699

Default Scope:

class User < ActiveRecord::Base
  default_scope -> { where(deactivated: false) }
end

You can use default_scope.

Now, whenever you query User, automatically the default scope query will get appended.

For more details on default_scope, please refer: https://api.rubyonrails.org/classes/ActiveRecord/Scoping/Default/ClassMethods.html#method-i-default_scope

If there are usecases that prevent you from using default_scope, then you can use custom scopes or unscope the default scope.

Unscoping:

You can unscope in Project model if you want to remove the default scope.

belongs_to :user, ->{ unscope(where: :deactivated) }

Or you can fetch all user and then unscope project.users.unscoped

Custom Scope:

class User < ActiveRecord::Base
  scope :deactivated, ->(deactivated = false) { where(deactivated: deactivated) }
end

Now, to make use of that scope, you can query like this:

User.deactivated.where(:status => true, :country => "IN")

For reference: https://api.rubyonrails.org/classes/ActiveRecord/Scoping/Named/ClassMethods.html#method-i-scope

Upvotes: 3

Related Questions