Der Trick wäre, die leeren Werte zu entfernen, führen Sie ein wenig Vorverarbeitung (und möglicherweise Validierung) der Daten, und dann die params übergeben an die where
Klausel .
mit der Verarbeitung der Datumsbereiche unterstützen zu können, können Sie eine Methode erstellen, die beide Daten überprüft werden zur Verfügung gestellt und werden auf einen Bereich umgewandelt:
def convert_to_range(start_date, end_date)
if start_date && end_date
price_from = Date.parse(price_from)
price_to = Date.parse(price_to)
price_from..price_to
end
rescue ArgumentError => e
# If you're code reaches here then the user has invalid date and you
# need to work out how to handle this.
end
Dann Aktion des Controllers wie folgt aussehen könnte:
# select only the params that are need
car_params = params.slice(:car_model_id, :used, :year_from, :year_to, :price_from, :price_to, :condition)
# do some processing of the data
year_from = car_params.delete(:year_from).presence
year_to = car_params.delete(:year_to).presence
car_params[:price] = convert_to_range(year_from, year_to)
price_from = car_params.delete(:price_from).presence
price_to = car_params.delete(:price_to).presence
car_params[:price] = convert_to_range(price_from, price_to)
# select only params that are present
car_params = car_params.select {|k, v| v.present? }
# search for the cars
@cars = Car.where(car_params)
auch, ich bin ziemlich sicher, dass der used
Wert wird automatisch gegossen bekommen für Sie boolean, wenn seine auf dem where
zur Verfügung gestellt.
Auch @cars
ist eine ActiveRecord::Relation
, die keine errors
Methode hat. Vielleicht wollen Sie unterschiedliche Ergebnisse geben, je nachdem, ob Autos zurückgegeben werden?
ZB: @cars.any?
(oder @cars.load.any?
wenn Sie nicht wollen, zwei Abfragen auszuführen, die Autos zu holen und prüfen, ob Autos vorhanden sind)
Edit:
Wie mu is too short erwähnt können Sie auch sauber up Ihren Code durch Verkettung where
Bedingungen und scopes. Bereiche helfen, die Funktionalität aus dem Controller heraus in das Modell zu verschieben, was die Wiederverwendbarkeit der Funktionalität erhöht.
z.
class Car > ActiveRecord::Base
scope :year_between, ->(from, to) { where(year: from..to) }
scope :price_between, ->(from, to) { where(price: from..to) }
scope :used, ->(value = true) { where(used: used) }
end
Dann in Ihrem Controller:
# initial condition is all cars
cars = Cars.all
# refine results with params provided by user
cars = cars.where(car_model_id: params[:car_model_id]) if params[:car_model_id].present?
cars = cars.year_between(params[:year_from], params[:year_to])
cars = cars.price_between(params[:price_from], params[:price_to])
cars = cars.used(params[:used])
cars = cars.where(condition: params[:condition]) if params[:condition].present?
@cars = cars
Könnte auch nichts wert sein, dass 'M.where (a: 'b', c: 'd')' ist das gleiche wie 'M.where (a: 'b') .wobei (c: 'd') 'oder sogar 'ms = M.wo (a:' b '); ms = ms.where (c: 'd') 'so könnten Sie die gemeinsamen Teile der' if'- und 'else'-Zweige leicht ausfiltern. Ein wenig flexibler als einen Hash zu manipulieren, da auch Bereiche hinzugefügt werden können. –
Ich stecke bei '' 'car_params.delete''' Debug von Rails Konsole:' '' 2.2.3: 035> car_params [: Jahr] = car_params.delete (: Jahr_von) .. car_params.delete (: year_to) => nil..nil 2.2.3: 037> Auto.where (car_params) Autoladung (0.1ms) SELECT "Autos". * Von "Autos" WO "Autos". "car_model_id" = ? UND "Autos". "Used" =? UND "Autos". "Bedingung" =? UND ("Autos". "Jahr" ZWISCHEN? UND?) UND ("Autos". "Preis" ZWISCHEN? UND?) [["car_model_id", 1], ["gebraucht", wahr], ["bedingung", "perfekt"], ["jahr", nil], ["jahr", nil], ["preis", nil ], ["price", nil]] => # '' ' –
Freeminder
Die Anfrage kommt mit leeren Parametern:' '' "year_from" => "", "year_to" => " "," price_from "=>" "," price_to "=>" "' '' And .delete-Methode konvertiert es in '' '..''' – Freeminder