Reputation: 42207
I use the following query in SQL to find the same value in multiple fields of my model but would like to do it in a more correct Activerecord way.
MyModel.where("'some_value' in (a_field, another_field)").first.try(:id)
The following does not work since it's an AND and I need an OR
MyModel.where(a_field: 'some_value', another_field: 'some_value').first.try(:id)
Any suggestions ?
Out of curiosity: if I use the first (which works) and use a puts
or p
to view the result I see the results two times ? I wonder why..
EDIT in this example I use only two fields but in reality there could be more so an or wouldn't be doable and not dry
Upvotes: 1
Views: 2041
Reputation: 42207
I forgot about this question, here is how I do this now
def search_in_all_fields model, text
model.where(
model.column_names
.map {|field| "#{field} like '%#{text}%'" }
.join(" or ")
)
end
Or better as a scope in the model itself
class Model < ActiveRecord::Base
scope :search_in_all_fields, ->(text){
where(
column_names
.map {|field| "#{field} like '%#{text}%'" }
.join(" or ")
)
}
end
You would just need to call it like this
Model.search_in_all_fields "test"
Before you start.., to be sure there is no sql injection here still better and shorter
class Model < ActiveRecord::Base
scope :search_all_fields, ->(text){
where("#{column_names.join(' || ')} like ?", "%#{text}%")
}
end
Upvotes: 1
Reputation: 1470
Myltiple ways to do so:
Rails:
Post.where('id = 1').or(Post.where('id = 2'))
refs: https://github.com/rails/rails/commit/9e42cf019f2417473e7dcbfcb885709fa2709f89
Use rais_or Gem: https://github.com/khiav223577/rails_or
EX: user = User.where(account: account).or(email: account).take
Use ARel # Arel is best for complex queries
t = Post.arel_table
results = Post.where(
t[:author].eq("Someone").
or(t[:title].matches("%something%"))
)
Upvotes: 2
Reputation: 36880
There is an or
method available...
MyModel.where(a_field: 'some_value').or(MyModel.where(another_field: 'some_value')).first.try(:id)
for multiple fields you could do
test_value = 'some_value'
my_models = MyModel.where(id: nil)
%i(a_field another_field third_field fourth_field fifth_field).each do |field|
my_models = my_models.or(MyModel.where(field => test_value))
end
Upvotes: 4
Reputation: 3175
Ransack is a gem which is used to build complex queries.
It supports both or
and and
operators.
For searching on multiple columns with same value you can build ransack query in following way.
MyModel.ransack(field1_or_field2_or_field3_eq: 'some_value')
Ransack provide various options to get your result like (equal_to condition, like_condition etc...).
If you don't want to use any external gem then I think @steve's answers is apt.
Upvotes: 2