In my app, only admins can create new User records. The user is emailed an activation link where they set their password.
I'd like to use the has_secure_passord method (railscast):
class User < ActiveRecord::Base
has_secure_password
...
end
Works great, but it automatically validates presence of password digest...so when the admin creates the record the validations fail. I there a way to skip just the automatically added password_digest validation without skipping the others I've added?
Since 4.X versions of rails, has_secure_password
takes an option :validations. If you set it to false
, it will not run validations.
The 3.X version of the gem does not support this parameter. However you can backport the activemodel/lib/active_model/secure_password.rb from latest 4.0.XRC code which supports this argument.
So with that, your code will look like this:
class User < ActiveRecord::Base
has_secure_password :validations => false
...
end
I decided to do my own custom authentication. The following solution will validate passwords but only when they are being set. This allows admins to create users without adding a password.
class User < ActiveRecord::Base
include BCrypt
attr_accessor :password, :password_confirmation
validates :password, length: (6..32), confirmation: true, if: :setting_password?
def password=(password)
@password = password
self.password_hash = Password.create(password)
end
def authenticate(password)
password.present? && password_hash.present? && Password.new(password_hash) == password
end
private
def setting_password?
password || password_confirmation
end
end
If someone posts an answer that allows me to still use the has_secure_password
method, I'll accept it instead.
There's no way to skip the validation, but it would be easy enough to write your own version of the method that allows you to pass an argument to determine whether or not to validate presence of the password_digest field.
Just extend ActiveModel
the same way they do in the SecurePassword module (via ActiveSupport::Concern
) and add your own secure password method.
i.e.
module ActiveModel
module MySecurePassword
extend ActiveSupport::Concern
module ClassMethods
def my_has_secure_password(validate_password_digest=true)
# you custom logic
end
end
end
end
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