Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deep Nested Rails 4 Form

I have 3 models Item which accepts nested attributes for questions and questions accept nested attributes for answers. I'm trying to create an item which has a question and an answer in the same form.

item.rb

class Item < ActiveRecord::Base
  has_many :questions, dependent: :destroy
  accepts_nested_attributes_for :questions
end

question.rb

class Question < ActiveRecord::Base
  belongs_to :item

  has_many :answers, dependent: :destroy
  accepts_nested_attributes_for :answers
end

answer.rb

class Answer < ActiveRecord::Base
  belongs_to :question
end

item_controller.rb

class ItemsController < ApplicationController
    def new
      @item = @repository.items.new
      questions = @item.questions.build
      answers = questions.answers.build
    end

    def create
      @item = Item.new(item_params)
      if @item.save
          redirect_to @item, notice: '...'
      else
          render action: 'new'
      end
    end

  private
  def item_params
      params.require(:item).permit(:id, :content, :kind, :questions_attributes => [:content, :helper_text, :kind], :answers_attributes => [:content, :correct])
  end   
end

_form.haml

= simple_form_for(@item) do |f|
    = f.input :kind
    = f.input :content
    = f.simple_fields_for :questions do |q|
        = q.input :content
        = q.simple_fields_for :answers do |a|
            = a.input :content
    = f.submit

The form is being displayed correctly and it saves the question model correctly. I can't seem to save the answer though.

I've already looked at a lot of online help but none are covering it with Rails 4 strong params.

like image 263
Hass Avatar asked Jan 08 '14 10:01

Hass


2 Answers

I think your problem is with your strong params:

def item_params
      params.require(:item).permit(:id, :content, :kind, questions_attributes: [:content, :helper_text, :kind, answers_attributes: [:content, :correct]])
end   

Basically, when you pass a deep nested form (where you have multiple dependent models), you'll have to pass the attributes as part of the other model's attributes. You had the params as separate

like image 129
Richard Peck Avatar answered Nov 13 '22 11:11

Richard Peck


I run into a similar issue and, while Richard Peck answer helped me as well, there is one thing that it was missing for me.

If you are deep-nesting you need to specify the id of the parent of the nested item. In this case to create an answers you need to make questions id explicit with q.input :id, otherwise you will run into this error.

= simple_form_for(@item) do |f|
    = ...
    = f.simple_fields_for :questions do |q|
        = ...
        = q.input :id
        = q.simple_fields_for :answers do |a|
            = ...
    = f.submit
like image 2
a.barbieri Avatar answered Nov 13 '22 10:11

a.barbieri