medBouzid
medBouzid

Reputation: 8392

Can't update my nested model form for has_one association

I try to create a nested model form for the has_one association. (i'm using Rails 4)

In my user, and adress model i have the following :

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

class Address < ActiveRecord::Base
 belongs_to :user

end

my user controller :

class UsersController < ApplicationController
    .
    .
    .
    def edit
      @user = User.find(params[:id]) 
      @user.build_address if @user.address.nil?
    end 

    def update
      @user = User.find(params[:id])
      if @user.update(params.require(:user).permit(:user_name, address_attributes: [:street]))
        flash[:success] = "Profile updated successfully"
        sign_in @user
        redirect_to @user
      else
         flash.now[:error] = "Cannot updating your profile"
         render 'edit'
      end
    end
end

finally in my view i have :

= form_for(@user) do |f|
  = render 'shared/error_messages', object: f.object
  %div
    = f.label :user_name, "User name"
    = f.text_field :user_name
    = f.fields_for :address do |add|
      = addd.label :street
      = d.text_field :street
    = f.submit "Update"

When i try to fill street filed for the first time it works, but when i try to update i get the error : Failed to remove the existing associated address. The record failed to save after its foreign key was set to nil

any idea where is the error ? thank's

Upvotes: 26

Views: 12729

Answers (3)

stoodfarback
stoodfarback

Reputation: 1349

There is an option to make it do a partial update if the record already exists:

accepts_nested_attributes_for(:address, update_only: true)

In your controller, include the nested id to the permitted params:

permit(:user_name, address_attributes: [:id, :street])

Documented here: http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html#method-i-accepts_nested_attributes_for

Upvotes: 38

d34n5
d34n5

Reputation: 1318

in your controller UsersController, in the update method, add the address: :id to the address permitted attributes. Like this:

params.require(:user).permit(:user_name, address_attributes: [:id, :street]))

Upvotes: 23

Mohamad
Mohamad

Reputation: 35349

This error usually indicates that there is an existing record for the has_one relationship. In other words, this particular user object already has an address record associated with it. This could happen while testing the form in the browser.

In this case, it seems like Rails is trying to create a new address record, and it has to do with how your edit action is written.

Try this:

def edit
  @user = User.find(params[:id]) 
  @address = user.address || @user.build_address
end 

Upvotes: 0

Related Questions