我想从数据库中选择Cars
,其中where子句为我的问题寻找最佳DRY方法。
例如我有这两个参数
params[:car_model_id] (int)
params[:transmission_id] (int)
params[:from_date]
params[:to_date]
但我不知道哪一个会为空
if params[:car_model_id].nil? && !params[:transmission_id].nil?
if params[:from_date].nil? && params[:from_date].nil?
return Car.where(:transmission_id => params[:transmission_id])
else
return Car.where(:transmission_id => params[:transmission_id], :date => params[:from_date]..params[:to_date])
end
elseif !params[:car_model_id].nil? && params[:transmission_id].nil?
if params[:from_date].nil? && params[:from_date].nil?
return Car.where(:car_model_id=> params[:car_model_id])
else
return Car.where(:car_model_id=> params[:car_model_id], :date => params[:from_date]..params[:to_date])
end
else
return Car.where(:car_model_id=> params[:car_model_id], :transmission_id => params[:transmission_id], :date => params[:from_date]..params[:to_date])
end
避免此类错误代码的最佳方法是什么,并检查参数是否为内联零(where
)
答案 0 :(得分:4)
你可以这样做:
car_params = params.slice(:car_model_id, :transmission_id).reject{|k, v| v.nil? }
然后:
Car.where(car_params)
说明:因为,您要检查:car_model_id
中是否存在特定密钥,即:transmission_id
和params
。当:transimission_id
中只有params
时,上面的代码会是这样的:
Car.where(:transmission_id => '1')
或:car_model_id
中的params
:
Car.where(:car_model_id => '3')
或当你同时拥有这两个时:
Car.where(:transmission_id => '1', :car_model_id => '3')
注意:仅当您将params键作为您尝试运行查询的列名时才会起作用。如果您打算在params
中使用与列名称不匹配的其他键,那么我建议您在{{{{}}之前更改它作为控制器本身中列名称的键。 1}}。
更新:因为OP已经编辑了他的问题并且现在引入了更多slice
条件。解决这个问题并始终牢记一件事的一种方法是让您的if.. else
正确值,以便在模型类上运行查询,此处user_params
。所以,在这种情况下:
Car
然后:
car_params = params.slice(:car_model_id, :transmission_id).reject{|k, v| v.nil? }
if params[:from_date].present? && params[:from_date].present?
car_params.merge!(date: params[:from_date]..params[:to_date])
end
答案 1 :(得分:0)
避免此类错误代码的最佳方法是什么,并检查参数是否正确 无内联(在哪里)
好问题!
我将使用两个额外的布尔变量(transmission_id_is_valid
和
car_model_id_is_valid
)
transmission_id_is_valid = params[:car_model_id].nil? && !params[:transmission_id].nil?
car_model_id_is_valid = !params[:car_model_id].nil? && params[:transmission_id].nil?
if transmission_id_is_valid
return Car.where(:transmission_id => params[:transmission_id])
elseif car_model_id_is_valid
return Car.where(:car_model_id=> params[:car_model_id])
....
end
我认为现在更具人性化。
答案 2 :(得分:0)
首先,我会将此代码更改为Car
模型,我认为无需检查params是否存在。
# using Rails 4 methods
class Car < ActiveRecord::Base
def self.find_by_transmission_id_or_model_id(trasmission_id, model_id)
if transmission_id
find_by trasmission_id: trasmission_id
elsif model_id
find_by model_id: model_id
end
end
end
在控制器中:
def action
car = Car.find_by_transmission_id_or_model_id params[:trasmission_id], params[:car_model_id]
end
修改强>
这个代码很好,而你只有两个参数。对于许多条件参数,请查看ransack gem。