【问题标题】:One or more params in model find conditions with Ruby on Rails模型中的一个或多个参数使用 Ruby on Rails 查找条件
【发布时间】:2009-11-02 01:08:24
【问题描述】:

假设我有模型“汽车”和控制器“汽车”,还有一个方法“显示”。

我有多个属性,例如:

in_productionyearmake

我可以轻松地做这样的事情来找到匹配所有传递参数的汽车:

def display
  @cars = Car.find(:all, :conditions => { :in_production => #{params[:in_production]}, :year => #{params[:year]}, :make => #{params[:make]} })`
end

所以我要做的是在菜单中编写硬链接,所以如果我想查找 2009 年生产的所有 Nissan 汽车,我会将这些值作为参数传递到我的链接中。

在另一页上,我想展示 2009 年生产的每辆汽车,只有两个参数而不是三个参数。在使用相同操作的同时动态更改条件以使其与一个、两个或三个参数一起工作的最佳方法是什么?

有什么想法吗?

【问题讨论】:

  • 刚刚注意到我没有逃避条件 sql,编辑了我的帖子,谢谢

标签: ruby-on-rails ruby


【解决方案1】:

首先,使用

:conditions => "in_production = '#{params[:in_production]}' AND year = '#{params[:year]}' AND make = '#{params[:make]}'"

易受 SQL 注入攻击。在数据库条件中使用用户提供的参数之前,您需要对其进行转义。

这样的事情应该可以让您根据参数是否存在更动态地添加条件。我没有测试它,所以我可能会尽快编辑它......

def display
  conditions = []
  conditions << [ "in_production = ?", params[:in_production] ] if params[:in_production].present?
  conditions << [ "year = ?", params[:year] ] if params[:year].present?
  conditions << [ "make = ?", params[:make] ] if params[:make].present?
  @cars = Car.all(:conditions => conditions )
end

【讨论】:

    【解决方案2】:

    当然要转义参数并确保您只查询要公开的字段。除此之外,您还可以使用 Rails 内置的功能:

    Car.find_all_by_in_production_and_year_and_make(in_production, year, make)
    

    手动滚动条件可能允许应用额外的逻辑(仅当年份在 x 和 y 之间时才按年份搜索,等等)。使用 rails finders(反过来使用 method_missing)可以保持 API 的干净和灵活,而不必盯着直接的 SQL 条件。

    您可以构造一个 Car#search 方法,该方法将整个参数哈希作为输入,其中对参数进行清理并去除未公开的字段,并使用参数名称本身构造 Car#find_all_by* 方法调用。添加新的搜索条件就像在参数中传递它们一样简单。

    【讨论】:

    • 如果这些值中的任何一个为“nil”(即未指定 url 参数),这将不起作用
    【解决方案3】:

    您可以查看搜索逻辑。它使用了一些缺少魔法的方法来构造 named_scopes 来做你想做的事情。

    http://github.com/binarylogic/searchlogic

    【讨论】:

    • 这将是命名范围的好地方,特别是如果您经常发现自己进行需要这些条件的查询。 Searchlogic 让它变得非常简单,但手动滚动它们也很容易。
    【解决方案4】:

    我用SmartTuple 来处理这样的事情。简单、强大、专为任务而设计。

    @cars = Car.all(:conditions => (SmartTuple.new(" AND ") + 
      ({:in_production => params[:in_production]} if params[:in_production].present?) +
      ({:year => params[:year]} if params[:year].present?) +
      ({:make => params[:make]} if params[:make].present?)
    ).compile)
    

    @cars = Car.all(:conditions => [SmartTuple.new(" AND "),
      ({:in_production => params[:in_production]} if params[:in_production].present?),
      ({:year => params[:year]} if params[:year].present?),
      ({:make => params[:make]} if params[:make].present?),
    ].sum.compile)
    

    keys = [:in_production, :year, :make]
    @cars = Car.all(:conditions => (SmartTuple.new(" AND ").add_each(keys) do |k|
      {k => params[k]} if params[k].present?
    end).compile)
    

    选择你最喜欢的一个。 :)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-06-15
      • 2015-01-29
      • 1970-01-01
      • 1970-01-01
      • 2011-12-17
      • 1970-01-01
      • 2021-08-06
      相关资源
      最近更新 更多