0

I can't wrap my head around this any help would be appreciated. I went through many articles and other postings on here and I can't seem to get the results I'm looking for.

I have a User model and Team model.

Team Model has user_id and team_id

The user who creates the team will be user_id and users who are members of the team will be in the team_id

User Model
 has_many :teams, foreign_key: :team_id
 has_many :team_members, class_name: "Team", foreign_key: :user_id

Team Model
 belongs_to :user, foreign_key: :team_id    
 belongs_to :team_member, class_name: "User", foreign_key: :user_id

The end result of what I'm trying to achieve is:

  • Each user can add as many team members
  • Each user can see a list of users who are part of their team.
  • A view where, Users who are part of a team can see which team they are part of.
Michael
  • 13
  • 3
  • I suspect you want a [`has_and_belongs_to_many`](http://apidock.com/rails/ActiveRecord/Associations/ClassMethods/has_and_belongs_to_many) relationship, but it's not entirely clear what you're wanting to do. – Undo Dec 03 '15 at 23:25
  • @Undo thanks for commenting. I looked into that but couldn't get it to work. Can you show me an example how I would use it within the model i have above? – Michael Dec 03 '15 at 23:35

1 Answers1

0

I believe what you're looking for is a join table model. The issue is that both a User and a Team may have many of each other. So the relationship must be stored separately.

See this answer here on a similar question: https://stackoverflow.com/a/15442583/5113832

So you might choose a model structure of User, Team and TeamMembership.

Updated to destroy dependent team memberships when a user or team is destroyed.

#app/models/user.rb
class User < ActiveRecord::Base
  has_many :team_memberships, :dependent => :destroy
  has_many :teams, :through => :team_memberships
end

#app/models/team.rb
class Team < ActiveRecord::Base
  has_many :team_memberships, :dependent => :destroy
  has_many :users, :through => :team_memberships
end

#app/models/team_membership.rb
class TeamMembership < ActiveRecord::Base
  belongs_to :user
  belongs_to :team
end

Updated to reply to question:

How would my controller look on create? (Adding a user to a team) – Michael

In order to add a user to to a team you COULD do it in UserController, you COULD do it in TeamController. However, because you are now creating a TeamMembership resource you would want to create a TeamMembership record in a TeamMembershipsController. This keeps with the "Rails" way of doing things. So for example:

# app/controllers/team_memberships_controller.rb
class TeamMembershipsController < ApplicationController
  def index
    @team_memberships = TeamMembership.all
  end

  def new
    @team_membership = TeamMembership.new
  end

  def create
    @team_membership = TeamMembership.new(team_membership_params)
    if @team_membership.save
      flash[:success] = 'Team membership created'
      redirect_to team_memberships_path
    else
      flash[:error] = 'Team membership not created'
      render :new
    end
  end

  def destroy
    @team_membership = TeamMembership.find_by_id(params[:id])
    if @team_membership && @team_membership.destroy
      flash[:success] = 'Team membership destroyed'
    else
      flash[:error] = 'Team membership not destroyed'
    end
    redirect_to team_memberships_path
  end


  private
  def team_membership_params
    params.require(:team_membership).permit(
      :user_id,
      :team_id
    )
  end
end

The advantage to having the TeamMembership resource is using this pattern to manage when a user is added (#create), or removed (#destroy) from a team.

The magic of Rails associations will take care of accessing a team's members (users) and a user's teams for each instance of those models.

You just go about your business doing CRUD on these resources and Rails takes care of the organization for you by your conforming to it's conventions.

Also I updated my original model code to destroy team memberships when a user or team is destroyed. This ensures no orphaned records are in your team_memberships table.

As a final note. You should also be able to easily use form_for to send a TeamMembership to your controller to be created. This could be done using select option dropdowns for users and teams with Rails' collection_select:

<%# app/views/team_memberships/new.html.erb %>
<h1>
  Create Team Membership
</h1>

<%= form_for(@team_membership) do |f| %>
  <%= f.label(:user) %>
  <%= f.collection_select(
    :user_id,
    User.all,
    :id,
    :username
  ) %>

  <%= f.label(:team) %>
  <%= f.collection_select(
    :team_id,
    Team.all,
    :id,
    :name
  ) %>

  <%= f.submit %>
<% end %>

The above code will render dropdown for all users and teams allowing you to select a specific combination to create a team membership from. Deleting a team membership is as easy as sending a DELETE #destroy request with the id of the team membership.

Another consideration might be adding a unique pair constraint to your database table and model within the migration and model validations.

Hope this helps!

Community
  • 1
  • 1
bideowego
  • 451
  • 1
  • 5
  • 17
  • Thanks this makes sense! How would my controller look on create? (Adding a user to a team) – Michael Dec 03 '15 at 23:54
  • If you have a user like `user = User.first` and a team `team = Team.first` you can add the user to the team by using `team.users << user` and calling `team.save` – Erica Tripp Dec 04 '15 at 07:30
  • @Michael I updated my answer to give an example of how a TeamMembershipsController would look as well as some views, forms and tips. – bideowego Dec 14 '15 at 04:13