I am currently trying to make a form for a model, which has a dynamic number of nested models. I'm using Nested Forms (as described in RailsCasts 197). To make things even more complicated, each of my nested models has a has_one
association with a third model, which I would also like to be added to the form.
For any who are wondering about over normalization or an improper approach, this example is a simplified version of the problem I'm facing. In reality, things are slightly more complex, and this is the approach we've decided to take.
Some example code to illustrate the problem below:
#MODELS
class Test
attr_accessible :test_name, :test_description, :questions_attributes
has_many :questions
accepts_nested_attributes_for :questions
end
class Question
attr_accessible :question, :answer_attributes
belongs_to :test
has_one :answer
accepts_nested_attributes_for :answer
end
class Answer
attr_accessible :answer
belongs_to :question
end
#CONTROLLER
class TestsController < ApplicationController
#GET /tests/new
def new
@test = Test.new
@questions = @test.questions.build
@answers = @questions.build_answer
end
end
#VIEW
<%= form_for @test do |f| %>
<%= f.label :test_name %>
<%= f.text_box :test_name %>
<%= f.label :test_description %>
<%= f.text_area :test_description %>
<%= f.fields_for :questions do |questions_builder| %>
<%= questions_builder.label :question %>
<%= questions_builder.text_box :question %>
<%= questions_builder.fields_for :answer do |answers_builder| %>
<%= answers_builder.label :answer %>
<%= answers_builder.text_box :answer %>
<% end %>
<% end %>
<%= link_to_add_fields 'New', f, :questions %>
<% end %>
This code example works fully for the first instance of Question. The issue occurs when another question is dynamically added to be created; the answer fields are not displayed. I believe this is because they are only built for the first question in the controller. Is there a way to achieve this using nested_attributes?
I solved my own issue here. What I did was, instead of building the answer model in the controller (which is impossible when you do not know how many questions are going to be made in the view), I built it when calling fields_for:
#CONTROLLER
class TestsController < ApplicationController
#GET /tests/new
def new
@test = Test.new
@questions = @test.questions.build
end
end
#VIEW
<%= form_for @test do |f| %>
<%= f.label :test_name %>
<%= f.text_box :test_name %>
<%= f.label :test_description %>
<%= f.text_area :test_description %>
<%= f.fields_for :questions do |questions_builder| %>
<%= questions_builder.label :question %>
<%= questions_builder.text_box :question %>
<%= questions_builder.fields_for :answer, @questions.build_answer do |answers_builder| %>
<%= answers_builder.label :answer %>
<%= answers_builder.text_box :answer %>
<% end %>
<% end %>
<%= link_to_add_fields 'New', f, :questions %>
<% end %>
This works because no matter how many question forms are being built on the view, a new answer specific to the question being built is built.
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