使用Ransack实现多态关联下多模型搜索是否可行?
跨多态关联模型的Ransack搜索实现方案
错误原因
Ransack原生不支持直接对多态关联同时指定多个关联类型进行字段查询,无法自动识别不同关联模型的字段映射规则,因此会抛出Polymorphic associations do not support computing the class.报错。
方案1:自定义ransacker(最简实现)
适合仅需要搜索Subscription和Purchase共有的status字段的场景,直接在Invoice模型中添加自定义搜索字段:
class Invoice < ApplicationRecord belongs_to :invoiceable, polymorphic: true # 自定义多态关联status的搜索字段 ransacker :invoiceable_status do Arel.sql("CASE WHEN invoices.invoiceable_type = 'Subscription' THEN (SELECT status FROM subscriptions WHERE id = invoices.invoiceable_id) WHEN invoices.invoiceable_type = 'Purchase' THEN (SELECT status FROM purchases WHERE id = invoices.invoiceable_id) END") end # 允许ransack识别该自定义字段 def self.ransackable_attributes(auth_object = nil) super + %w[invoiceable_status] end end
视图层直接使用该自定义字段即可:
<%= f.check_box :invoiceable_status_in, { multiple: true }, type[1], false %>
方案2:显式定义单态关联(灵活扩展)
如果后续需要搜索Subscription和Purchase的多个不同字段,可以先在Invoice模型中单独定义针对两种多态类型的关联:
class Invoice < ApplicationRecord belongs_to :invoiceable, polymorphic: true # 单独绑定两种多态类型的关联 has_one :subscription, -> { where(invoices: {invoiceable_type: 'Subscription'}) }, foreign_key: 'id', primary_key: 'invoiceable_id' has_one :purchase, -> { where(invoices: {invoiceable_type: 'Purchase'}) }, foreign_key: 'id', primary_key: 'invoiceable_id' # 允许ransack搜索这两个关联 def self.ransackable_associations(auth_object = nil) super + %w[subscription purchase] end end
视图层直接使用Ransack原生的OR条件查询语法即可:
<%= f.check_box :subscription_status_or_purchase_status_in, { multiple: true }, type[1], false %>
内容的提问来源于stack exchange,提问作者pinkfloyd90
相关产品推荐
相关产品推荐

