问题
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). Devise out of the box seems to allow this, but when you remove the validatable module and setup custom validations, it seems you need to work around a bit.
I have setup the following validation in my user model :
validates :password, length: { in: 6..128 }
When signing up, user is required to specify his password (which is what I expect). When updating settings, though, if I leave password blank it raises an error to the user that says password must be at least 6 characters.
How can I work around this without having to change the way Devise works or having to implement a custom controller of some sort ?
回答1:
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.
回答2:
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.
回答3:
Add this code to your user model.
private
def password_required?
new_record? ? super : false
end
回答4:
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
来源:https://stackoverflow.com/questions/12110931/rails3-devise-prevent-password-validation-when-updating