【问题标题】:association and migration between users and teams (rails)用户和团队之间的关联和迁移(rails)
【发布时间】:2014-08-09 00:04:59
【问题描述】:

我有这个具有以下关联的用户和团队模型:

用户.rb

class User < ActiveRecord::Base
    belongs_to :team

team.rb

class Team < ActiveRecord::Base
    has_many :users
    has_one :leader, class_name: "User", foreign_key: "leader_id"
    belongs_to :manager, class_name: "User", foreign_key: "manager_id"

但我似乎无法想象将其正确地表示为迁移。起初,我是这样做的:

class AddTeamIdToUsers < ActiveRecord::Migration
    def change
        add_column :users, :team_id, :integer
        add_index :users, :team_id
    end
end

class AddUsersToTeams < ActiveRecord::Migration
    def change
        add_reference :teams, :leader, index: true
        add_reference :teams, :manager, index: true     
    end
end

当然,我在AddTeamToIdUsers 上所做的是多对一关联,因为Team 可以有多个Users,但领导职位 应该只是仅限特定团队(成员也是如此,他们不应该属于其他团队)。但是,经理可以拥有许多团队来管理。回到我的关注点,我如何将我的场景表示为迁移?或者我应该在我的协会中做出任何调整?在考虑了必要的调整和解决方案后,应用程序是否会在添加/更新团队时自动遵循关联规则?

【问题讨论】:

  • 如果用户管理一个团队,他们是否被称为该团队的“一部分”,即他们会被包含在team.users 中吗?领导呢?
  • 你的两个答案都是肯定的。 leader 和 manager 都是用户属性 type 的值(默认为 worker)。
  • 领导者或工人是否也可以是团队的经理,即一个用户可以有多种类型?

标签: ruby-on-rails ruby activerecord associations rails-migrations


【解决方案1】:

您的迁移看起来正确,但您的关联不完整:

class User < ActiveRecord::Base
  belongs_to :team
  has_one :leading_team, class_name: 'Team', foreign_key: 'leader_id'
  has_many :managed_teams, class_name: 'Team', foreign_key, 'manager_id'

class Team < ActiveRecord::Base
  has_many :users
  belongs_to :leader, class_name: "User"
  belongs_to :manager, class_name: "User"

你应该准备好了。

【讨论】:

    【解决方案2】:

    因为经理可以拥有多个团队,但仍然是团队的“一部分”,我建议为 usersteams 创建一个联接表。我们称之为members。它将同时引用userteam

    class CreateMembers < ActiveRecord::Migration
      def change
        create_table :members do |t|
          t.references :user
          t.references :team
    
          t.timestamps
        end
      end
    end
    

    然后,我们需要将 members 关联添加到 User 模型。用户将有许多成员,并且由于经理的原因,也有许多团队。我还包含了一个获取工人或领导团队的功能,因为只有一个。

    class User < ActiveRecord::Base
      has_many :members
      has_many :teams, through: members, dependent: destroy
    
      validates_associated :members # More on this later
    
      # for workers and leaders
      def team
        self.teams.first
      end
    end
    

    User 模型类似,我们需要将members 关联添加到Team 模型。我们还将包含一些函数来获取团队的领导和经理,以及验证以确保团队只有一名领导和一名经理。

    class Team < ActiveRecord::Base
      has_many :members
      has_many :users, through: :members, dependent: destroy
    
      validate :has_one_leader_and_manager
      validates_associated :members # More on this later
    
      def manager
        self.users.where(type: 'manager').first
      end
    
      def leader
        self.users.where(type: 'leader').first
      end
    
      def has_one_leader_and_manager
        ['leader', 'manager'].each do |type|
          unless self.users.where(type: type).count == 1
            errors.add(:users, "need to have exactly one #{type}")
          end
        end
      end
    end
    

    最后,我们将设置 Member 模型。我们还可以包括一些验证,以确保一个团队只能有一名领导和一名经理,并且工人和领导不能属于多个团队。

    class Member < ActiveRecord::Base
      belongs_to :user
      belongs_to :team
    
      validate :team_has_one_leader_and_manager
    
      # Make sure player (worker or leader) is only on one team
      validates :user_id, uniqueness: true, if: :is_player?
    
      def is_player?
        ['worker', 'leader'].include? user.type
      end
    
      def team_has_one_leader_and_manager
        if ['leader', 'manager'].include?(user.type)
          if team.users.where('type = ? AND id != ?' user.type, user_id).count.any?
            errors.add(:team, "can't add another #{user.type}")
          end
        end
      end
    end
    

    请注意,对于验证方法,您可能需要移动它们和/或重构它们,具体取决于您添加用户和团队的方式以及添加新成员的方式。不过,这个答案有望为您提供足够的信息以帮助您入门。

    【讨论】:

    • 由于您添加了 Members 模型,我的用户表中的 team_id 外键是否仍然是必需的?
    • 哦,太好了。您的users 表中不需要team_id
    • 顺便说一句,对于我的表单页面,它应该有一个经理和领导者的下拉列表,以便于识别.. 对于成员的下拉列表,我将尝试 select2。 . 那么,我将如何隔离经理和领导者的选择?
    • 您可以使用类似于User.where(type: 'manager') 的内容作为可能的经理的列表。你可以为领导者使用类似的东西。
    • 好的,但是保存前Team.new(team_params) 中的team_params 的内容是什么?只有members(因为领导和经理是members的一部分)?
    猜你喜欢
    • 2020-08-15
    • 1970-01-01
    • 2013-10-24
    • 1970-01-01
    • 2016-08-30
    • 2021-07-06
    • 1970-01-01
    • 2013-04-29
    • 1970-01-01
    相关资源
    最近更新 更多