Leandro
Leandro

Reputation: 377

Rails nested attribute form: error when creating an object with a many-to-many relationship

My project has a many-to-many relationship among the following classes:

class Project < ApplicationRecord
  has_many :project_software_processes, inverse_of: :project, :dependent => :delete_all
  has_many :software_processes, through: :project_software_processes

  accepts_nested_attributes_for :project_software_processes

  attr_accessor :project_attributes
end

..

class SoftwareProcess < ApplicationRecord
  has_many :project_software_processes
  has_many :projects, through: :project_software_processes
 end

--

class ProjectSoftwareProcess < ApplicationRecord
  belongs_to :software_process
  belongs_to :project
end

- -

I am using nested forms to create an instance of project so the user can pick as many software processes as they want:

<div class="field">
  <%= f.label :software_processes %>
  <%= f.fields_for :project_software_processes do |project_software_process|  %>
    <%= project_software_process.select(:software_processes_id, @processes.collect { |s| [s.name, s.id] } ) %>
    <%= project_software_process.link_to_remove "Remove this SoftwareProcess" %>
  <% end %>
  <p><%= f.link_to_add "Add a process", :project_software_processes %></p>
</div>

Problem is, when I click on submit I get the following validation message:

Project software processes software process must exist

It took me a bit to understand what the error actually means. I guess it is complaining about the existence of software process class when attempting to create an instance of project software process. However, there are instances of project software process, the user can even select them in the dropdown selects. Not sure if that's the issue though.

Here's some snippets from my project controller:

 def create
    @project = Project.new(project_params)
    @project.user = current_user

    respond_to do |format|
      if @project.save
        format.html { redirect_to @project, notice: 'Project was successfully created.' }
        format.json { render :show, status: :created, location: @project }
      else
        @processes = SoftwareProcess.all
        format.html { render :new }
        format.json { render json: @project.errors, status: :unprocessable_entity }
      end
    end
  end

--

def project_params
  params.require(:project).permit(:name, :user_id, project_software_processes_attributes: [:software_process_id, :_destroy])
end

--

Here's what is being sent in the params:

  Parameters: {"utf8"=>"✓", "authenticity_token"=>"[FILTERED]", "project"=>{"name"=>"aas", "project_software_processes_attributes"=>{"1484020859023"=>{"software_processes_id"=>"1", "_destroy"=>"false"}, "1484020859693"=>{"software_processes_id"=>"4", "_destroy"=>"false"}}}, "commit"=>"Create Project"}

Upvotes: 1

Views: 88

Answers (1)

Dario Barrionuevo
Dario Barrionuevo

Reputation: 3277

The issue is on the name of the select method, should be software_process_id rather than software_processes_id. Try changing it to:

<%= project_software_process.select(:software_process_id, @processes.collect { |s| [s.name, s.id] } ) %>

Also, Ryan Bate's software is pretty outdated by now and nested_forms gem is not an exception. I've seen people recommending Cocoon as a suitable alternative. Take a look here

Cheers.

Upvotes: 1

Related Questions