假设我们有这两个模型:
class Attendee < ActiveRecord::Base
has_many :dances
has_many :partners, through: :events
end
class Dance < ActiveRecord::Base
belongs_to :attendee
belongs_to :partner, class_name: Attendee
end
我想实现一种方法,例如Dance.matches_of(attendee)
,只有当他的伙伴有一个他是合作伙伴的舞蹈时才会返回与会者的舞蹈。您将如何实施有效的解决方案?
编辑:
很抱歉,因为我无法很好地解释我的问题,我会尝试澄清它(我将Event
班级名称更改为Dance
)。如果用户想要与另一个人跳舞,他/她将创建一个对象Dance
,指定合作伙伴。所以,让我们说Bob想和Sarah一起跳舞,数据库表dances
看起来像这样(我会使用用户名而不是id来让它更清晰,希望如此):
| id | attendee_id | partner_id |
---------------------------------------------------
| 1 | bob | sarah |
所以,Dance.matches_of(bob)
没有任何回报,因为没有人想和他跳舞,谁也想要他作为舞伴(可怜的鲍勃)。过了一会儿,莎拉认为鲍勃可能并不是一个坏人,他应该有机会发言。现在,dances
表看起来像这样:
| id | attendee_id | partner_id |
---------------------------------------------------
| 1 | bob | sarah |
---------------------------------------------------
| 2 | sarah | bob |
Dance.matches_of(bob)
现在返回id为1的舞蹈,因为这是显示Bob对与Sarah一起跳舞的兴趣的记录,并且Sarah也希望与他一起跳舞(Dance.matches_of(sarah)
将检索第二条记录)。如果鲍勃也想与安娜一起跳舞,那么她也是如此,这个方法会找回两个记录,鲍勃将成为派对中最快乐的人,因为他有两个舞伴。
我希望这个解释更清楚,但我知道如果解释和理解起来很难,也许我所遵循的方法不正确,所以我愿意接受建议。
编辑2:
我提出的解决方案:
def self.matches_of(attendee)
attendee.dances.select { |dance| dance.partner.partners.include? attendee }
end
但我不认为它的效率会高得多。
答案 0 :(得分:2)
根据您的模型,您可以向Dance模型添加matches_of
范围:
class Attendee < ActiveRecord::Base
has_many :dances
has_many :partners, class_name: 'Attendee', through: :dances
end
class Dance < ActiveRecord::Base
belongs_to :attendee
belongs_to :partner, class_name: 'Attendee'
scope :matches_of, -> (attendee) {
where(partner_id: attendee.id, attendee_id: attendee.partner_ids)
}
end
给出像
这样的舞蹈| id | attendee_id | partner_id |
---------------------------------------------------
| 1 | bob | sarah |
matches_of将返回[]
bob = Attendee.find 1
Dance.matches_of(bob)
# returns []
给出像
这样的舞蹈| id | attendee_id | partner_id |
---------------------------------------------------
| 1 | bob | sarah |
---------------------------------------------------
| 2 | sarah | bob |
matches_of将返回Dance#2
Dance.matches_of(bob)
# returns [#<Dance id: 2, attendee_id: 2, partner_id: 1>]
答案 1 :(得分:0)
如果partner_id
与id
表中的attendees
相关,我可以考虑这样的方法:
def partner_events
Event.where('partner_id = ? and attendee_id in (?)', id, events.map(&:partner_id))
end
答案 2 :(得分:0)
def matches_of(attendee)
partner_ids = Event.pluck(:attendee_id).where(:partern_id = > attendee.id).uniq
Event.where('attendee_id = ? and partner_id in (?)', attendee.id, partner_ids)
end