【问题标题】:ActiveRecord Rails How do you query for an associated model in a polymorphic associationActiveRecord Rails 如何在多态关联中查询关联模型
【发布时间】:2021-07-13 08:27:33
【问题描述】:

我的PartnerItem 模型上有一个多态关联:

class PartnersItem < ApplicationRecord
  belongs_to :item, polymorphic: true
  belongs_to :partner
end

项目可以是programsession

Program 也以has_many 关系链接到sessionsProgram has_many Sessions

我需要找到partner_item 链接到的所有Programs。这意味着

与特定合作伙伴关联的任何program / item

任何program 链接到与特定合作伙伴关联的session/item

最后查询结果需要是唯一的,这意味着Program不能在结果中出现两次

我很难弄清楚如何组装这样的查询。

这会检索特定partner 的所有items,但我坚持下一步是什么

  PartnerItem.where(
     partner: current_partner
   ).items

【问题讨论】:

    标签: ruby-on-rails activerecord polymorphic-associations


    【解决方案1】:

    一种方法可能是这样的:

    program_ids = PartnerItem.where(partner: current_partner, item_type: 'Program').pluck(:item_id)
    program_ids += Session.joins(:partner_items).where(partner_items: { partner_id: partner.id }).where.not(program_id: nil).pluck(:program_id)
    Program.where(id: program_ids.uniq)
    

    这可能会直接或通过Session 返回所有具有PartnerItemProgram 记录。

    【讨论】:

      【解决方案2】:
      partner_items = PartnerItem.where(partner: current_partner)
      problem_ids = partner_items.filter { |x| x.item_type == "Program" }.map(&:item_id)
      session_ids = partner_items.filter { |x| x.item_type == "Session" }.map(&:item_id)
      Problem.joins(:sessions)
      .where("problems.id IN (?) OR sessions.id IN (?)", problem_ids, session_ids)
      .distinct
      

      【讨论】:

        【解决方案3】:

        如果我理解正确,这几乎就是你的:

        current_partner.partners_items
        

        希望你得到模型与程序或会话的引用以及你想要它所属的程序的会话时间。

        在 SQL 中是:

        SELECT programs.*
        FROM programs
          INNER JOIN partners
            ON partners.item_type = 'Program' and partners.item_id = programs.id
        WHERE partners.id = ?
        
        UNION
        
        SELECT programs.*
        FROM programs
          INNER JOIN sessions
            ON sessions.program_id = programs.id
          INNER JOIN partners
            ON sessions.item_type = 'Session' and partners.item_id = sessions.id
        WHERE partners.id = ?
        

        由于连接具有不同的结构,SQL 将需要一个 UNION 或子查询,这很难在一个使用 ActiveRecord 的查询中表达。

        首先我要为多态类型添加作用域。

        class PartnersItem < ApplicationRecord
          belongs_to :item, polymorphic: true
          belongs_to :partner
        
          scope :programs, -> { where(type: 'Program') }
          scope :sessions, -> { where(type: 'Session') }
        end
        

        然后您可以查询当前合作伙伴的程序 ID 和会话 ID,并在最终查询中使用。

        partner_program_ids = current_partner.partners_items.programs.pluck(:id)
        partner_session_ids = current_partner.partners_items.sessions.pluck(:id)
        
        Program.joins(:session)
            .where("programs.id = :partner_program_ids
                   OR sessions.id = :partner_session_ids",
                   partner_program_ids: partner_program_ids,
                   partner_session_ids: partner_session_ids)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-10-15
          • 1970-01-01
          • 1970-01-01
          • 2023-03-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多