class Shoulda::Matchers::ActiveModel::HaveSecurePasswordMatcher

@private

def authenticate_method

def authenticate_method
  if @attribute == :password
    :authenticate
  else
    "authenticate_#{@attribute}".to_sym
  end
end

def description

def description
  "have a secure password, defined on #{@attribute} attribute"
end

def expected_methods

def expected_methods
  @_expected_methods ||= %I[
    #{authenticate_method}
    #{@attribute}=
    #{@attribute}_confirmation=
    #{@attribute}_digest
    #{@attribute}_digest=
  ]
end

def failure_message_when_negated

def failure_message_when_negated
  MESSAGES[:should_not_have_secure_password] %
    { subject: @subject.class, description: description }
end

def initialize(attribute)

def initialize(attribute)
  @attribute = attribute.to_sym
end

def matches?(subject)

def matches?(subject)
  @subject = subject
  if failure = validate
    key, params = failure
    @failure_message =
      MESSAGES[key] % { subject: subject.class }.merge(params)
  end
  failure.nil?
end

def validate

def validate
  missing_methods = expected_methods.reject do |m|
    subject.respond_to?(m)
  end
  if missing_methods.present?
    [:method_not_found, { methods: missing_methods.to_sentence }]
  else
    subject.send("#{@attribute}=", CORRECT_PASSWORD)
    subject.send("#{@attribute}_confirmation=", CORRECT_PASSWORD)
    if not subject.send(authenticate_method, CORRECT_PASSWORD)
      [:did_not_authenticate_correct_password,
       { attribute: @attribute },]
    elsif subject.send(authenticate_method, INCORRECT_PASSWORD)
      [:authenticated_incorrect_password, { attribute: @attribute }]
    end
  end
end