Module: ActiveModel::SecurePassword::ClassMethods

Defined in:
activemodel/lib/active_model/secure_password.rb

Instance Method Summary collapse

Instance Method Details

#has_secure_password(options = {}) ⇒ Object

Adds methods to set and authenticate against a BCrypt password. This mechanism requires you to have a password_digest attribute.

Validations for presence of password on create, confirmation of password (using a password_confirmation attribute) are automatically added. If you wish to turn off validations, pass validations: false as an argument. You can add more validations by hand if need be.

If you don't need the confirmation validation, just don't set any value to the password_confirmation attribute and the validation will not be triggered.

You need to add bcrypt (~> 3.1.7) to Gemfile to use #has_secure_password:

gem 'bcrypt', '~> 3.1.7'

Example using Active Record (which automatically includes ActiveModel::SecurePassword):

# Schema: User(name:string, password_digest:string)
class User < ActiveRecord::Base
  has_secure_password
end

user = User.new(name: 'david', password: '', password_confirmation: 'nomatch')
user.save                                                       # => false, password required
user.password = 'mUc3m00RsqyRe'
user.save                                                       # => false, confirmation doesn't match
user.password_confirmation = 'mUc3m00RsqyRe'
user.save                                                       # => true
user.authenticate('notright')                                   # => false
user.authenticate('mUc3m00RsqyRe')                              # => user
User.find_by(name: 'david').try(:authenticate, 'notright')      # => false
User.find_by(name: 'david').try(:authenticate, 'mUc3m00RsqyRe') # => user

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'activemodel/lib/active_model/secure_password.rb', line 44

def has_secure_password(options = {})
  # Load bcrypt gem only when has_secure_password is used.
  # This is to avoid ActiveModel (and by extension the entire framework)
  # being dependent on a binary library.
  begin
    require 'bcrypt'
  rescue LoadError
    $stderr.puts "You don't have bcrypt installed in your application. Please add it to your Gemfile and run bundle install"
    raise
  end

  attr_reader :password

  include InstanceMethodsOnActivation

  if options.fetch(:validations, true)
    # This ensures the model has a password by checking whether the password_digest
    # is present, so that this works with both new and existing records. However,
    # when there is an error, the message is added to the password attribute instead
    # so that the error message will make sense to the end-user.
    validate do |record|
      record.errors.add(:password, :blank) unless record.password_digest.present?
    end

    validates_confirmation_of :password, if: ->{ password.present? }
  end

  if respond_to?(:attributes_protected_by_default)
    def self.attributes_protected_by_default #:nodoc:
      super + ['password_digest']
    end
  end
end