问题
I have these models:
class User < ActiveRecord::Base
has_one :city
accepts_nested_attributes_for :city
end
class City < ActiveRecord::Base
belongs_to :user
end
This controller action:
def create
@user = User.new(params[:user])
respond_to do |format|
if @user.save
format.html { redirect_to(@user, :notice => 'User was successfully created.') }
format.xml { render :xml => @user, :status => :created, :location => @user }
else
format.html { render :action => "new" }
format.xml { render :xml => @user.errors, :status => :unprocessable_entity }
end
end
end
and this view:
<%= 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 %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
I am trying to allow the user to select a city from the list of already added cities. I am trying to present him a select. The select part it works, but the generated html code for it, looks like this:
<select name="user[city][id]" id="user_city_id">
<option value="1">One</option>
<option value="2">Two</option>
</select>
Notice that it's name doesn't have attribute
anywhere. So, when I try to save it, I get this error:
City(#37815120) expected, got ActiveSupport::HashWithIndifferentAccess(#32969916)
How can I fix this?
EDIT: there is some progress, I tried to change the fields_for to this:
<%= f.fields_for :city_attributes do |b| %>
<%= b.collection_select :id,City.all,:id,:name %>
<% end %>
and now, the html seems to generate correctly. But I get this error now:
Couldn't find City with ID=1 for User with ID=
I have no idea what to do next.
EDIT2: overriding the city_attributes=
method seems to work:
def city_attributes=(attribs)
self.city = City.find(attribs[:id])
end
I don't know if it's the way to go, but it seems good.
回答1:
Have a look at this question that seems similar to yours : Rails 3: How does "accepts_nested_attributes_for" work?
Actually, since the Cities already exsit, I think there is no need for nested forms here.
Try Replacing
<%= f.fields_for :city_attributes do |b| %>
<%= b.collection_select :id,City.all,:id,:name %>
<% end %>
With
<%= f.collection_select :city, City.all,:id,:name %>
Updated afters comments
Could you change your relationship with (and update database scheme accordingly)
class User < ActiveRecord::Base
belongs_to :city
end
class City < ActiveRecord::Base
has_many :users
end
And then try using:
<%= f.collection_select :city_id, City.all,:id,:name %>
回答2:
You could also do a
<%= f.collection_select :city_id, City.all, :id, :name %>
in your view and then add virtual attributes to your User model:
class User < ActiveRecord::Base
...
def city_id(c_id)
update_attribute(:city, City.find(c_id))
end
def city_id
city.id
end
end
This might not be very clean, since the associated City model is "saved" whenever assigning an ID to some_user.city_id. However, this solution keeps your controller and view nice and clean.
Note: you might also want to account for a blank ID being passed in to the setter method.
回答3:
Try this
<%= f.select(:city_id, City.all.collect {|p| [ p.name, p.id ] }) %>
来源:https://stackoverflow.com/questions/5576895/cannot-get-nested-form-with-a-has-one-association-to-work