简体   繁体   中英

Rails - How to limit number of records for a particular user in a particular model

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.

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

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.

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 .

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?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM