Ruby on Rails搜索多个参数

时间:2014-03-26 14:35:13

标签: ruby-on-rails ruby activemodel

例如在我的Car模型中我有这样的字段:

color, price, year

以形式partial我生成包含所有这些字段的表单。但是如何编写这样的逻辑:

用户可以输入颜色和年份,我必须找到这个条件,用户可以同时输入一年或所有字段......

如何写出条件?我可以这样写:

if params[:color].present?
car = Car.where(color: params[:color])
end

if params[:color].present? && params[:year].present?
car = Car.where(color: params[:color], year: params[:year])
end
and so over....

但这是一个非常难看的解决方案,我是铁杆的新手,想知道:如何更好地解决我的问题?

5 个答案:

答案 0 :(得分:4)

查看has_scope gem:https://github.com/plataformatec/has_scope

它确实简化了很多:

class Graduation < ActiveRecord::Base
  scope :featured, -> { where(:featured => true) }
  scope :by_degree, -> degree { where(:degree => degree) }
  scope :by_period, -> started_at, ended_at { where("started_at = ? AND ended_at = ?", started_at, ended_at) }
end

class GraduationsController < ApplicationController
  has_scope :featured, :type => :boolean
  has_scope :by_degree
  has_scope :by_period, :using => [:started_at, :ended_at], :type => :hash

  def index
    @graduations = apply_scopes(Graduation).all
  end
end

来自控制器方面

答案 1 :(得分:2)

我会把它们变成你的Car模型的范围:

scope :by_color, lambda { |color| where(:color => color)}
scope :by_year, lambda { |year| where(:year => year)}

在您的控制器中,您只需将它们有条件地链接起来:

def index
  @cars = Car.all

  @cars = @cars.by_color(params[:color]) if params[:color].present?
  @cars = @cars.by_year(params[:year]) if params[:year].present?
end

答案 2 :(得分:1)

user_params = [:color, :year, :price]

cars = self
user_params.each do |p|
    cars = cars.where(p: params[p]) if params[p].present?
end

答案 3 :(得分:0)

我会这样做的典型(天真但简单)方法是在我的模型中使用通用search方法,例如

class Car < ActiveRecord::Base
  # Just pass params directly in
  def self.search(params)
    # By default we return all cars
    cars = all

    if params[:color].present?
      cars = cars.where(color: params[:color])
    end

    if params[:price1].present? && params[:price2].present?
      cars = cars.where('price between ? and ?', params[:price1], params[:price2])
    end

    # insert more fields here

    cars
  end
end

您可以轻松地将where链接到这样的查询上,并且Rails将在SQL中将它们全部组合在一起。然后,您可以使用Car.search(params)调用它。

答案 4 :(得分:-1)

我认为你可以使用params.permit

my_where_params = params.permit(:color, :price, :year).select {|k,v| v.present?}
car = Car.where(my_where_params)

编辑:我认为这仅适用于rails 4,不确定您使用的是哪个版本。

编辑#2摘自我链接到的网站:

如果允许的属性丢失,使用许可证不会介意

params = ActionController::Parameters.new(username: "john", password: "secret")
params.permit(:username, :password, :foobar)
# => { "username"=>"john", "password"=>"secret"}

正如您所看到的,foobar并不在新哈希中。

EDIT#3将select块添加到where_params,因为在注释中指出空表单字段会触发在params散列中创建一个空元素。