【问题标题】:Does ActiveRecord support dynamic conditions in sql statements?ActiveRecord 是否支持 sql 语句中的动态条件?
【发布时间】:2010-11-01 11:41:44
【问题描述】:

我想在添加下拉菜单时添加条件的 Rails 应用程序中进行 SQL 查询。显然,如果未选择下拉菜单,我不想使用空白条件进行搜索。如何在 SQL 语句中开发动态条件?

未经测试的示例:

当没有选择下拉菜单时:Object.find("billy," :conditions => {})

选择下拉列表时:Object.find("billy," :conditions => {"last_name => "johnson"})

感谢您的意见!

【问题讨论】:

  • 快速说明,Ruby 本身不执行 SQL,您具体询问的是 Rails、ActiveRecord :-)
  • 如果您使用 ActiveRecord,Object 不是模型的好名称,因为它是 Ruby 中的核心类之一。如果您要通用,请尝试模型或事物。 #2 - Thing.find("billy", :conditions => { etc.. } ) 也不起作用。如果您以某种方式将 Thing 设置为具有值为“billy”的 ID 列,那么您可以说 Thing.find("billy"),不需要条件。如果你使用条件,你通常需要 Thing.find :first, :conditions => { etc.. } 或 Thing.find :all, :conditions => { etc.. }。下面你有一些很好的答案,由于这个问题,这些答案不会运行。
  • @austinfromboston 我同意,但我有一种感觉,他只是用那个作为例子,而不是实际使用那个类......至少,我希望他没有使用那个类......

标签: sql ruby-on-rails search activerecord conditional-statements


【解决方案1】:

我为此使用SmartTuple。它很简单,但提供了一种构建“条件条件”的系统方法。

【讨论】:

    【解决方案2】:

    假设您的#find 在控制器中,并且选择的值作为params 中的项目进入(如果没有,我认为您应该考虑更改内容!)那么您应该能够执行以下操作:

    if params[:last_name] # or whatever it's actually called
      Object.find("billy," :conditions => {'last_name = ?', params[:last_name]})
    else
      Object.find("billy")
    end
    

    如果您使用的是相当新的 ActiveRecord 版本(应该是 2.1,可能是 2.0),那么您可以将该逻辑转移到 named_scope

    class Object < ActiveRecord::Base
      named_scope :for_last_name, lambda { |nm| { :conditions => nm.nil? ? {} : { last_name => nm } }
    

    然后你的控制器归结为(我们喜欢瘦控制器)

    Object.for_last_name(params[:last_name])
    

    (都有些未经测试)

    【讨论】:

    • 嘿嘿,你一定看过我的代码并使用了“last_name =>?”而不是“last_name =?”。抱歉让你失望了,我修好了:-)
    • 同意在尝试处理动态条件时使用 named_scopes
    【解决方案3】:

    不太确定您在做什么,但实现此目的的一般方法是让下拉列表的值(不可见文本)成为您希望选择的对象的 ID。如果你没有选择,那么你可以使用这样的东西:

    last_name = unless params[:object][:last_name]
    
    conditions = []
    conditions << "last_name = ?" unless last_name.blank?
    conditions << last_name unless last_name.blank?
    
    Object.find("billy", :conditions => conditions)
    

    查看this link 以了解有关ActiveRecord::Base.find() 方法的更多信息以及使用它们的正确方法。另请查看this great guide,了解如何保护自己免受 SQL 注入攻击。

    编辑 1: 修改后的代码更简洁。此方法还具有能够轻松添加单独条件的优点,只需确保添加所有“something =?”在添加关联值(参数)之前。

    编辑 2: 如果您还没有看到 select form helper,您可以考虑将其用于下拉菜单。让生活更轻松:-)

    【讨论】:

    • 我不知道我是否偷了“last_name =>?”从您的代码中或从问题中调整它。不管怎样,我的校对很烂!感谢您指出。
    • 大声笑,我们可能都看过原始代码......我什至没有注意到那里也有问题。
    【解决方案4】:

    也许是这个?

    Object.find("billy", :conditions => last_name.nil? ? {} : {:last_name => last_name})
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-20
      • 1970-01-01
      • 1970-01-01
      • 2016-12-19
      • 2012-04-15
      相关资源
      最近更新 更多