如何使用 Arel 跨多态 has_one 关系进行查询

How to use Arel to query across a polymorphic has_one relationship

我目前正在从事一个项目,该项目有一个 jquery 数据tables 前端,并且正在使用 ajax-datatables-rails gem to handle the backend. After reviewing the examples 他们 link 并且我遇到了挑战。

我有一个数据table,它显示来自 table 的数据,我们称它为 Foo,它与 3 个不同的 table 具有 has_one 多态关系.我的搜索需要搜索该多态关系中的列。

def my_filter
    ->(column,value) { Arel.sql("Foo.bar.description").matches("%#{value}%")}
end

我尝试的一件事是转换 Arel::Table(a 是 arel table)

Foo.where(a[:id].not_eq(nil)).find(
     :all,
     :joins => "bar",
     :conditions => ["bar.description LIKE %asd%", true]
 ).arel_table

但是在这种情况下,我收到一条消息,指出它无法在 Foo 上找到 ID。

试试这个方法

class Foo < ActiveRecord::Base
  has_one :bar, polymorphic: true

  def view_columns
    @view_columns ||= {
      description: { source: "City.id", cond: by_description },
    }
  end

  def by_description
    ->(column) { joins(:bar).where("description LIKE ?", "%#{column.search.value}%")}
  end
end

我可以想到两种方法(并且根据您的 DBMS,幕后发生的事情可能几乎相同):

  • 为所有不同多态 bar 类型的所有相关字段创建视图
  • 加入即时创建的动态 table

在这两种情况下,底层逻辑都是一个 UNION 命令,看起来有点像下面这样:

SELECT foo_id, description FROM bars1
UNION
SELECT foo_id, description FROM bars2
UNION
SELECT foo_id, description FROM bars3

对于视图,此 UNION 将构成视图本身的内容。

在动态 table 的情况下,它看起来像这样:

SELECT foos.*, bars.*
FROM foos
LEFT JOIN (
  SELECT foo_id, description FROM bars1
  UNION
  SELECT foo_id, description FROM bars2
  UNION
  SELECT foo_id, description FROM bars3
) AS bars ON bars.foo_id = foos.id
WHERE bars.description LIKE 'whatever%'

来看一下,Arel的使用基本和平时一样,只是需要把JOIN显式化一下:

Foo.joins("LEFT JOIN bars ON bars.foo_id = foos.id").where("bars.description LIKE ?", description)

对于动态 table,我确信可以用纯 Arel 来表达它,但就我个人而言,我只是简单地使用 SQL 代替:

joins_sql = <~SQL.strip_heredoc
  LEFT JOIN (
    SELECT foo_id, description FROM bars1
    UNION
    SELECT foo_id, description FROM bars2
    UNION
    SELECT foo_id, description FROM bars3
  ) AS bars ON bars.foo_id = foos.id
SQL

Foo.select("foos.*, bars.*").joins(joins_sql).where("bars.description LIKE ?", description)

希望对您有所帮助。