I have this code in my user model:
class User < ActiveRecord::Base
attr_accessible :email, :password, :password_confirmation
attr_accessor :password
before_save :encrypt_password
validates :email, :presence => true,
:uniqueness => { :case_sensitive => false },
:format => { :with => /\A[^@]+@[^@]+\z/ },
:length => 7..128
validates :password, :presence => true,
:confirmation => true,
:length => 6..128
private
def encrypt_password
return unless password
self.encrypted_password = BCrypt::Password.create(password)
end
end
Now in my controller when I’m updating some user fields with
@user.update_attributes(params[:user])
the password field is always validated, even when it is not set in the params hash. I figured that this is happening because of the attr_accesor :password which always sets password = “” on update_attributes.
Now I could simply skip the validation of password if it is an empty string:
validates :password, :presence => true,
:confirmation => true,
:length => 6..128,
:if => "password.present?"
But this doesn’t work because it allows a user to set an empty password.
Using update_attribute on the field I’d like to change is not a solution because i need validation on that attribute.
If I pass in the exact parameter with
@user.update_attributes(params[:user][:fieldname])
it doesn’t solve the problem because it also triggers password validation.
Isn’t there a way to prevent attr_accesor :password from always setting password = “” on update?
New answer
This works for me:
If I remember correctly it also took me some time to get this right (a lot of trial and error). I never had the time to find out exactly why this works (in contrast to
:if => "password.present?").Old answer – not really useful for your purpose (see comments)
I get around this problem by using a completely different action for password update (user#update_password). Now it is sufficient to only validate the password field
(and also only make it accessible to those actions).
Here some more details:
in your routes:
in your UsersController:
In your edit_password view, you now have a form for only updating the password, very similar to your form in the edit view, but with :method => :put and :url => edit_password_user_path(@user)