Jia Cheng Sun
Jia Cheng Sun

Reputation: 279

Existence of ActiveModel::SecurePassword authenticate method (Rails 6)

The "authenticate" method can only be found here: https://apidock.com/rails/ActiveModel/SecurePassword/InstanceMethodsOnActivation/authenticate , with version 6.0.0 being grayed out. So this seems to be outdated.

I have searched the Rails 6 documentation for the authenticate method, and found no record of it under https://api.rubyonrails.org/classes/ActiveModel/SecurePassword/ClassMethods.html. Yet in the code snippet on the same page

# Schema: User(name:string, password_digest:string, recovery_password_digest:string)
class User < ActiveRecord::Base
  has_secure_password
  has_secure_password :recovery_password, validations: false
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.recovery_password = "42password"
user.recovery_password_digest                              # => "$2a$04$iOfhwahFymCs5weB3BNH/uXkTG65HR.qpW.bNhEjFP3ftli3o5DQC"
user.save                                                  # => true
user.authenticate('notright')                              # => false
user.authenticate('mUc3m00RsqyRe')                         # => user
user.authenticate_recovery_password('42password')          # => user
User.find_by(name: 'david')&.authenticate('notright')      # => false
User.find_by(name: 'david')&.authenticate('mUc3m00RsqyRe') # => user

The authenticate method is still used (user.authenticate). Where does this method come from if I can't find it in the latest documentation?

Edit: A related question regarding differences in documentation: I am able to find ActionDispatch::Request::Session on rubydocs but not on api.rubyonrails. https://www.rubydoc.info/docs/rails/ActionDispatch/Request/Session

https://api.rubyonrails.org/classes/ActionDispatch/Request.html

Now I am not certain where I should be looking when searching for methods. Is api.rubyonrails not the "definitive" place to look for documentation?

Upvotes: 0

Views: 214

Answers (1)

edariedl
edariedl

Reputation: 3352

It looks like they forgot to mention it in the documentation for has_secure_password. If you look into source code of ActiveModel::SecurePassword. You will find

        # Returns +self+ if the password is correct, otherwise +false+.
        #
        #   class User < ActiveRecord::Base
        #     has_secure_password validations: false
        #   end
        #
        #   user = User.new(name: 'david', password: 'mUc3m00RsqyRe')
        #   user.save
        #   user.authenticate_password('notright')      # => false
        #   user.authenticate_password('mUc3m00RsqyRe') # => user
        define_method("authenticate_#{attribute}") do |unencrypted_password|
          attribute_digest = public_send("#{attribute}_digest")
          BCrypt::Password.new(attribute_digest).is_password?(unencrypted_password) && self
        end

        alias_method :authenticate, :authenticate_password if attribute == :password

You can se it is now defined as dynamic method based on the parametr name provided to has_secure_password method. So they implemented it in more general way. And to be more friendly with backwards compatibility the implemented the alias authenticate for authenticate_password which was the original implementation.

Unfortunately these dynamic methods are not very well documented in the rails API docs.

Upvotes: 2

Related Questions