I've been running into this problem several times: I want to apply a scope on a query, but only if the parameter passed to the scope is not null. So
tags = Tag.where(name: params[:name]) if params[:name]
However, there are two problems with this. One is that Rails will evaluate the query immediately, and so if I want to apply more conditions to it, say
tags.where(location: params[:place]) if params[:place]
It will query the DB again. The second problem is that it doesn't look very nice, which I've tried to get around with class methods.
class Tag < ActiveRecord::Base
def self.name_like this_name
if !this_name.blank?
where("name ILIKE '%#{this_name}%'")
else
#what do I put here? `all` does not work
end
end
end
However, I cannot simply just put all
in there, because that evaluates a query. Any thoughts?
Here you can use a lambda scope, and use the self
to call self.all
:
class Tag < ActiveRecord::Base
scope :named_like, (lambda do |name|
if name.present?
where("name ILIKE ?", "%#{name}%")
else
scoped # does not apply a where clause
end
end)
end
This is taking too much lines for a very basic scope, here is the compressed version:
class Tab < ActiveRecord::Base
scope :named_like, lambda{ |name| self.where("name ILIKE ?", "%#{name}%") if name.present? }
end
Also:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With