2

During the update action of a nested form, instead of updating the current nested records, it seems to create new nested records.

This is what my controller looks like :

class ApplicationsController < ApplicationController

  before_filter :set_user_and_job


  def new 
   job = params[:job_id]
   @application = Application.build(job)

  end

  def create
    @application = Application.new(application_params)
    @application.save

    redirect_to root_url, :notice => "You have now applied!"
  end


  def edit 
    @application = Application.find(params[:id])

    @answers = []

    @job.questions.each do |question|
      @application.answers.each do |answer|
        @answers << answer if answer.question_id == question.id
      end
    end

  end

  def update
    @application = Application.find(params[:id])
    @application.update_attributes(application_params)
    redirect_to root_url, :notice => "You have updated your application!"

  end


  def destroy
    Application.find(params[:id]).destroy
    flash[:success] = "Application Deleted."
    redirect_to root_url 
  end 

  def show 
    @application = Application.find(params[:id])

    @answers = []

    @job.questions.each do |question|
      @application.answers.each do |answer|
        @answers << answer if answer.question_id == question.id
      end
    end

  end

private

  def set_user_and_job
      @user = current_user
      @job = Job.find(params[:job_id])
  end

  def application_params
       params.require(:application).permit(:job_id, :user_id, answers_attributes:[:question_id, :content]).merge(user_id: current_user.id, job_id: params[:job_id])
  end


end

This is what my edit view looks like :

<% provide(:title, " Edit this application") %>

  <div class="row">
      <div class="span6">
        <h2> Job: <%= @job.job_title  %></h2>
        <p> <%= @job.job_summary %> </p>
      </div>
      <div class="span6">
        <h2> Applicant: <%= @user.name  %></h2>
      </div>

      <div class="span12">
        <h3>Edit your job application below.</h3>
      </div>
  </div>


<%= form_for [@job, @application] do |f| %>
  <%= render 'shared/error_messages', object: f.object %>

     <% @job.questions.each_with_index do |question| %>
         <%= f.fields_for :answers, question do |question_field| %>
              <%= question_field.label :content, question.content %>
              <%= question_field.text_area :content, :value => "" %>
              <%= question_field.hidden_field :question_id,  :value => question.id  %>
         <% end %>
    <% end %>



   <%= f.submit "Submit the application", class: "button" %>
<% end %>

The Application Model itself:

# == Schema Information
#
# Table name: applications
#
#  id         :integer          not null, primary key
#  user_id    :integer
#  job_id     :integer
#  created_at :datetime
#  updated_at :datetime
#

class Application < ActiveRecord::Base
    belongs_to :job
    belongs_to :user
    validates :job_id, presence: true 
    validates :user_id, presence: true 
    has_many :answers
    accepts_nested_attributes_for :answers, :reject_if => lambda { |a| a[:content].blank? }, :allow_destroy => true


    def self.build(job_id) 
        application = self.new

        job = Job.find(job_id)
        job.questions.count.times do
         application.answers.build
        end

    application
    end

end

And the Answer Model :

# == Schema Information
#
# Table name: answers
#
#  id             :integer          not null, primary key
#  application_id :integer
#  question_id    :integer
#  created_at     :datetime
#  updated_at     :datetime
#  content        :string(255)
#

class Answer < ActiveRecord::Base
    belongs_to :question
    belongs_to :application
    validates :content, presence: true
end

From searching, I found this link, RoR nested attributes produces duplicates when edit , which suggests that I add the :id to application_params, however when I do that, I get the error

ActiveRecord::RecordNotFound in ApplicationsController#update
Couldn't find Answer with ID=5 for Application with ID=17

(That's also a bit weird, because the actual id of the answer is 39. 5 is actually the ID of the question :S )

What are your thoughts on this? Mentors of SO, help much appreciated :)

Community
  • 1
  • 1
Stepan Parunashvili
  • 2,627
  • 5
  • 30
  • 51

2 Answers2

7

update_only does not work for has_many relationships. You need to add the nested attribute :id field to your strong parameters:

def application_params
   params.require(:application).permit(:job_id, :user_id, 
     answers_attributes:[:id, :question_id, :content]).merge(user_id: current_user.id,
     job_id: params[:job_id])
end
Philip7899
  • 4,599
  • 4
  • 55
  • 114
  • Hi Philip, thanks for the response. After adding the :id parameter, I get a NoRecordFound Error. It might be because somehow Rails is mistaking the question id for the answer id, or I'm not sure what's going on. The errors are in the post above. What are your thoughts on it? – Stepan Parunashvili Dec 30 '13 at 02:17
  • 1
    Update: Philip was right on needing the :id. The reason I was getting the nomethoderror was because of my view. Instead of running jobs.question.each, and then form_for under it, I just wrote form_for, and got the questions by writing question_field.object.question.content. – Stepan Parunashvili Dec 30 '13 at 10:20
0

Try adding update_only to your call to accepts_nested_attributes_for.

accepts_nested_attributes_for :nested_attribute, update_only: true
OneChillDude
  • 7,856
  • 10
  • 40
  • 79
  • Hi bw, I added it, but it still seems to be producing duplicate records. Let me know if there's more info I can provide that might help deduce things. – Stepan Parunashvili Dec 29 '13 at 18:35