【问题标题】:Rails - Find matches in relation modelRails - 在关系模型中查找匹配项
【发布时间】:2014-07-01 13:17:03
【问题描述】:

假设我们有这两个模型:

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) 不会返回任何内容,因为没有一个他想和他一起跳舞的人也希望他作为舞伴(可怜的 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) 将检索第二个记录)。如果 Bob 也想和 Anna 一起跳舞,Anna 也想跳舞,那么该方法将检索两条记录,并且 Bob 将是派对上最快乐的人,因为他有两个舞伴。

我希望这个解释更清楚,但我知道如果它很难解释和理解,也许我遵循的方法不正确,所以我愿意接受建议。

编辑 2:

我想出的解决方案:

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

但我不希望它有效率。

【问题讨论】:

  • 你能举一个更具体的例子吗?
  • 你的命名有点“黑暗”/令人困惑/不清楚。 Event 实际上是与会者之间的耦合--> 他们表示对彼此感兴趣,您想找到对彼此感兴趣的与会者吗?但它根本没有与贸易展之类的“事件”相关联,afaik?
  • 活动中有partner_id和attendee_id?
  • @nathanvda 正是你所说的,一个用户可以对另一个用户表现出兴趣,如果兴趣是相互的,我正在寻找的方法应该返回用户的事件。

标签: sql ruby-on-rails activerecord ruby-on-rails-4


【解决方案1】:

根据您的模型,您可以将 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

鉴于舞蹈喜欢

|    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>]

【讨论】:

  • @davids,我更新了我的答案。这就是你要找的吗?
【解决方案2】:

如果attendees表中有一个id相关的partner_id,我可以想到这样的方法:

def partner_events
    Event.where('partner_id = ? and attendee_id in (?)', id, events.map(&:partner_id))
end

【讨论】:

    【解决方案3】:
    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多