My nested model form is working great on the first level deep. But I was under the impression that you could go many levels deep using accepts_nested_attributes_for. But when I try the code below, the "Image" attributes are attached to the top level "Question" model and it breaks upon form submission with an unknown attribute "Image" error.
I could do the inserts all by hand using the form data but if Rails can handle it automatically, it would be better for obvious reasons.
What am I doing wrong? I tried changing |af| in the "fields for :image do" to its own unique name but it didn't have any effect.
Models:
class Question < ActiveRecord::Base
  has_one :answer
  accepts_nested_attributes_for :answer
end
class Answer < ActiveRecord::Base
  belongs_to :question
  has_one :image
  accepts_nested_attributes_for :image
end
class Image < ActiveRecord::Base
  belongs_to :answer
end
Controller:
def new
    @question = Question.new
    answer = @question.build_answer
    image = answer.build_image
    @case_id = params[:id]
    render :layout => 'application', :template => '/questions/form' 
end
def create
  question_data = params[:question]
  @question = Question.new(question_data)
  if @question.save
  ...
end
View:
= form_for @question, :html => {:multipart => true} do |f|
  = f.label :text, "Question Text:"
  = f.text_area :text, :rows => 7
  %br
  %br
  =f.fields_for :answer, do |af|
    = af.label :body, "Answer Text:"
    = af.text_area :body, :rows => 7
    %br
    %br
    = f.fields_for :image do |af|
      = af.label :title, "Image Title:"
      = af.text_field :title
      %br
      = af.label :file, "Image File:"
      = af.file_field :file
      %br
      = af.label :caption, "Image Caption:"
      = af.text_area :caption, :rows => 7
  = hidden_field_tag("case_id", value = @case_id)
  = f.submit
                I think you've got the form variables slightly mixed up. It should be:
= form_for @question, :html => {:multipart => true} do |f|
  = f.label :text, "Question Text:"
  = f.text_area :text, :rows => 7
  %br
  %br
  =f.fields_for :answer, do |af|
    = af.label :body, "Answer Text:"
    = af.text_area :body, :rows => 7
    %br
    %br
    = af.fields_for :image do |img_form|
      = img_form.label :title, "Image Title:"
      = img_form.text_field :title
      %br
      = img_form.label :file, "Image File:"
      = img_form.file_field :file
      %br
      = img_form.label :caption, "Image Caption:"
      = img_form.text_area :caption, :rows => 7
  = hidden_field_tag("case_id", value = @case_id)
  = f.submit
Notice how form_for ... do |f| spawns f.fields_for ... do |af|, which in turns spawns af.fields_for ... do |img_form|.
The key is the second fields_for. It should be af.fields_for :image do |img_form| rather than f.fields_for :image do |img_form|.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With