简体   繁体   English

ActiveRecord Rails 如何在多态关联中查询关联模型

[英]ActiveRecord Rails How do you query for an associated model in a polymorphic association

I have a polymorphic association on my PartnerItem model :我的PartnerItem模型上有一个多态关联:

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

Item can be a program or a session项目可以是programsession

Program is also linked to sessions in a has_many relationship : Program has_many Sessions Program还以has_many关系链接到sessionsProgram has_many Sessions

I need to find all Programs to which a partner_item is linked.我需要找到partner_item链接到的所有Programs That means这意味着

Any program / item associated to a specific partner与特定合作伙伴关联的任何program / item

Any program linked to a session/item associated to a specific partner.链接到与特定合作伙伴关联的session/item任何program

Finally the query results need to be unique, meaning a Program can't appear twice in the results最后查询结果必须是唯一的,这意味着一个Program不能在结果中出现两次

I am having a hard time figuring out how to assemble such query.我很难弄清楚如何组合这样的查询。

This retrieves all items for a specific partner but Im stuck on what are the next steps这将检索特定partner所有items ,但我坚持下一步是什么

  PartnerItem.where(
     partner: current_partner
   ).items

One way to do could be like this:一种方法可能是这样的:

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)

This would probably return all the Program records which have a PartnerItem directly or through Session .这可能会直接或通过Session返回所有具有PartnerItemProgram记录。

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

If I understand correctly, this is almost what you:如果我理解正确,这几乎就是你:

current_partner.partners_items

want except then you get models with a reference to the program or to the session and when the session you want the program it belongs to.想要除此之外,您会获得包含对程序或会话的引用的模型,以及您希望该程序所属的会话的时间。

In SQL this would be:在 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 = ?

Because the joins have a different structure the SQL is going to need a UNION or a subquery which is hard to express in one query using ActiveRecord.因为连接具有不同的结构,所以 SQL 将需要一个 UNION 或一个子查询,这在使用 ActiveRecord 的查询中很难表达。

First I would add scopes for the polymorphic types.首先,我会为多态类型添加作用域。

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

  scope :programs, -> { where(type: 'Program') }
  scope :sessions, -> { where(type: 'Session') }
end

Then you might query for the program ids and the session ids for the current partner and use that in the final query.然后,您可以查询当前合作伙伴的程序 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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM