#196 Nested Model Form Part 1
Handling multiple models in a single form is much easier with the accepts_nested_attributes_for method. See how to use this method to handle nested model fields.
- Download:
- source codeProject Files in Zip (100 KB)
- mp4Full Size H.264 Video (16.1 MB)
- m4vSmaller H.264 Video (11.1 MB)
- webmFull Size VP8 Video (28 MB)
- ogvFull Size Theora Video (21.6 MB)
There is a newer version of this episode, see the revised episode.
Resources
- Episode 197: Nested Model Form Part 2
- accepts_nested_attributes_for
- Nifty Generators
- Nested Model Forms Blog Post
- Full Episode Source Code
Note: If you are protecting attributes with attr_accessible
be certain to add the nested attributes to that (such as questions_attributes
and answers_attributes
).
bash
rails surveysays script/generate nifty_layout script/generate nifty_scaffold survey name:string script/generate model question survey_id:integer content:text script/generate model answer question_id:integer content:string rake db:migrate
models/survey.rb
class Survey < ActiveRecord::Base has_many :questions, :dependent => :destroy accepts_nested_attributes_for :questions, :reject_if => lambda { |a| a[:content].blank? }, :allow_destroy => true end
models/question.rb
class Question < ActiveRecord::Base belongs_to :survey has_many :answers, :dependent => :destroy accepts_nested_attributes_for :answers, :reject_if => lambda { |a| a[:content].blank? }, :allow_destroy => true end
models/answer.rb
class Answer < ActiveRecord::Base belongs_to :question end
surveys_controller.rb
def new @survey = Survey.new 3.times do question = @survey.questions.build 4.times { question.answers.build } end end
views/surveys/_form.html.erb
<%= form_for @survey do |f| %> <%= f.error_messages %> <p> <%= f.label :name %><br /> <%= f.text_field :name %> </p> <%= f.fields_for :questions do |builder| %> <%= render "question_fields", :f => builder %> <% end %> <p><%= f.submit "Submit" %></p> <% end %>
views/surveys/_question_fields.html.erb
<p> <%= f.label :content, "Question" %><br /> <%= f.text_area :content, :rows => 3 %><br /> <%= f.check_box :_destroy %> <%= f.label :_destroy, "Remove Question" %> </p> <%= f.fields_for :answers do |builder| %> <%= render 'answer_fields', :f => builder %> <% end %>
views/surveys/_answer_fields.html.erb
<p> <%= f.label :content, "Answer" %> <%= f.text_field :content %> <%= f.check_box :_destroy %> <%= f.label :_destroy, "Remove" %> </p>