【问题标题】:Assemble a complex SQL query using Activerecord::Relation and/or Arel with 'joins', 'as', and 'like'使用带有“joins”、“as”和“like”的 Activerecord::Relation 和/或 Arel 组装复杂的 SQL 查询
【发布时间】:2013-05-30 03:30:11
【问题描述】:

我正在使用数据表 (http://datatables.net) 构建一个 Rails 3.2 应用程序,在大多数 html 表上进行客户端分页和过滤,在其他一些 html 表上进行服务器端分页和过滤。我想做每列过滤,这对于客户端表来说非常容易,但我认为我需要为数据库构造一个 sql 查询来对服务器端表进行每列过滤。我密切关注 RailsCast #340 on datatables 中的示例并使其正常工作。

挑战在于对与另一个表真正具有外键关系的列进行排序和过滤。我不想对 foreign_key 值的实际内容进行排序和过滤。我想对为链接对象显示的“.to_s”值进行排序和过滤(这是使用客户端排序和过滤功能的语义)。这是一个例子:

class Address < ActiveRecord::Base
  attr_accessible :city, :line1, :line2, :state, :zip

  has_many :people

  def to_s
    [line1, line2, city, state, zip].join(' ')
  end
end
class Person < ActiveRecord::Base
  attr_accessible :address, :name

  belongs_to :address
end

所以显示人员列表的视图有两列,分别是姓名和地址

<td><%= p.name %></td>
<td><%= p.address %></td>

而出现在索引表中的是

John Smith |  1234 Main St Anywhere City AA 12345

因此,通过客户端排序和过滤,我可以在地址列中搜索“Anywhere”,并在地址字段中获取包含该术语的所有行。在服务器端做同样的事情似乎要困难得多。我想我正在尝试组装一个看起来像这样的 sql 查询:

select * from people 
         join address on people.address_id = address.id
        where concat(address.line1, 
                     address.line2, 
                     address.city, 
                     address.state, 
                     address.zip) as spec_address like query_term 
     order by spec_address

(这不一定是正确的 SQL 代码。)

我查看了 ActiveRecord Query Rails 指南以及我在 Arel 上可以找到的任何内容,但均未成功。

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 activerecord arel


    【解决方案1】:

    您可以使用Address 上的范围来执行此操作,然后将其合并到Person 查询中。

    class Address < ActiveRecord::Base
      scope :anywhere, lambda{|search|
        attrs = [:line1, :line2, :city, :state, :zip]
        where(attrs.map{|attr| "addresses.#{attr} LIKE :search"}.join(' OR '), search: "#{search}%").
          order(*attrs) 
      }
    end
    
    Person.joins(:address).merge(Address.anywhere(query_term))
    

    【讨论】:

    • 谢谢!仅供参考 Person.includes(:address).merge(Address.anywhere(query_term)) 不会在 person.address_id = address.id 上生成连接,但 Person.joins(:address).merge(Address.anywhere(query_term))做我想做的事。
    猜你喜欢
    • 2021-11-27
    • 1970-01-01
    • 2011-05-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-06
    • 1970-01-01
    • 2017-09-21
    相关资源
    最近更新 更多