How does has_secure_password work in my model class?
ruby, ruby-on-rails, ruby-on-rails-3
Solution
The easiest way of understanding what anything's doing is to consult the source! In this case, that would be the ActiveModel::SecurePassword documentation. From that, you can see that `has_secure_password` does this:
def has_secure_password
# Load bcrypt-ruby only when has_secure_password is used.
# This is to avoid ActiveModel (and by extension the entire framework) being dependent on a binary library.
gem 'bcrypt-ruby', '~> 3.0.0'
require 'bcrypt'
attr_reader :password
validates_confirmation_of :password
validates_presence_of :password_digest
include InstanceMethodsOnActivation
if respond_to?(:attributes_protected_by_default)
def self.attributes_protected_by_default
super + ['password_digest']
end
end
end
To explain in English, this function:
- Loads the `bcrypt-ruby` Gem and requires `bcrypt`. bcrypt is a secure hashing function that you can learn more about in Wikipedia.
- Adds a read-only attribute to the model called `password`.
- Validates that the password is confirmed by another field, called `password_confirmation`. In other words, you have to enter the password twice to confirm it.
- Ensures that password_digest is present before a model is saved.
- Load the instance methods, which in this case are `authenticate` (which returns true if the password is correct, otherwise false) and `password=`, which encrypts the passed password into the password_digest attribute.
- If the method has attributes that are protected by default, this will also add `password_digest` to that list of protected attributes. (Thus preventing it from being mass assigned.)
You can learn more at the ActiveModel::SecurePassword documentation and the further documentation on its instance attributes.
Problem
I'm doing the Rails tutorial by Michael Hartl, and I've come to the point where you simply add: ``` has_secure_password ``` to your model class and a bunch of magic happens. I understand that this method comes from the `ActiveModel::SecurePassword` module that is included in `ActiveRecord::Base`, which my model class extends. What I don't understand is what is going on when I add that one line to my class definition. Can somebody please explain, in as much detail as possible. I really want to understand what is going on and not just throw stuff at my app not knowing how it works. (If it helps to understand why I'm confused, I come from a Java background and I'm new to Ruby)