2014-10-01 62 views
4

我想从数据库中选择Cars,其中where子句为我的问题寻找最佳DRY方法。Rails ActiveRecord where子句

,比如我有这两个参数

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

你能证明此请求您的路由设置。 – 2014-10-01 18:01:11

+0

你正在使用哪个版本的Rails? – Surya 2014-10-01 18:41:17

+0

Rails 4 ............ – 2014-10-01 18:48:13

回答

4

你可以这样做:

car_params = params.slice(:car_model_id, :transmission_id).reject{|k, v| v.nil? } 

然后:

Car.where(car_params) 

说明:既然,你检查,如果特定的键即::car_model_idtransmission_id存在于params。上面的代码会是这样的,当你刚刚:transimission_idparams

Car.where(:transmission_id => '1') 

或此当你有:car_model_idparams

Car.where(:car_model_id => '3') 

或这个时候你就会有两个:

Car.where(:transmission_id => '1', :car_model_id => '3') 

注意:只有当您将params键作为您尝试运行查询的列名称时才能使用。如果您打算在params中使用与列名称不匹配的不同密钥,那么我建议您在slice之前将其密钥更改为控制器本身的列名称。

UPDATE:因为,OP已经编辑了他的问题,现在引入了更多的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 

然后:

Car.where(car_params) 
+0

谢谢你看起来不错,但如果我想检查car_model_id是否不相等,怎么办?=或价格> params [:price]? – 2014-10-02 09:43:25

+0

我不明白你在问什么。你没有在你的问题中提到任何这样的事情。如果您也提前发布过头脑,将会更容易进行头脑风暴。 – Surya 2014-10-02 09:50:01

+0

我已更新我的问题请看看 – 2014-10-02 10:06:59

0

什么是避免这种错误代码的最佳方法,并检查参数是否为 无内联(在哪里)

好问题!

我会执行两个额外的布尔变量(transmission_id_is_validcar_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 

我觉得现在更是人类可读。

+0

有没有更好的办法?因为我有45个参数我的代码将变得巨大和困难的机器 – 2014-10-01 18:06:58

+0

这种情况下使用路由设置。 – 2014-10-01 18:09:40

+0

get'/ api/cars',to:'cars#index',并且使用强参数也即时通讯 – 2014-10-01 18:11:34

0

首先,我会将此代码更改为Car模型,我认为不需要检查参数是否不存在。

# 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宝石。

+0

如果有45个参数,那又怎么样? – 2014-10-01 18:16:14

+0

好点!回答编辑 – Rodrigo 2014-10-01 18:51:51