Rails 3中带有连接字段的“Where”子句

时间:2010-12-08 04:58:09

标签: ruby-on-rails ruby-on-rails-3 where-clause

我正在写一个rails 3应用程序,我有一个用户数据库表。用户具有first_name和last_name列。在我列出用户的页面上,我想要一个允许用户过滤列表的文本搜索框。他们需要能够在搜索框中输入以下内容之一: - 用户的名字 - 用户的姓氏 - 用户的全名(例如“Smith,John”)

我不知道如何编写将返回这些结果的where子句。我得到的最接近的是下面,但是连接的字段部分不起作用。

where('(first_name LIKE :search) or (last_name LIKE :search) or ("#{last_name}, #{first_name}" LIKE :search)', :search => "%#{search}%")

我也有兴趣知道是否有更好的方法来处理我的OR语句,因为这个条款变得非常笨重。

感谢您的帮助!

2 个答案:

答案 0 :(得分:2)

您必须记住,where将转换为SQL,如果要将连接列与搜索字符串进行比较,则必须在数据库/ sql级别执行此操作。

现在这就变得棘手,因为sql中的连接因数据库而异。

在Postgresql和Oracle中,您可以编写如下内容:

where("(first_name LIKE :search) or (last_name LIKE :search) or (last_name || ',' || first_name LIKE :search)", :search => "%#{search}%"

不幸的是,Mysql不支持标准连接运算符||,使用mysql,你必须使用concat代替:

where("(first_name LIKE :search) or (last_name LIKE :search) or (concat(last_name, ',', first_name) LIKE :search)", :search => "%#{search}%"

答案 1 :(得分:2)

如果它对其他人有帮助,这就是我采用的解决方案:

  def self.search(query)
    if query.blank?
      scoped
    else
      sql = query.split.map do |word|
       %w[first_name last_name].map do |column|
        sanitize_sql ["#{column} LIKE ?", "%#{word}%"]
       end.join(" or ")
      end.join(") and (")
      where("(#{sql})")
    end
  end

感谢Railscasts的Ryan Bates提供此解决方案。