如何使用 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)
希望对您有所帮助。
我目前正在从事一个项目,该项目有一个 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)
希望对您有所帮助。