【问题标题】:How to use Arel to query across a polymorphic has_one relationship如何使用 Arel 跨多态 has_one 关系进行查询
【发布时间】: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。

【问题讨论】:

    标签: ruby-on-rails activerecord datatables arel


    【解决方案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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-08-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多