1
votes

I have user model, and each user has_one profile model. I want to update profile model. But there just two attributes in User model (first_name, and last_name). So I used accepts_nested_attributes_for.

When I call update action, I receive the following errors on profile model:

  1. email can't be blank
  2. password can't be blank

The following my code:

User Model:

class User < ActiveRecord::Base 
   devise :database_authenticatable, :registerable,
     :recoverable, :rememberable, :trackable, :validatable,
     :confirmable
   has_one :profile
end

Profile Model:

class Profile < ActiveRecord::Base
 belongs_to :user
 accepts_nested_attributes_for :user
end

Profile controller - update action

class ProfilesController < ApplicationController
   def profile_params
      params.require(:profile).permit(:current_city_id, :current_country_id, :google_plus_page_url, :linkedin_page_url, :facebook_page_url, :skype_id, :user_attributes => [:first_name, :last_name])
  end
  def update
     @profile = Profile.find_by_id(params[:profile_id])
     respond_to do |format|
       if @profile.update(profile_params)
          format.json { render :show, status: :ok, location: @profile }
       else
          format.json { render json: @profile.errors, status: :unprocessable_entity }
       end
     end
  end
end

So, How can I update profile with user's nested attributes without email & password (In Profile Controller Not in devise controller) ??

3

3 Answers

1
votes

When I call update action, I receive the following errors on profile model:

  • email can't be blank
  • password can't be blank

Looks like the devise validation happen.

Remove :validatable from the use model:

class User < ActiveRecord::Base 
   devise :database_authenticatable, :registerable,
     :recoverable, :rememberable, :trackable, :confirmable
   has_one :profile
end

Or change this validation to something smarter, say on: :create only.

class User < ActiveRecord::Base 
   devise :database_authenticatable, :registerable,
     :recoverable, :rememberable, :trackable, :confirmable
   has_one :profile
   validates :email, presence: true, email: true, on: :create
   validates :password, presence: true, on: :create
end
0
votes

For new searchers, encountered this today. After hours of searching for nothing and failing, what I did was I tried to add the id as a hidden_field of the nested devise model fields. It fixed my problem.

ex:

<%= form.fields_for :users do |f| %>
  <%= f.hidden_field :id %>
  <%= f.text_field :firstname %>
  <%= f.text_field :lastname %>
<% end %>

No need to update or override the devise validations.

Strange. If you don't add the devise model id in the nested fields the update would treat the action for the nested model as a create action, causing devise to ask for the email and password fields.

Upsetting. No sign of the create action in the rails logs. If only there was a sign that the action went on to create, would have fixed this early.

Thanks.

-2
votes

I believe accepts_attributes_for should be on the User model instead of the Profile model.

User model

class User < ActiveRecord::Base 
  devise :database_authenticatable, :registerable,
    :recoverable, :rememberable, :trackable, :validatable,
    :confirmable
  has_one :profile
  accepts_nested_attributes_for :profile
end

Profile model

class Profile < ActiveRecord::Base
  belongs_to :user
end