Building a Multi-Model Form
Notice: A non well formed numeric value encountered in /home/batteur/www/wp-content/plugins/crayon-syntax-highlighter/crayon_formatter.class.php on line 118
Notice: A non well formed numeric value encountered in /home/batteur/www/wp-content/plugins/crayon-syntax-highlighter/crayon_formatter.class.php on line 119
Notice: A non well formed numeric value encountered in /home/batteur/www/wp-content/plugins/crayon-syntax-highlighter/crayon_formatter.class.php on line 118
Notice: A non well formed numeric value encountered in /home/batteur/www/wp-content/plugins/crayon-syntax-highlighter/crayon_formatter.class.php on line 119
Notice: A non well formed numeric value encountered in /home/batteur/www/wp-content/plugins/crayon-syntax-highlighter/crayon_formatter.class.php on line 118
Notice: A non well formed numeric value encountered in /home/batteur/www/wp-content/plugins/crayon-syntax-highlighter/crayon_formatter.class.php on line 119
Notice: A non well formed numeric value encountered in /home/batteur/www/wp-content/plugins/crayon-syntax-highlighter/crayon_formatter.class.php on line 118
Notice: A non well formed numeric value encountered in /home/batteur/www/wp-content/plugins/crayon-syntax-highlighter/crayon_formatter.class.php on line 119
Your application must interact with more than one model on a single form. Rails offers this support for nested forms.
Take the case that one wishes to label the posts of a blog with tags.
We assume the posts module and its controller are already available.
To demonstrate, we will allow you to add multiple tags to each post. Start by creating a new model to hold the tags:
1 |
$ rails generate model tag name:string post:references |
run the migration to create the table in the database.
1 |
$ rake db:migrate |
Then edit the file to associate post.rb tag to posts and to tell Rails (via macro accepts_nested_attributes_for) you want to edit tags via posts:
1 2 3 4 5 6 |
class Post < ActiveRecord::Base has_many :tags accepts_nested_attributes_for :tags, :allow_destroy => :true, :reject_if => proc { |attrs| attrs.all? { |k, v| v.blank? } } end |
Option: allow_destroy on the declaration of nested attributes tells Rails to display a checkbox “remove” in the next view. The reject_if option prevents saving tags without attributes.
Then modify views / posts / _form.html.erb to make a partial tag creation:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
<% @post.tags.build %> <%= form_for(@post) do |post_form| %> <% if @post.errors.any? %> <div id="errorExplanation"> <h2><%= pluralize(@post.errors.count, "error") %> prohibited this post from being saved:</h2> <ul> <% @post.errors.full_messages.each do |msg| %> <li><%= msg %></li> <% end %> </ul> </div> <% end %> <div class="field"> <%= post_form.label :name %><br /> <%= post_form.text_field :name %> </div> <div class="field"> <%= post_form.label :title %><br /> <%= post_form.text_field :title %> </div> <div class="field"> <%= post_form.label :content %><br /> <%= post_form.text_area :content %> </div> <h2>Tags</h2> <%= render :partial => 'tags/form', :locals => {:form => post_form} %> <div class="actions"> <%= post_form.submit %> </div> <% end %> |