【问题标题】:Rails Associations StructureRails 关联结构
【发布时间】:2021-05-17 14:23:53
【问题描述】:

如何通过关联构建这 3 个模型?

问题

我在为我正在进行的个人项目设置模型关联时遇到了很多麻烦。本质上,我正在构建一个由 3 个模型组成的裁判分配系统:

  1. Assignor:为比赛分配裁判的用户
  2. 裁判:分配给比赛的用户
  3. 比赛:分配了 1-4 名裁判

到目前为止,我的模型中有:

class Assignor < ApplicationRecord
  has_many :games
  has_many :referees
  has_many :assigned_referees, through:referees
end

class Game < ApplicationRecord
  belongs_to :assignor
  has_many :referees
end

class Referee < ApplicationRecord
  has_many :assignors
  has_many :games, through: :assignor
  has_many :assigned_games, :through:assignor
end 

我想在我的应用中处理这些关联是:

  1. 列出转让人拥有的裁判 => Assignor.referees
  2. 列出裁判拥有的分配者 => Referee.assignors

我遇到问题的地方是……

  1. 列出分配给比赛的裁判
  2. 列出未分配给比赛的裁判 -例如: 如果用户(分配者)要启动游戏并分配裁判,我想制作一个下拉列表,其中填充未分配的裁判列表

【问题讨论】:

    标签: ruby-on-rails model associations


    【解决方案1】:

    我会选择 3 路连接表:

    class Game < ApplicationRecord
      has_many :referee_assignments
      has_many :referees, 
        through: :referee_assignments,
        inverse_of: :assigned_games
      has_many :assigners, 
        through: :referee_assignments
    
      def build_assignment(referee:, assigner:)
        referee_assignments.new(
          referee: referee.
          assigner: assigner
        )
      end
    end
    
    class RefereeAssignment
      # User who assigned the referee
      belongs_to :assigner, 
        class_name: 'User'
      belongs_to :game
      belongs_to :referee
    end
    
    class Referee < ApplicationRecord
      has_many :referee_assignments
      has_many :assigners, 
        through: :referee_assignments
      has_many :assigned_games,
        through: :referee_assignments,
        source: :game,
        inverse_of: :referees
    
      def build_assignment(game:, assigner:)
        referee_assignments.new(
          game: game,
          assigner: assigner
        )
      end
    end 
    

    列出分配给比赛的裁判

    game = Game.find(1)
    game.referees.each do |r|
      # ...
    end
    

    列出未分配给比赛的裁判

    referees = Referee.where.not(
      id: game.referees
    )
    

    使用子查询是最简单的方法,但您也可以使用NOT EXIST 或连接。

    【讨论】:

    • 我从来没有这样想过,谢谢你的帮助。菜鸟问题:我需要为 RefereeAssignment 生成连接表吗?分配器模型和我一样吗?
    • 是的,您需要运行 rails g model RefereeAssignment assigner:references game:references referee:references 并将这一行 t.references :assigner, null: false, foreign_key: true 更改为 t.references :assigner, null: false, foreign_key: { to_table: :users }。不需要分配器模型,可以废弃。
    • 我在这里假设您有一个像 User 这样的类,它代表您应用程序中的用户。
    • 我认为我需要运行该迁移,并且我正在使用 Devise 进行用户身份验证,这就是为什么我有两个“用户”模型(Assignor 和Referee)可以这么说,以便用户可以登录他们各自的帐户并在登录后执行他们需要做的事情。不确定这是否会改变任何事情......
    • 那么你会改变 foreign_key: { to_table: :assignors } 和 `belongs_to :assigner, class_name: 'Assignor'`。这里的语法很奇怪。否则它真的是一样的。这与您的解决方案略有不同,因为游戏可以有许多分配者。
    猜你喜欢
    • 2014-04-15
    • 2016-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-25
    • 1970-01-01
    • 1970-01-01
    • 2016-03-20
    相关资源
    最近更新 更多