Rails 3.1: accepts_nested_attributes_for and has_one - not working?

I am trying to use accepts_nested_attributes_for for the has_one association model and get absolutely nowhere: - (

I have two models, user and location. The user has one location:

class User < ActiveRecord::Base # current location has_one :location, :dependent => :destroy accepts_nested_attributes_for :location end class Location < ActiveRecord::Base belongs_to :user end 

I can save the changes to the model using User.find(1).location.current_location_text = "blah" from the console, so I know that the associations are configured correctly.

I have two forms on the rights editing page. One that updates the basic user attributes (and works fine, not shown below), and then this that allows the user to update the location model attribute called "current_location_text":

 <%= form_for(@user) do |f| %> <%= fields_for(@user.location) do |location_fields| %> <%= location_fields.label :current_location_text, 'Current Location' %> <%= location_fields.text_field :current_location_text, :placeholder => 'Road, City or Postcode' %> <% end %> <%= f.submit "Update Current Location" %> <% end %> 

This does not work. I'm a little confused as the parameters submitted by the form do not look right. When the form is submitted, it is in the log:

 Started PUT "/users/1" for 127.0.0.1 at 2011-10-08 00:28:05 +0100 Processing by UsersController#update as HTML Parameters: {"utf8"=>"βœ“", "authenticity_token"=>"YdTAsXwEvRgXIqri+jfx3dLlYG2XWQTuYkgLDsO/OJw=", "location"=>{"current_location_text"=>"E14 8JS"}, "commit"=>"Update Current Location", "id"=>"1"} User Load (10.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1 User Load (5.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = ? LIMIT 1 [["id", "1"]] SQL (4.4ms) BEGIN (2.5ms) COMMIT Redirected to http://localhost:3000/users/1 

Two things that I find strange in this regard:

  • There is a β€œCOMMIT” message here, but without the previous update line and without errors. for example, if you tried to commit a protected attribute, you will receive an error message "You cannot assign ..." at this point.

  • Parameters do not look right. The "location" bit is nested as I expected, but I would also expect it to be nested in the "user" hash code, something like this:

      {"utf8"=>"βœ“", "authenticity_token"=>"YdTAsXwEvRgXIqri+jfx3dLlYG2XWQTuYkgLDsO/OJw=", "user"=>{"location"=>{"current_location_text"=>"E14 8JS"}, "commit"=>"Update Current Location", "id"=>"1"}} 

I don’t think I'm completely stupid here. Did I miss something really obvious? I tried to add additional hidden fields to my form, that is, the user ID, and then get the user’s hash code, but at the same level as the hash location, and not as the parent element as I expected!

Also, if that helps, here is my update in my UserController:

def update @user = User.find (params [: id])

 if @user.update_attributes(params[:user]) redirect_to current_user, :notice => 'User was successfully updated.' else render :action => "edit" end 

end

and this is what is on my .rb routes (although I don't think this is relevant):

 resources :users do resource :location end 

Any help appreciated. If I do not solve this, the laptop will exit the window .... Thank you.

+8
ruby-on-rails
source share
2 answers
 <%= fields_for(@user.location) do |location_fields| %> 

It's your problem. You need to actually β€œnest” the fields in your form, for example:

 <% f.fields_for(@user.location) do |location_fields| -%> 
+11
source share

Try this instead

 <%= f.fields_for :location do |location_fields| %> 

Instead of giving it the object itself, tell the rails which association you want to load for

+5
source share

All Articles