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!
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? }
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.
Ended up here googling this error message, and using
@account.encrypted_password_changed?
in my case yielded what I wanted.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With