2014-10-01 103 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