What am I doing wrong in this nested form?

I have these 2 models:

class User < ActiveRecord::Base
has_one :city
accepts_nested_attributes_for :city
end

class City < ActiveRecord::Base
belongs_to :user
end

This view:

<%= form_for :user,:url => users_path,:method => :post do |f| %>

<%= f.fields_for :city_attributes do |b| %>
<%= b.collection_select :id,City.all,:id,:name %>
<% end %>

<%= f.label :name %>
<%= f.text_field :name %>
<%= f.submit %>
<% end %>

So, I already have a list of cities added. I want to allow the user to
select from one of the available cities in the select. But, when I
submit the form, I get this error:

Couldn’t find City with ID=1 for User with ID=

What am I doing wrong?

On Apr 7, 8:36am, John C. [email protected] wrote:

This view:

<%= form_for :user,:url => users_path,:method => :post do |f| %>

<%= f.fields_for :city_attributes do |b| %>
<%= b.collection_select :id,City.all,:id,:name %>
<% end %>

With accepts_nested attributes this should just be f.fields_for :city

Fred

If I put f.fields_for :city, this gets generated:

and I get an AssociationMismatch saying
ActiveRecord::AssociationTypeMismatch: City(#36862620) expected, got
Hash(#21169932)

If I put f.fields_for :city_attributes, this gets generated:

Which looks more like what the nested form would accept.

On Apr 7, 10:43am, John C. [email protected] wrote:

Which looks more like what the nested form would accept.

With accepts_nested_attributes you always just use the association
name - you don’t need to mangle things. Also I’m slightly confused by
your models / form. Does a city really belong to a unique user ?

Fred

Ignore the model names and what they stand for :). They are only for
example purpose.

So, if I make my view like this:

<%= form_for :user,:url => users_path,:method => :post do |f| %>

<%= f.fields_for :city do |b| %>
<%= b.collection_select :id,City.all,:id,:name %>
<% end %>

<%= f.label :name %>
<%= f.text_field :name %>
<%= f.submit %>
<% end %>

Then I get the association mismatch:

City(#37602432) expected, got
ActiveSupport::HashWithIndifferentAccess(#32969988)

With these parameters:

{“commit”=>“Save User”,
“authenticity_token”=>“whatever”,
“utf8”=>“✓”,
“user”=>{“city”=>{“id”=>“1”},
“name”=>“as”}}

On Apr 7, 1:37 pm, John C. [email protected] wrote:

Ignore the model names and what they stand for :). They are only for
example purpose.

So, if I make my view like this:

<%= form_for :user,:url => users_path,:method => :post do |f| %>

Oh, for nested attributes to work you need an actual instance of user,
not the symbol :user

<%= f.fields_for :city do |b| %>
<%= b.collection_select :id,City.all,:id,:name %>
<% end %>

I’m not convinced that this will play well with nested attributes.
nested attributes mostly wants to either create a new object or edit
an existing one, whereas you want to choose from a list of objects and
then edit one of those (to set the user_id)

Fred

On Apr 7, 2:19pm, John C. [email protected] wrote:

I guess it’s expecting me to build the city instance in the controller?

correct. field_for on an association that has nested attributes turned
on renders its block for each associated object.

The way I got it to work is by doing this in my model:

def city_attributes=(attribs)
self.city = City.find(attribs[:id])
end

Is there no other way?

It might be easier to just have a city_id virtual attribute rather
than trying to bend accepts_nested_attributes_for (given that you are
currently overriding all of the stuff it gives you)

Fred

If I try to pass an User instance, the select isn’t displayed. Here’s
the view now:

<%= form_for @user,:url => users_path,:method => :post do |f| %>

<%= f.fields_for :city do |b| %>
<%= b.collection_select :id,City.all,:id,:name %>
<% end %>

<%= f.label :name %>
<%= f.text_field :name %>
<%= f.submit %>
<% end %>

I guess it’s expecting me to build the city instance in the controller?
The way I got it to work is by doing this in my model:

def city_attributes=(attribs)
self.city = City.find(attribs[:id])
end

Is there no other way?

But, how would having it as a virtual attribute help? It would not be
saved to the database, so it’s value would be lost.

On Apr 7, 4:57pm, John C. [email protected] wrote:

But, how would having it as a virtual attribute help? It would not be
saved to the database, so it’s value would be lost.

because you’d define city_id= to be basically the same as the
city_attributes method you have above. It’s not very different to what
you have but allows you to get rid of the accepts_nested_attributes
and the fields_for

Fred