I\'ve looking for a way to allow users to change their settings (User model) without having to change their password (they still have to enter their current password). Devis
I tried Amal Kumar S solution, but unfortunately it didn't help me to solve the same issue, so here is modified version of solution tested in real project.
Here is the code from devise/models/validatable.rb module
protected
# Checks whether a password is needed or not. For validations only.
# Passwords are always required if it's a new record, or if the password
# or confirmation are being set somewhere.
def password_required?
!persisted? || !password.nil? || !password_confirmation.nil?
end
The validation fails when you leave blank password and password confirmation fields while updating user info, because this condition is always false:
!password.nil? || !password_confirmation.nil?
Password and password_confirmation fields equals blank string '' which is never equals to nil. So you can fix that by overriding password_required? method in your user model and change nil? check to blank? check.
protected
def password_required?
!persisted? || !password.blank? || !password_confirmation.blank?
end
Think that it's easiest way to fix that and it's doesn't ruin original logic. Maybe it's devise's bug.
Maybe this will look obvious for some, but it took me a while getting this together. After a few hours of trying different solutions and workarounds and looking all over the place, I dove deeper in Rails validations and found a few constructs that, when put together, make this really easy.
All I had to do was setup a validation for the create action and one for the update action and allow blanks on update.
validates :password, length: { in: 6..128 }, on: :create
validates :password, length: { in: 6..128 }, on: :update, allow_blank: true
With that, I'm getting the behaviour I want and it's only two short lines of code.
Additional note :
At first, I had tried this way :
validates :password, length: { in: 6..128 }, on: :create
This is wrong because it would skip the validation entirely on updates. Users would then be able to set short/long (or blank?) passwords when updating settings.
Devise has its own method to achieve that, update_without_password, It updates record attributes without asking for the current password. Never allows a change to the current password.
Note. If you are using this method, you should probably override this method to protect other attributes you would not like to be updated without a password.
Example:
def update_without_password(params={})
params.delete(:email)
super(params)
end
It is all in the Devise Documentation. http://rdoc.info/gems/devise/index
Add this code to your user model.
private
def password_required?
new_record? ? super : false
end