4

I have 2 models User and Address .

class User < ActiveRecord::Base 
  has_many :addresses
  accepts_nested_attributes_for :addresses
end

class Address < ActiveRecord::Base
  belongs_to :user
end

My controller

  def new
    @user = User.new
    @user.addresses << Address.new
    @user.addresses << Address.new
  end

  def create
    @user = User.new(params[:user])
    if @user.save
      #do something
    else
      render 'new'
    end
  end

And my View

 <%= form_for @user do |f| %>
     <%= f.label :name %>
     <%= f.text_field :name %>
       <%= f.fields_for :addresses do |a| %>
         <p> Home </p>
         <%= a.text_field :state %>
         <%= a.text_field :country%>
         <%= a.text_field :street %>
         <p> Work </p>
         <%= a.text_field :state %>
         <%= a.text_field :country%>
         <%= a.text_field :street %>
       <% end %>
     <% end %>
   <% end %>

My problem is I get only the last state,country,street entered in params .

"addresses_attributes"=>{"0"=>{"street"=>"test", "state"=>"test",, "country"=>"test"},
"1"=>{"street"=>"", "state"=>"", "country"=>""}} 

Also if there's a better way to do this I will appreciate any suggestions .

lesce
  • 6,224
  • 5
  • 29
  • 35
  • What do you mean only the last? the output you show here clearly shows you are receiving both. addresses_attributes[0] and addresses_attributes[1] – Faisal Mar 27 '12 at 10:19
  • yes but I filled out all the fields , and only the last 3 where sent . – lesce Mar 27 '12 at 10:22
  • Example: first 3 fields where filled with 'test0' and the last 3 with 'test' . – lesce Mar 27 '12 at 10:23

2 Answers2

5

The rails API says that fields_for will be repeated by it self over each element in the collection of addresses.

I would suggest adding a kind of label to your addresses (like Work, Home, etc). And then it should work by itself. And with this label your are a bit more flexible when you want to add more addresses.

   <%= f.fields_for :addresses, @user.addresses do |a| %>
     <p> <%= a.object.label %> </p>
     <%= a.text_field :state %>
     <%= a.text_field :country%>
     <%= a.text_field :street %>
   <% end %>
klump
  • 3,259
  • 2
  • 23
  • 26
  • ok I tried what you said and I get an undefined method `is_home_address' for nil:NilClass error , any ideas ? – lesce Mar 27 '12 at 11:11
  • Could you please provide some more information? some line numbers and the code arround this number? I find it quite hard to always guess the errors :P – klump Mar 27 '12 at 11:12
  • ok I fixed the error by wrapping the form in a @user.addresses.each do |address| and adding the address object to fields_for :addresses,address .... and now I can access the object ... but the parameters changed params[:user][:address] and only one of the address is sent . – lesce Mar 27 '12 at 11:24
  • Mhh, you could try `fields_for @user.adresses do |a|`. And revert your last changes. – klump Mar 27 '12 at 11:27
  • ok I did what you said , it seems I only get one address object but I build 2 objects in my controller ... – lesce Mar 27 '12 at 11:40
  • Did you set the label when you build these 2 objects? `@user.addresses.build( label: "Work" )` should do the job for the first one. – klump Mar 27 '12 at 11:45
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/9363/discussion-between-klump-and-lesce) – klump Mar 27 '12 at 11:50
  • yes I did , @user.addresses.build(:label => "work") @user.addresses.build(:label => "home") and I added <%= debug a.object.label %> in the view and it only shows --- home ... – lesce Mar 27 '12 at 11:52
3

fields_for :addresses already do the loop for you so you don't need to repeat state, country and street. So in your case, you can add new field address type then the controller should look like this:

def new
  @user = User.new
  @user.addresses.build(address_type: 'Home')
  @user.addresses.build(address_type: 'Work')
end

Then in the form:

<%= form_for @user do |f| %>
  <%= f.label :name %>
  <%= f.text_field :name %>
    <%= f.fields_for :addresses do |a| %>
      <%= a.hidden_field :address_type %>
      <p><%= a.object.address_type %></p>
      <%= a.text_field :state %>
      <%= a.text_field :country%>
      <%= a.text_field :street %>
    <% end %>
  <% end %>
<% end %>

a.object refer to the address object.

Hoang Nghiem
  • 139
  • 1
  • 7
  • ok I tried what you said and I get an undefined method `is_home_address' for nil:NilClass error , any ideas ? – lesce Mar 27 '12 at 10:55
  • Did you migrate address_type to db? Is that error happen when you visit the form? I updated my answer to add hidden field to address_type so it get persist to db. If you still have problem, then try to debug with: <%= debug a.object %>. – Hoang Nghiem Mar 27 '12 at 11:25
  • I think you should recheck the code within @user.save. Look like there is some code that remove the addresses from user. – Hoang Nghiem Mar 28 '12 at 01:44