1

I have a Project model and Team model and User model through devise. The associations between the models are as follows:-

class Project
  has_many :teams, :dependent => :destroy
end

class Team
    belongs_to :project
    belongs_to :user
end

class User
   has_many :teams, :dependent => :destroy
end

Teams are nested withins Projects, so every project has its own seperate group of teams.

resources :projects do
    resources :teams
  end

The teams themselves are derived from Users, so when a new team is created, it is linked to the current_user that is signed in:

  def create
    @project = Project.find(params[:project_id])
    @team = @project.teams.new(team_params)
    @team.user = current_user
   if @team.save
      redirect_to @project, notice: 'Successfully Joined Project'
    else
      render action: 'new'
    end
  end

The Problem:-

I need the user to only have one Team per project (so he can only join a project once). I figured I could do this in the following way:

<% if @project.teams.user == current_user do %>
    <%= link_to 'edit role', edit_project_team_path(@project), class: 'btn btn-primary' %>
<% end %>
<% else %>
    <%= link_to 'Join Project', new_project_team_path(@project), class: 'btn btn-primary' %>
<% end %>

However im getting the following error for the previous code:

NoMethodError in Projects#show

undefined method `user' for #<Team::ActiveRecord_Associations_CollectionProxy:0x5858430>

Im not sure if the problem is with my associations or if im trying to achieve this the wrong way.

P.S think of Team as Team Member (as a team suggests a group of users however each team actually consists of one user only)

3 Answers3

1

You are trying to find user from a association object. @project.teams.user here @project.teams will return multiple objects not single object. So you should change @project.teams.user to @project.teams.first.user . You will not get this error.

<% if @project.teams.present? && @project.teams.first.user == current_user %>
    <%= link_to 'edit role', edit_project_team_path(@project), class: 'btn btn-primary' %>
<% else %>
    <%= link_to 'Join Project', new_project_team_path(@project), class: 'btn btn-primary' %>
<% end %>

I have just make a prediction that project has_many :teams. As your code look like.

Dipak Gupta
  • 7,321
  • 1
  • 20
  • 32
  • Just tried that, im having 2 problems:- 1) for exisiting project, the buttons for edit role and join project do not appear at all. 2) if I create a new project, I get the following error: undefined method `user' for nil:NilClass – Rashed Al-Julaibi Sep 07 '15 at 10:45
  • I have updated my answer. Problem is with your use case. Your use case should be. If project already have team member assign then there is no button for join or edit role. And if team present then user should be current user then only they can change role. – Dipak Gupta Sep 07 '15 at 10:53
  • The code you provided seems to be working, however Im now getting an error for the line below with the edit role link: <%= link_to 'edit role', edit_project_team_path(@project), class: 'btn btn-primary' %>. The error is: No route matches {:action=>"edit", :controller=>"teams", :id=>nil, :project_id=>"75"} missing required keys: [:id] – Rashed Al-Julaibi Sep 07 '15 at 11:15
  • You are not providing team id in your path. You need yo provide team id something like this `<%= link_to 'edit role', edit_project_team_path(@project, @project.teams.first), class: 'btn btn-primary' %>` Or `<%= link_to 'edit role', edit_project_team_path(@project, any_team_id_to_edit), class: 'btn btn-primary' %>` – Dipak Gupta Sep 07 '15 at 11:19
1

Try:

- team_member = @project.teams.where(user_id: current_user.id).first
<% if team_member.present? %>
    <%= link_to 'edit role', edit_project_team_path(@project, team_member), class: 'btn btn-primary' %>
<% else %>
    <%= link_to 'Join Project', new_project_team_path(@project), class: 'btn btn-primary' %>
<% end %>

Also to prevent inconsistencies in the database i would recommend to use uniqueness validations:

class Team
    belongs_to :project
    belongs_to :user
    validates :user_id, uniqueness: { scope: :project_id }
end

It will help you a lot in the future. Also don't forget to add unique indices.

Community
  • 1
  • 1
tiktak
  • 1,801
  • 2
  • 26
  • 46
0

If I understood well, you are creating the TeamMember model just to prevent the user to join a project more than once? You also mention Teams, but their position is not clear.

Why cannot a project has_many users and then you restrict the user to belong to a project more than once through a before_filter or a validation in the model?

Puce
  • 1,003
  • 14
  • 28
  • TeamMember is actually the same as Team, I only changed the names here as I thought it would make my question linguistically clearer. sorry for the confusion. I will edit my question. To answer your question, I need the TeamMember model so that I can add extra information regarding the Users role in the project, So I need to generate a new form in which the user selects his role within the project. Hope that makes sense. – Rashed Al-Julaibi Sep 07 '15 at 10:41