You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于多关联表构建带作用域的has_many关联以实现Ransack标签搜索

解决方案:为Low模型添加包含继承标签的关联以支持Ransack搜索

要实现无需冗余存储、能被Ransack识别的完整标签集合,你可以在Low模型中通过自定义SQL的has_many关联来合并自身、关联Middle及Top的标签,具体实现如下:

class Low < ApplicationRecord
  has_many :low_tags, dependent: :destroy
  has_many :tags, through: :low_tags
  has_many :middle_foos, dependent: :destroy
  has_many :middles, through: :middle_foos

  # 定义包含所有继承标签的关联
  has_many :all_tags, ->(low) {
    from(
      <<-SQL.squish, 'tags'
        SELECT tags.* FROM tags
        JOIN low_tags ON low_tags.tag_id = tags.id
        WHERE low_tags.low_id = #{low.id}

        UNION

        SELECT tags.* FROM tags
        JOIN middle_tags ON middle_tags.tag_id = tags.id
        JOIN middle_lows ON middle_lows.middle_id = middle_tags.middle_id
        WHERE middle_lows.low_id = #{low.id}

        UNION

        SELECT tags.* FROM tags
        JOIN top_tags ON top_tags.tag_id = tags.id
        JOIN middles ON middles.top_id = top_tags.top_id
        JOIN middle_lows ON middle_lows.middle_id = middles.id
        WHERE middle_lows.low_id = #{low.id}
      SQL
    )
  }, class_name: 'Tag', primary_key: :id, foreign_key: :id

  # 允许Ransack搜索该关联
  def self.ransackable_associations(auth_object = nil)
    super + ['all_tags']
  end
end

代码说明

  1. 关联逻辑:
    • 通过UNION合并三个标签来源:Low自身标签、关联Middle的标签、关联Top的标签(通过Middle间接关联)
    • UNION会自动去重重复标签,若需保留重复可替换为UNION ALL
  2. Rails关联配置:
    • 使用class_name: 'Tag'指定关联模型为Tag
    • primary_key和foreign_key用于匹配自定义SQL结果集与Tag模型的主键
  3. Ransack支持:
    • 重写ransackable_associations方法,将all_tags加入可搜索关联列表,确保Ransack能识别该关联

使用示例

你可以直接通过Ransack基于all_tags进行搜索:

# 搜索包含名称为"ruby"标签的Low实例
Low.ransack(all_tags_name_eq: 'ruby').result

# 搜索包含任意指定标签的Low实例
Low.ransack(all_tags_name_in: %w[rails backend]).result

注意事项

原模型中Low关联Middle的join table命名为middle_foos,但Middle中使用的是middle_lows,若数据库实际join table为middle_lows(对应MiddleLow模型),需将Low中的middle_foos关联修正为middle_lows,否则会导致关联查询失败。

内容的提问来源于stack exchange,提问作者Slth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 15:55:20