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)

Original source