Recent posts:
The Wordchuck Blog.
Shelly Roche is a Ruby on Rails engineer and founder of Wordchuck. She usually blogs about Ruby, Rails 3, woodchucks, i18n, l10n, startup life or whatever has her fired up on any given day. Yes, she is available for i18n consulting & training. Find her or by . |
How to use check_box in nested model forms
This article will show you how to use the check_box helper in a nested model form using Rails 3.
In this example, I have two models with a many-to-many relationship - projects and languages
Because a project can have many languages and a language can have many projects, I'm going to use a :has_many association with the :through option and create a join model called project_languages to store the relationships:
class Language < ActiveRecord::Base has_many :project_languages has_many :projects, :through => :project_languages end
class Project < ActiveRecord::Base has_many :project_languages has_many :languages, :through => :project_languages end
The join model:
class ProjectLanguage < ActiveRecord::Base belongs_to :project belongs_to :language end
We need to do one more thing to set our models up properly - tell the project model to automatically include the project_languages model when it saves. To do this, we add accepts_nested_attributes_for to the model like so:
class Project < ActiveRecord::Base has_many :project_languages has_many :languages, :through => :project_languages accepts_nested_attributes_for :project_languages, :allow_destroy => true end
Using accepts_nested_attributes_for means we don't need to add anything special in the projects controller - it will automatically save the project_languages object when we save the project object.
In the edit form for my project, I want to list all of the languages that have been associated with the project, and then allow the user to check the box next to each language to set a flag in my nested project_languages model.
To give you more context for this functionality, part of the OpenGab awesomeness is that we have a rake task that automatically generates and deploys all of your translated .yml files. The flag we're setting with each check box indicates that all of the content for that language has been translated and is ready to be deployed to the production environment for the project. Languages that aren't checked remain associated with the project (i.e. the association in the project_languages model is not destroyed), but they will be ignored when the rake task to re-generate the yml files runs for the production environment.
The next step is to create the form in my project edit form view (this example is using Rails 3):
=form_for @project, :remote => true do |form|
Then within the form:
-for language in @project.project_languages =form.fields_for :project_languages, language do |pl| =pl.check_box :production =pl.label language.language.name %br
For each language that has been added to the project (through the nested project_languages join model), we're printing a check_box that will update an attribute in the project_languages model called "production".
This is what it looks like in the form:
This is the html that is generated:
"project[project_languages_attributes][0][production]" type="hidden" value="0" />"project_project_languages_attributes_0_production" name="project[project_languages_attributes][0][production]" type="checkbox" value="1" />
And that's it!