Rails - 过滤多对多

Posted

技术标签:

【中文标题】Rails - 过滤多对多【英文标题】:Rails - filter many to many 【发布时间】:2021-12-09 23:58:11 【问题描述】:

“事件”和“成员”之间存在多对多关系。我目前正在尝试过滤掉不属于某个成员的所有事件。

我可以做相反的事情,我可以选择属于特定事件的所有事件。我就是这样做的:

class Event < ApplicationRecord
  has_and_belongs_to_many :members
  scope :filter_by_member, -> (member)  joins(:members).where( members:  id: member.id  ) 
end
class Member < ApplicationRecord
  has_and_belongs_to_many :events
end

但是,我试图通过将where 更改为where.not 来获得反向行为(所有不属于成员的事件);这只是选择事件表中的所有记录。

在将where 切换为where.not 后,我试图在rails 控制台中获取所有不属于成员的事件。但是,正确的输出应该是在最后一行中选择了事件 2 和 3(因为事件 1 属于 sample_member);三个都被选中了。

irb(main):001:0> sample_member = Member.find(2)
  Member Load (0.3ms)  SELECT "members".* FROM "members" WHERE "members"."id" = $1 LIMIT $2  [["id", 2], ["LIMIT", 1]]
=> #<Member id: 2, uid: nil, name: "John", created_at: "2021-10-23 14:30:38.434442000 -0500", updated_at: "2021-10-23 14:30:38.434442000 -0500", isAdmin: nil, email: nil>
irb(main):002:0> sample_member.events
  Event Load (0.4ms)  SELECT "events".* FROM "events" INNER JOIN "events_members" ON "events"."id" = "events_members"."event_id" WHERE "events_members"."member_id" = $1  [["member_id", 2]]
=> 
[#<Event:0x00007f02f0aeb4e8
  id: 1,
  date: nil,
  description: "Please come",
  isMandatory: nil,
  location: nil,
  admin_id: nil,
  created_at: Sat, 23 Oct 2021 14:27:32.966994000 CDT -05:00,
  updated_at: Sat, 23 Oct 2021 14:27:32.966994000 CDT -05:00,
  time: nil,
  datetime: nil,
  name: "Fun event">]
irb(main):003:0> Event.filter_by_member sample_member
  Event Load (0.3ms)  SELECT "events".* FROM "events" INNER JOIN "events_members" ON "events_members"."event_id" = "events"."id" INNER JOIN "members" ON "members"."id" = "events_members"."member_id" WHERE "members"."id" != $1  [["id", 2]]
=> 
[#<Event:0x00005651319bf3d8
  id: 1,
  date: nil,
  description: "Please come",
  isMandatory: nil,
  location: nil,
  admin_id: nil,
  created_at: Sat, 23 Oct 2021 14:27:32.966994000 CDT -05:00,
  updated_at: Sat, 23 Oct 2021 14:27:32.966994000 CDT -05:00,
  time: nil,
  datetime: nil,
  name: "Fun event">,
 #<Event:0x00005651319bf270
  id: 2,
  date: nil,
  description: "Important",
  isMandatory: nil,
  location: nil,
  admin_id: nil,
  created_at: Sat, 23 Oct 2021 14:29:39.380136000 CDT -05:00,
  updated_at: Sat, 23 Oct 2021 14:29:39.380136000 CDT -05:00,
  time: nil,
  datetime: nil,
  name: "Conference">,
 #<Event:0x00005651319bf158
  id: 3,
  date: nil,
  description: "this is orientation",
  isMandatory: false,
  location: "",
  admin_id: nil,
  created_at: Sat, 23 Oct 2021 14:39:13.186162000 CDT -05:00,
  updated_at: Sat, 23 Oct 2021 14:39:13.186162000 CDT -05:00,
  time: nil,
  datetime: nil,
  name: "orientation">]

有什么线索吗?

【问题讨论】:

你首先不需要那个范围。只需member.events 【参考方案1】:

最简单的方法是使用WHERE events.id NOT IN (...) 子查询:

Event.where.not(
  id: member.events
)

【讨论】:

以上是关于Rails - 过滤多对多的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate映射( 多对一对一对多多对多)的配置方法

Rails Api 多对多如何发送和处理 json

如何在rails的同一个表中创建多对多

总结一下数据库的 一对多多对一对多对多 关系

如何在 Rails 中为多对多关系(和中间表)做一个选择字段?

如何在 Rails 4.2 中为多对多关联创建表单