I am using cocoon in my Rails app for assigning employees (users) to projects (many to many connection). The creation of associations is working correctly, but each time I add another employee cocoon adds an empty form field in the edit view. None of the other cocoon form fields in the edit view are populated either. Could this be due to the usage of dropdowns (select)?
When I inspect the form in my browser I can see that each field seems to be assigned to one of the associations, but the selection is still empty.
What I would like to achieve is, that every association is displayed in a cocoon form field, so that they can be edited. Thanks for any help in advance!
My code is below (Sorry for any mess, it is my first time trying out a many to many connection of two models).
Project Edit View
<%= form_for(@project, :url => project_path, method: :patch) do |f| %>
<div class="form-group">
<%= f.label :title %>
<%= f.text_field :title, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :customer %>
<%= f.text_field :customer, class: "form-control" %>
</div>
<%= f.fields_for :user_projects do |collab| %>
<% collab.hidden_field :project_id, value: @project.id %>
<%= render 'user_project_fields', f: collab %>
<% end %>
<div class="add-collaborator">
<%= link_to_add_association "add", f, :user_projects, class: "btn btn-mmc" %>
</div>
<div class="actions">
<%= f.submit "Save Changes", class: "btn btn-mmc btn-mmc-medium" %>
</div>
<% end %>
cocoon field partial
<div class="nested-fields">
<%= f.label "Select User" %>
<div class="form-group custom-form-group">
<%= f.select(:user_id, options_for_select(User.all.map { |u| [u.email, u.id] }), {include_blank: true}, {class: 'form-control'})%>
<div class="btn-user-project">
<%= link_to_remove_association "x", f, class: "btn btn-mmc-attention btn-mmc" %>
</div>
</div>
</div>
Project Model
class Project < ApplicationRecord
has_many :user_projects
has_many :users, :through => :user_projects
accepts_nested_attributes_for :user_projects, reject_if: :all_blank, allow_destroy: true
end
User Model
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :user_projects
has_many :projects, :through => :user_projects
end
Project Controller
def edit
@project = Project.find(params[:id])
@project.user_projects.build
end
def update
@project = Project.find(params[:id])
@project.update(project_params)
@new_collaborator = UserProject.new(user_id: params[:user_id], project_id: params[:project_id])
@new_collaborator.save
if @project.update(project_params) && @new_collaborator.save
redirect_to projects_path
else
render :edit
end
end
private
def project_params
params.require(:project).permit(:title, :customer, :delted, user_projects_attributes: [:user_id, :project_id]).reject { |_, v| v.blank? }
end
I am guessing the mapping to the actual value is not done correctly, e.g. the value of the user_id
is not marked as selected, in the options_for_select
you have to add the selected value as parameter (see documentation).
However, there is a much easier version:
<%= f.collection_select(:user_id, User.all, :id, :email) %>
BTW using a gem like simple_form
also makes building forms a lot more intuitive and straightforward.