Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Undefined method password_changed? Error

I'm trying to set my program so that the password only is validated if it is changed (so a user can edit other information without having to put in their password).

I am currently getting an error that says

NoMethodError in UsersController#create, undefined method `password_changed?' for #<User:0x00000100d1d7a0>

when I try to log in.

Here is my validation code in user.rb:

    validates :name,  :presence => true,
 :length   => { :maximum => 50 }
validates :email, :presence   => true,
:format     => { :with => email_regex },
:uniqueness => { :case_sensitive => false }
validates :password, :presence =>true, :confirmation => true, :length => { :within => 6..40 }, :if=>:password_changed?  

Here is my create method in users_controller.rb:

def create
    @user = User.new(params[:user])
    if @user.save
        sign_in @user
        flash[:success] = "Welcome to the Sample App!"
        redirect_to @user
    else
        @title = "Sign up"
        render 'new'
    end
end

Thank you!

like image 649
steffi2392 Avatar asked Aug 16 '11 15:08

steffi2392


4 Answers

Replace with:

:if => lambda {|user| user.password_changed? }

I'd do two different validations:

validates :password, :presence =>true, :confirmation => true, :length => { :within => 6..40 }, :on => :create
validates :password, :confirmation => true, :length => { :within => 6..40 }, :on => :update, :unless => lambda{ |user| user.password.blank? }  
like image 197
apneadiving Avatar answered Nov 14 '22 13:11

apneadiving


I encountered this same problem and after reading this post I implemented the code suggested by apneadiving in his answer but with a slight modification:

I used two different validations, one for create:

validates :password, :presence => true, :confirmation => true, :length => { :within => 6..128 }, :on => :create

and then I used this one for update:

validates :password, :presence => true, :confirmation => true, :length => { :within => 6..128 }, :on => :update, :unless => lambda{ |user| user.password.to_s.empty? }

Originally, I Implemented exactly what apneadiving suggested, but I realized that on updates to the user it wasn't actually validating the presence of a string. As in, it was allowing a user to set their password to " " (A string of whitespace). This is due to the fact that " ".blank? == true, and so if you have it set to validate like this:

:unless => lambda { |user| user.password.blank? }

Then it won't run the validation if a string full of whitespace is submitted by the user is submitted because it reads the string as being blank. This essentially invalidates the effect of validating for presence on the update. The reason I did password.to_s.empty? instead of simply password.empty? is to prevent errors if someone calls update_attributes on the user model and doesn't pass in anything into the password, field, then the password will be nil, and since the ruby nil class doesn't have an empty? method, it will throw an error. Calling .to_s on nil, however will convert it to an empty string, which will return true on a successive .empty? call (thus the validation won't run). So after some trials and tribulation I found that this was the best way to do it.

like image 38
Batkins Avatar answered Nov 14 '22 11:11

Batkins


Ended up here googling this error message, and using

@account.encrypted_password_changed?

in my case yielded what I wanted.

like image 43
tirdadc Avatar answered Nov 14 '22 12:11

tirdadc


The change to look for, in Rails 4 at least, is password_digest.

@account.password = "my new password"
@account.changes # => {"password_digest"=>["$2a$10$nR./uTAmcO0CmUSd5xOP2OMf8n7/vXuMD6EAgvCIsnoJDMpOzYzsa", "$2a$10$pVM18wPMzkyH5zQBvcf6ruJry22Yn8w7BrJ4U78o08eU/GMIqQUBW"]}
@account.password_digest_changed? # => true
like image 1
Jacob Evan Shreve Avatar answered Nov 14 '22 13:11

Jacob Evan Shreve