代码之家  ›  专栏  ›  技术社区  ›  anon_swe

rubyonrails:对两个字段使用关联?

  •  0
  • anon_swe  · 技术社区  · 5 年前

    我的Rails应用程序中目前有两个模型: Team Player ,如下所示:

    class Team < ApplicationRecord
      has_many :players
    end
    
    class Player < ApplicationRecord
      belongs_to :team
    end
    

    我想添加一个 Matchup 代表两队互相比赛。在正常的OOP环境中,我可能会执行以下操作:

    class Matchup
      attr_accessor :first_team, :second_team
    end
    

    但我不是100%确定Rails的惯用设置方式是什么。我正在考虑的一些选择:

    对决 有许多团队和 团队 属于许多对决。这有点尴尬,因为现在我不能为每个字段指定一个字段 first_team second_team

    2) 坚持面向对象的方法。 有两个字段: 一队 二队 团队 物体。因为我主要计划允许用户查看匹配,所以这里不需要资源丰富的路由。

    提前感谢您的帮助!

    0 回复  |  直到 5 年前
        1
  •  3
  •   CWitty    5 年前

    一场比赛可以分为两队。您可以指定不同的关联名称,然后告诉它要使用的类。

    belongs_to :team_a, class_name: "Team"
    belongs_to :team_b, class_name: "Team"
    

    然后一支球队有很多对手,这也是有道理的。

        2
  •  0
  •   max Mike Williams    5 年前

    仅仅在匹配表上放置两个外键列似乎是最简单的解决方案,但问题出在细节上。既然有两个外键,就不能只创建一个 has_many :matchups 关联,因为Rails无法知道匹配中的哪个列对应于 teams.id

    class Team
      has_many :matchups_as_a, class_name: "Matchup"
                               foreign_key: 'team_a'
      has_many :matchups_as_b, class_name: "Matchup"
                               foreign_key: 'team_b'
      def matchups
         matchups_as_a + matchups_as_b
      end
    end
    

    这会破坏秩序和其他很多事情。

    或:

    Matchup.where('team_a = :x OR team_b = :x', x: team)
    

    class Matchup
      has_many :matchup_teams
      has_many :teams, though: :matchup_teams
    end
    
    # rails g model MatchupTeam match_up:references team:references
    class MatchupTeam
      belongs_to :match_up
      belongs_to :team
    end
    
    class Team
      has_many :matchup_teams
      has_many :matchups, through: :matchup_teams
    end
    

    这看起来可能更复杂,但实际上让你做到:

    team.matchups
    matchup.teams
    
    # Get matchups between team and other_team
    matches = Matchups.joins(:teams)
               .where(teams: { id: [team, other_team] })
               .group('matchups.id')
               .having('count(*) = 2')