2014-10-01 6 views
4

Я хочу выбрать Cars из базы данных, где предложение ищет лучший подход DRY для моей проблемы.Rails ActiveRecord где статья

, например, у меня есть эти два параметра

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

Можете ли вы показать параметры маршрута для этого запроса. –

+0

Какую версию Rails вы используете? – Surya

+0

Rails 4 ............ –

ответ

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, который не соответствует имени столбца, я бы предложил вам изменить его ключ на имя столбца в самом контроллере до slice.

ОБНОВЛЕНИЕ: Поскольку, ОП отредактировал его вопрос и ввел еще if.. else условий сейчас. Один из способов решить это и всегда помнить о том, что нужно иметь правильные значения, для которых вы хотите запускать свои запросы в классе модели, вот 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! = Или price> params [: price]? –

+0

Я не понимал, о чем вы просите. Вы не упомянули ничего подобного в своем вопросе. Было бы легче провести мозговой штурм, если бы вы разместили это заранее. – Surya

+0

Я обновил свой вопрос, пожалуйста, посмотрите –

0

Что такое лучший подход, чтобы избежать такого плохого кода и проверить, является ли параметр nil inline (in where)

Хороший вопрос!

Сделаю реализацию с двумя дополнительными логическими переменными (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 

Я думаю, что теперь более читаемым человеком.

+0

Нет лучшего способа? coz у меня есть 45 параметров, мой код станет огромным и сложным для машины. –

+0

В случае, если это игра с настройками маршрута. –

+0

get '/ api/cars', to: 'cars # index' и im, используя сильные параметры также –

0

Во-первых, я бы сменил этот код на , и я думаю, что нет необходимости проверять, нет ли параметров.

# 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 параметров? –

+0

Хороший вопрос! Ответ отредактирован – Rodrigo