用户和团队之间的关联和迁移(导轨) [英] association and migration between users and teams (rails)

查看:79
本文介绍了用户和团队之间的关联和迁移(导轨)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have this User and team model which has the following association:

user.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"

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

but it seems that I can't imagine representing it properly into a migration. At first, this is what I did:

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 上所做的自团队以来的多对一关联可以拥有许多个用户,但是领导者职位只能仅适用于特定团队(成员也一样,他们不应该属于其他团队)。 经理,但是,可以拥有许多团队进行管理。回到我的关注点,如何将我的情况表示为迁移?还是我应该对我的协会进行任何调整?在考虑了必要的调整和解决方案之后,应用程序会在添加/更新团队时自动遵循关联规则吗?

for sure, what I did on AddTeamToIdUsers was a many-to-one association since a Team can have many Users, but the leader position should only be exclusive for a specific team only (same goes to members as well, they should not belong to other teams). Managers, however, can have many teams to manage. Going back to my concern, how can I represent my scenario into a migration? Or are there any adjustments I should make in my associations? After the necessary adjustments and solutions considered, will the application automatically follow the association rules upon adding/updating teams?

推荐答案

因为是管理员可以有多个团队,但仍然是团队的一部分,我建议为用户 teams 。我们称其为个成员。它将同时引用用户 team

Because a manager can have multiple teams, but is still "part of" the team, I'd suggest creating a join table for users and teams. We'll call it members. It will reference both user and team.

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

      t.timestamps
    end
  end
end

然后,我们需要将 members 关联添加到用户模型。用户将有许多成员,并且由于管理员的原因,还将有许多团队。我还提供了一个使工人或领导者团队化的功能,因为只有一个。

Then, we'll need add the members association to the User model. Users will have many members, and, because of managers, have many teams as well. I've also included a function to get the team of a worker or leader, since there's only one.

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 模型,我们需要添加成员关联到团队模型。我们还将包括一些获取团队领导者和经理的功能,并进行验证以确保团队中只有一位领导者和一位经理。

Similar to the User model, we'll need to add the members association to the Team model. We'll also include a few functions to get the leader and manager of a team, and validation to make sure a team has exactly one leader and one manager.

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

最后,我们将设置成员模型。我们还可以进行一些验证,以确保一个团队只能有一个领导者和一个经理,并且工人和领导者不能属于一个以上的团队。

Lastly, we'll set up the Member model. We can also include some validation to ensure that a team can only have one leader and one manager, and that workers and leader cannot belong to more than one team.

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

请注意,使用验证方法时,您可能需要移动它们和/或对其进行重构,具体取决于添加用户的方式和团队,以及如何添加新成员。但是,此答案有望为您提供足够的信息以开始使用。

Note that with the validation methods, you may want to move them around and/or refactor them, depending on how you add users and team, and how you'll add new members. However, this answer will hopefully give you enough information to get started.

这篇关于用户和团队之间的关联和迁移(导轨)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆