用户和团队之间的关联和迁移(导轨) [英] association and migration between users and teams (rails)
问题描述
我有这个具有以下关联的用户和团队模型:
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 $ c创建一个联接表$ c>。我们称其为
个成员
。它将同时引用用户
和 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屋!