Cannot get nested form using has_one association

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 is the action of the controller:

  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'm trying to present him a choice. The part of the selection in which 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> 

Please note that this name does not have attribute anywhere. Therefore, 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 changing the fields for this:

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

and now, html seems to be generated correctly. But now I get this error:

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

I do not know 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 do not know if this is the way, but it seems good.

+4
source share
3 answers

Have a look at this question similar to yours: Rails 3: How does "accepts_nested_attributes_for" work?

Actually, since cities already exist, I think that there is no need for nested forms.

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 comments after processing

Could you change your relationship with (and update the database schema 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
source

You can also do

<%= f.collection_select :city_id, City.all, :id, :name %>

in your view, and then add the virtual attributes to the 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 may not be very clean, because the associated city model is “saved” when the identifier some_user.city_id is assigned. However, this solution supports your controller and looks beautiful and clean.

Note: you may also need to specify an empty identifier passed to the setter method.

+1
source

try it

<% = f.select (: city_id, City.all.collect {| p | [p.name, p.id]})%>

0
source

Source: https://habr.com/ru/post/1347044/


All Articles