如何使用 Arel 跨多态 has_one 关系进行查询
Posted
技术标签:
【中文标题】如何使用 Arel 跨多态 has_one 关系进行查询【英文标题】:How to use Arel to query across a polymorphic has_one relationship 【发布时间】:2020-07-16 03:15:00 【问题描述】:我目前正在开发一个具有 jquery 数据表前端的项目,并且正在使用 ajax-datatables-rails gem 来处理后端。在查看了examples 之后,他们链接到并遇到了挑战。
我有一个数据表,它显示一个表中的数据,我们称之为 Foo,它与 3 个不同的表具有 has_one 多态关系。我的搜索需要搜索该多态关系中的列。
def my_filter
->(column,value) Arel.sql("Foo.bar.description").matches("%#value%")
end
我尝试的一件事是转换 Arel::Table(a 是 arel 表)
Foo.where(a[:id].not_eq(nil)).find(
:all,
:joins => "bar",
:conditions => ["bar.description LIKE %asd%", true]
).arel_table
但是在这种情况下,我收到一条消息,指出它在 Foo 上找不到 id。
【问题讨论】:
【参考方案1】:我可以想到两种方法(根据您的 DBMS,幕后发生的事情可能几乎相同):
为所有不同多态bar
类型的所有相关字段创建一个视图
加入动态创建的动态表
在这两种情况下,底层逻辑都是UNION
命令,看起来有点像以下:
SELECT foo_id, description FROM bars1
UNION
SELECT foo_id, description FROM bars2
UNION
SELECT foo_id, description FROM bars3
在视图的情况下,这个UNION
将构成视图本身的内容。
如果是动态表,它看起来像这样:
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)
对于动态表,我确信有办法用纯 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)
希望对您有所帮助。
【讨论】:
【参考方案2】:试试这个方法
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
【讨论】:
以上是关于如何使用 Arel 跨多态 has_one 关系进行查询的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Arel(大概)创建一个不影响 Rails 3 中的查询的 ActiveRecord 范围?
Rails 中具有相同键的两个表而不是 has_one 关系