Reputation: 797
I have difficulty to understand how to use fields_for and nested attributes. In order to understand it better, I created a repo, which is not working.
I read this, which is not helpful.
I am using:
Rails 4.0.1 Ruby 2.0.0-p247
address form shown, why can not save to database?
Why not work?
jack = Person.create(name: 'Jack')
jack.address.create(street: '12w 33st')
The main function is as below:
#model
class Person < ActiveRecord::Base
has_one :address
accepts_nested_attributes_for :address
end
class Address < ActiveRecord::Base
belongs_to :person
end
view as below:
<%= form_for(@person) do |f| %>
<% if @person.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@person.errors.count, "error") %> prohibited this person from being saved:</h2>
<ul>
<% @person.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :age %><br>
<%= f.text_field :age %>
</div>
<div class="field">
<%= f.label :gender %><br>
<%= f.text_field :gender %>
</div>
<%= fields_for :address do |address_fields|%>
Street:
<%= address_fields.text_field :street%>
Zip code:
<%= address_fields.text_field :zip_code%>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
person.address.create
. That's only for has_manyfields_for
, is really not clear. It's just missing the whole controller part. Follow it will not make it.Upvotes: 9
Views: 7862
Reputation: 6834
Try:
jack = Person.create(name: 'Jack')
jack.create_address(street: '12w 33st')
When there is only one associated address (has_one :address
) you use create_address
. When there are many associated addresses (has_many :addresses
) you use addresses.create
.
Also, in your view you will want f.fields_for
instead of fields_for
.
I would recommend checking out the RailsCasts for Nested Model Form to learn more.
Additional Info (to address comments below)
Also note that create
will make a new object and attempt to save it in the database. build
will just build the new object. In your PeopleController you'll want something like this:
def new
@person = Person.new
@person.build_address
end
Based on your need, you can determine whether you want this build
to occur in other actions or in callbacks in the model. But this will get you started.
You'll also need to update the person_params
to
def person_params
params.require(:person).permit(:name, :age, :gender, address_attributes: [:id, :street, :zip_code])
end
Upvotes: 9