简体   繁体   English

Rails-在关系模型中查找匹配项

[英]Rails - Find matches in relation model

Let's say we have these two models: 假设我们有以下两种模型:

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

I'd like to implement a method, for example Dance.matches_of(attendee) that returns the dances of an attendee only if his partners have a dance where he is the partner. 我想实现一个方法,例如Dance.matches_of(attendee) ,该方法仅在参与者的伙伴在伙伴所在的地方跳舞时才返回参与者的舞蹈。 How would you implement an efficient solution? 您将如何实施有效的解决方案?

EDIT: 编辑:

Sorry because I couldn't explain my question well, I'll try to clarify it (I changed the Event class name to Dance ). 抱歉,因为我无法很好地解释我的问题,因此我将尝试澄清该问题(我将Event类的名称更改为Dance )。 If an user wants to dance with another one, he/she will create an object Dance , specifying the partner. 如果用户想与另一个人跳舞,他/她将创建一个对象Dance ,指定伙伴。 So, let's say that Bob would like to dance with Sarah, the database table dances would look like this (I'll use usernames instead of ids to make it clearer, hopefully): 因此,假设鲍勃想与莎拉共舞,数据库的表dances看起来像这样(希望我会使用用户名而不是ID使其更清楚):

|    id    |    attendee_id    |    partner_id    |
---------------------------------------------------
|    1     |       bob         |       sarah      |

So, Dance.matches_of(bob) would return nothing, as there is no one that he wants to dance with who also wants him as a dancing partner (poor Bob). 因此, Dance.matches_of(bob)将不返回任何内容,因为没有人愿意与谁跳舞,而谁也希望他作为舞伴(可怜的鲍勃)。 After a while Sarah thinks that maybe Bob is not such a bad guy, and he deserves a chance to hit the floor. 过了一会儿,莎拉认为也许鲍勃不是一个坏人,他应该有机会发言。 Now, the dances table looks like this: 现在, dances表如下所示:

|    id    |    attendee_id    |    partner_id    |
---------------------------------------------------
|    1     |       bob         |       sarah      |
---------------------------------------------------
|    2     |      sarah        |        bob       |

Dance.matches_of(bob) now returns the dance with id 1, because it's the record that shows Bob's interest on dancing with Sarah AND Sarah wants to dance with him as well ( Dance.matches_of(sarah) would retrieve the second record). Dance.matches_of(bob)现在返回ID为1的舞蹈,因为这是记录,显示鲍勃有兴趣与Sarah跳舞,并且Sarah也想与他跳舞( Dance.matches_of(sarah)将检索第二个记录)。 If Bob wanted to dance with Anna too, and so did she, the method would retrieve two records and Bob would be the happiest guy at the party, as he'd have two dancing partners. 如果鲍勃也想和安娜一起跳舞,那么她也一样,该方法将检索两个记录,而鲍勃将是聚会上最快乐的家伙,因为他有两个舞伴。

I hope this explanation is clearer, but I'm aware that if it's so hard to be explained and understood, maybe the approach I'm following is not correct, so I'm open to suggestions. 我希望这个解释更清楚,但是我知道,如果很难解释和理解它,也许我所遵循的方法是不正确的,所以我愿意提出建议。

EDIT 2: 编辑2:

The solution I came up with: 我想出的解决方案:

def self.matches_of(attendee) 
    attendee.dances.select { |dance| dance.partner.partners.include? attendee }
end

But I don't expect it to be much efficient anyway. 但是我不希望它有任何效率。

Given your models, you can add a matches_of scope to the Dance model: 给定您的模型,您可以将matches_of范围添加到Dance模型:

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

Given dances like 像这样跳舞

|    id    |    attendee_id    |    partner_id    |
---------------------------------------------------
|    1     |       bob         |       sarah      |

matches_of will return [] matchs_of将返回[]

bob = Attendee.find 1
Dance.matches_of(bob) 
# returns []

Given dances like 像这样跳舞

|    id    |    attendee_id    |    partner_id    |
---------------------------------------------------
|    1     |       bob         |       sarah      |
---------------------------------------------------
|    2     |      sarah        |        bob       |

matches_of will return Dance #2 matchs_of将返回舞蹈#2

Dance.matches_of(bob) 
# returns [#<Dance id: 2, attendee_id: 2, partner_id: 1>]

I can think of a method like this, if there is a partner_id relating to an id in attendees table: 我可以想到这样的方法,如果在attendees表中有一个与id有关的partner_id

def partner_events
    Event.where('partner_id = ? and attendee_id in (?)', id, events.map(&:partner_id))
end
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

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

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