I found a few similar questions while searching here, but when I tried to add unless to the solutions I found, things started to break...
Here's what I have that works:
Controller:
@metrics = Metric.where("current_ratio > ?", @screen.current_ratio_min) unless @screen.current_ratio_min.nil?
Once I add another .where line (of which I need to add many),
@metrics = Metric.where("current_ratio > ?", @screen.current_ratio_min) unless @screen.current_ratio_min.nil?
.where("current_ratio < ?", @screen.current_ratio_max) unless @screen.current_ratio_max.nil?
I get an error:
undefined method `where' for false:FalseClass
I'm assuming this is because the first unless is ending my query. How do I apply an unless just to each individual condition? If that is, in fact, the problem :\
Thanks in advance!
@metrics = Metric.all
@metrics = @metrics.where('current_ratio > ?', @screen.current_ration_min) if @screen.current_ratio_min.present?
@metrics = @metrics.where('other_value > ?', @screen.other_value) if @screen.other_value.present?
This is the best way I can think of without programmatically building a where clause string which can be risky for SQL injection.
Keep adding as many conditions as you want. Notable, use if something.present? instead of your unless something.nil?
Also, the Metric.all might not be ideal, but whatever you need to get all records to start with.
If you want clean code, use scope
In metric.rb
scope :current_ratio_min, lambda {|current_ratio_min|
current_ratio_min.present? ? where('current_ratio > ?', current_ration_min) : where()}
scope :current_ratio_max, lambda {|current_ratio_max|
current_ratio_max.present? ? where('current_ratio > ?', current_ratio_max) : where()}
Your query :
@metrics = Metric.current_ratio_min(@screen.current_ratio_min).current_ratio_max(@screen.current_ratio_max)`
Write the following method in your Array class
class Array
def add_condition!(condition, conjunction = 'AND')
if String === condition
add_condition!([condition])
elsif Hash === condition
add_condition!([condition.keys.map { |attr| "#{attr}=?" }.join(' AND ')] + condition.values)
elsif Array === condition
unless condition.empty?
self[0] = "(#{self[0]}) #{conjunction} (#{condition.shift})" unless empty?
self.push(*condition)
end
else
raise "don't know how to handle this condition type"
end
self
end
end
You can build your conditions for ActiveRecord where or find with conditions as follows
conditions = []
conditions.add_condition!(["current_ratio > ?", @screen.current_ratio_min]) unless @screen.current_ratio_min.nil?
conditions.add_condition!(["current_ratio < ?", @screen.current_ratio_max]) unless @screen.current_ratio_max.nil?
@metrics = Metric.where(conditions)
This will be helpful in building multiple conditions with AND/OR combinations
What about something like this?
if !@screen.current_ratio_min.nil? && !@screen.current_ratio_max.nil?
@metrics = Metric.where("current_ratio > ?", @screen.current_ratio_min).where("current_ratio < ?", @screen.current_ratio_max)
elsif @screen.current_ratio_min.nil? && !@screen.current_ratio_max.nil?
@metrics = Metric.where("current_ratio < ?", @screen.current_ratio_max)
elsif !@screen.current_ratio_min.nil? && @screen.current_ratio_max.nil?
@metrics = Metric.where("current_ratio > ?", @screen.current_ratio_min)
else
@metrics = Metric.all
end
Try with the following code
if @screen.current_ratio_min and @screen.current_ratio_max
@metrics = Metric.where("current_ratio > ? and current_ratio < ?", @screen.current_ratio_min, @screen.current_ratio_max)
else
unless @screen.current_ratio_min.blank?
@metrics = Metric.where("current_ratio > ?", @screen.current_ratio_min)
else
unless @screen.current_ratio_max.blank?
@metrics = Metric.where("current_ratio < ?", @screen.current_ratio_max)
else
@metrics = Metric.all
end
end
end
来源:https://stackoverflow.com/questions/17519114/multiple-query-conditions-in-rails-if-they-exist