association and migration between users and teams (rails)

只愿长相守 提交于 2019-12-22 11:30:31

问题


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

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?


回答1:


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

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

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.




回答2:


Your migrations look correct, but your associations are not complete:

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"

And you should be all set.



来源:https://stackoverflow.com/questions/24289861/association-and-migration-between-users-and-teams-rails

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!