0

I'm debugging this problem with devise-- despite my best efforts I am still getting an error "password can't be blank" when updating a user without providing a password. I have tried the official solution, as well as the solution suggested in this SO question, but I am still getting the error despite ensuring the opts passed to update_attributes does not contain password or password_confirmation.

I am trying to figure out how to debug this-- I am poking around in devise, activerecord, activemodel, etc, but I can't seem to stick a debug statement in exactly the right spot.

When I run User.validators, I get the following output:

=> [#<ActiveRecord::Validations::PresenceValidator:0x007ff513507890 @attributes=[:email], @options={:if=>:email_required?}>,
 #<ActiveRecord::Validations::UniquenessValidator:0x007ff51350fef0
  @attributes=[:email],
  @klass=
   User(id: integer, name: string, email: string, encrypted_password: string, reset_password_token: string, reset_password_sent_at: datetime, remember_created_at: datetime, sign_in_count: integer, current_sign_in_at: datetime, last_sign_in_at: datetime, current_sign_in_ip: string, last_sign_in_ip: string, created_at: datetime, updated_at: datetime, school_id: integer, invitation_token: string, invitation_created_at: datetime, invitation_sent_at: datetime, invitation_accepted_at: datetime, invitation_limit: integer, invited_by_id: integer, invited_by_type: string, type: string, opt_in: boolean),
  @options={:case_sensitive=>true, :allow_blank=>true, :if=>:email_changed?}>,
 #<ActiveModel::Validations::FormatValidator:0x007ff51351c560
  @attributes=[:email],
  @options={:with=>/\A[^@\s]+@([^@\s]+\.)+[^@\s]+\z/, :allow_blank=>true, :if=>:email_changed?}>,
 #<ActiveRecord::Validations::PresenceValidator:0x007ff5148e4b60 @attributes=[:password], @options={:if=>:password_required?}>,
 #<ActiveModel::Validations::ConfirmationValidator:0x007ff50efb85a0 @attributes=[:password], @options={:if=>:password_required?}>,
 #<ActiveModel::Validations::LengthValidator:0x007ff5150e91d0
  @attributes=[:password],
  @options={:allow_blank=>true, :minimum=>8, :maximum=>128}>,
 #<ActiveRecord::Validations::PresenceValidator:0x007ff515125a90 @attributes=[:name], @options={}>]

Devise itself is (in theory) smart enough to not ask for a password if you haven't changed it:

devise/lib/devise/models/validatable.rb

validates_presence_of     :password, if: :password_required?
validates_confirmation_of :password, if: :password_required?

# ... 
def password_required?
  !persisted? || !password.nil? || !password_confirmation.nil?
end

And you can see this is reflected in the User.validators check above.

However, I am still getting this error!

How can I track down where this error is being added to the object, and who inserted the offending validator?

Community
  • 1
  • 1
joshwa
  • 1,660
  • 3
  • 17
  • 26
  • Are you passing any blank password field with the edit form parameters? – TarunJadhwani May 19 '15 at 17:12
  • @TarunJadhwani yes, but I am deleting it from the hash I pass to update_attributes. Have verified this with debugger. The only thing that gets passed is another attribute (`{:opt_in: true}`). – joshwa May 19 '15 at 18:39

1 Answers1

0

Have you added below code in registration controller?

class RegistrationsController < Devise::RegistrationsController

  protected

  def update_resource(resource, params)
    resource.update_without_password(params)
  end
end

And the route in routes.rb

devise_for :users, controllers: {registrations: 'registrations'}
TarunJadhwani
  • 1,151
  • 7
  • 21
  • I have tried both approaches listed on that devise wiki page-- neither update_attributes nor update_without_password manages to bypass the rogue validator. I don't need a solution to the problem, per se; I need a good method for debugging it! – joshwa May 21 '15 at 06:14