Rails 4 nested attributes not saving

nested-forms, ruby, ruby-on-rails, ruby-on-rails-4

Solution

Looks like you're using the wrong form builder object. Change the question section to something like this:

<%= f.fields_for :question do |question_builder| %>
   <%= question_builder.label :content %>
   <%= question_builder.text_area :content %>

   <%= question_builder.fields_for :answer do |answer_builder| %> 
       <%= answer_builder.label :content, "Answer" %>
       <%= answer_builder.text_field :content %>
   <% end %>

<% end %>

Originally you were using the `f` form builder in the line `f.fields_for :answers...`, however given your model code, since it is a `Question` that `accepts_nested_attributes_for` an `Answer`, we simply exchange the form builder object for the one used for the `question` section.

Note: I changed the names of the builder objects for clarity.

Update

In order to build a deeply nested relationship like this, you will have to loop through your "built" association (`questions` in this case), and invoke `build` again on its `has_many` association. So going off of gabrielhilal's answer, you would do this:

def new
  @survey = Survey.new
  @survey.questions.build
  @survey.questions.each do |question|
      question.answers.build
  end
end

Note that in your case, since you are explicitly creating only one question, you can technically do this instead (instead of the loop):

@survey.questions.first.answers.build

Disclaimer: If there is a cleaner, more Rails-y, way to do this, I am sadly unaware of it.

Problem

I cannot seem to get nested attributes to save to the database. I am using Rails 4. Here are my models : ``` class Answer < ActiveRecord::Base belongs_to :question end class Question < ActiveRecord::Base has_many :answers belongs_to :survey accepts_nested_attributes_for :answers, allow_destroy: true end class Survey < ActiveRecord::Base has_many :questions validates_presence_of :name accepts_nested_attributes_for :questions end ``` Here is the controller: ``` def create @survey = Survey.new(survey_params) respond_to do |format| if @survey.save format.html { redirect_to @survey, notice: 'Survey was successfully created.' } format.json { render action: 'show', status: :created, location: @survey } else format.html { render action: 'new' } format.json { render json: @survey.errors, status: :unprocessable_entity } end end end def survey_params params.require(:survey).permit(:name, questions_attributes:[:content, :id, :survey_id, answers_attributes:[:content, :id, :questions_id] ]) end ``` Finally, here is the form itself. I have tried using both f.fields_for and just fields_for ``` <%= form_for(@survey) do |f| %> <% if @survey.errors.any? %> <div id="error_explanation"> <h2><%= pluralize(@survey.errors.count, "error") %> prohibited this survey from being saved:</h2> <ul> <% @survey.errors.full_messages.each do |msg| %> <li><%= msg %></li> <% end %> </ul> </div> <% end %> <div class="field"> <%= f.label :name %><br> <%= f.text_field :name %> </div> <%= f.fields_for :question do |builder| %> <%= builder.label :content %> <%= builder.text_area :content %> <%= f.fields_for :answer do |builder| %> <%= builder.label :content, "Answer" %> <%= builder.text_field :content %> <% end %> <% end %> <div class="actions"> <%= f.submit %> </div> <% end %> ``` The survey saves fine to the database, put the questions and answers will not. I've looked at every resource I could find and it seems like I am doing this correctly, so it's really driving me crazy. This example is just a quick scaffold so I had some code to paste in, but I can't seem to get it to work anywhere else. edit: changing my new action to something like this: ``` def new @survey = Survey.new @survey.questions.build end ``` WORKED! SEE TEEGS ANSWER FOR SOLUTION TO THIS Here is the new form I am using, still only saving the survey name ``` <%= f.fields_for :question do |question_builder| %> <%= form_for(@survey) do |f| %> <% if @survey.errors.any? %> <div id="error_explanation"> <h2><%= pluralize(@survey.errors.count, "error") %> prohibited this survey from being saved:</h2> <ul> <% @survey.errors.full_messages.each do |msg| %> <li><%= msg %></li> <% end %> </ul> </div> <% end %> <div class="field"> <%= f.label :name %><br> <%= f.text_field :name %> </div> <%= f.fields_for :question do |question_builder| %> <%= question_builder.label :content %> <%= question_builder.text_area :content %> <%= question_builder.fields_for :answer do |answer_builder| %> <%= answer_builder.label :content, "Answer" %> <%= answer_builder.text_field :content %> <% end %> <% end %> <div class="actions"> <%= f.submit %> </div> <% end %> ```

Original source