If you have ever had a marvelous situation when you registered associations for models (has_one and belongs_to), accepted_nested_attributes, but the field_for helper does not show the form, this post will help you to get rid of this “glitch” once and for all. I warn you in advance that the post is purely for rails developers, and nobody will be interested in anyone but rails!
Preconditions
So, let's say we have the following models:
class Company < ActiveRecord::Base belongs_to :location has_one :user accepts_nested_attributes_for :user accepts_nested_attrbiutes_for :location end class User < ActiveRecord::Base belongs_to :company end class Location < ActiveRecord::Base has_one :company end
')
We need a company form with user and location resources. At first glance it may seem that the code:
form_for :company do |f| f.text_field :name f.fields_for :user, f.object.user_or_build do |fu| fu.text_field :name end f.fields_for :location, f.object.location_or_build do |fl| fl.text_field :address end end
will be enough to show the desired shape. However, it is not. Starting the application and opening the browser you will see that instead of the expected 3 fields on the page there is only one - this is the name field for the company (it is assumed that we have an initialized object like this:
@company = Company.new
).
What is wrong with this code?
The problem lies in the fact that we have not initialized the associated user and location objects for @company:
@company.build_location
If these conditions are met before the fields_for helpers are executed, the form will look like we expected. However, to write such code every time in controllers is somehow frivolous, because controllers must be clean!
Decision
To avoid this problem, you can use this
heme , which has a slightly awkward name -
get_or_build .
Add a line to the gemfile:
gem 'get_ot_build'
Install gems: bundle install, restart the application and refactor the code with the fields_for helpers as follows:
form_for :company do |f| f.fields_for :user, :build_association => true do |fu| fu.text_field :name end f.fields_for :user, :build_association => true do |fl| fl.text_field :address end end
After that, the initialization code of the user and location associations objects can be removed from the controllers, templates and helpers (somewhere else where it is;) and is no longer needed).
I would be very grateful for the criticism and comments, volunteers for the development of the heme are also welcome. Thanks for attention!