module Devise::Models::Confirmable

def self.required_fields(klass)

def self.required_fields(klass)
  required_methods = [:confirmation_token, :confirmed_at, :confirmation_sent_at]
  required_methods << :unconfirmed_email if klass.reconfirmable
  required_methods
end

def active_for_authentication?

calculate if the confirm time has not expired for this user.
is already confirmed, it should never be blocked. Otherwise we need to
by verifying whether a user is active to sign in or not. If the user
Overwrites active_for_authentication? for confirmation
def active_for_authentication?
  super && (!confirmation_required? || confirmed? || confirmation_period_valid?)
end

def after_password_reset

def after_password_reset
  super
  confirm! unless confirmed?
end

def confirm!

add errors
is already confirmed, add an error to email field. If the user is invalid
Confirm a user by setting it's confirmed_at to actual time. If the user
def confirm!
  pending_any_confirmation do
    if confirmation_period_expired?
      self.errors.add(:email, :confirmation_period_expired,
        :period => Devise::TimeInflector.time_ago_in_words(self.class.confirm_within.ago))
      return false
    end
    self.confirmation_token = nil
    self.confirmed_at = Time.now.utc
    if self.class.reconfirmable && unconfirmed_email.present?
      skip_reconfirmation!
      self.email = unconfirmed_email
      self.unconfirmed_email = nil
      # We need to validate in such cases to enforce e-mail uniqueness
      save(:validate => true)
    else
      save(:validate => false)
    end
  end
end

def confirmation_period_expired?


confirmation_period_expired? # will always return false
# confirm_within = nil

confirmation_period_expired? # returns true
# confirm_within = 3.days and confirmation_sent_at = 4.days.ago

confirmation_period_expired? # returns false
# confirm_within = 3.days and confirmation_sent_at = 2.days.ago

Examples:
Checks if the user confirmation happens before the token becomes invalid
def confirmation_period_expired?
  self.class.confirm_within && (Time.now > self.confirmation_sent_at + self.class.confirm_within )
end

def confirmation_period_valid?


confirmation_period_valid? # will always return false
# allow_unconfirmed_access_for = 0.days

confirmation_period_valid? # returns false
# allow_unconfirmed_access_for = 5.days and confirmation_sent_at = 5.days.ago

confirmation_period_valid? # returns true
# allow_unconfirmed_access_for = 5.days and confirmation_sent_at = 4.days.ago

confirmation_period_valid? # returns true
# allow_unconfirmed_access_for = 1.day and confirmation_sent_at = today

Example:

Confirm_within is a model configuration, must always be an integer value.
confirmation sent date does not exceed the confirm in time configured.
We do this by calculating if the difference between today and the
Checks if the confirmation for the user is within the limit time.
def confirmation_period_valid?
  confirmation_sent_at && confirmation_sent_at.utc >= self.class.allow_unconfirmed_access_for.ago
end

def confirmation_required?

Callback to overwrite if confirmation is required or not.
def confirmation_required?
  !confirmed?
end

def confirmed?

Verifies whether a user is confirmed or not
def confirmed?
  !!confirmed_at
end

def generate_confirmation_token

this token is being generated
Generates a new random token for confirmation, and stores the time
def generate_confirmation_token
  self.confirmation_token = self.class.confirmation_token
  self.confirmation_sent_at = Time.now.utc
end

def generate_confirmation_token!

def generate_confirmation_token!
  generate_confirmation_token && save(:validate => false)
end

def inactive_message

The message to be shown if the account is inactive.
def inactive_message
  !confirmed? ? :unconfirmed : super
end

def pending_any_confirmation

Checks whether the record requires any confirmation.
def pending_any_confirmation
  if (!confirmed? || pending_reconfirmation?)
    yield
  else
    self.errors.add(:email, :already_confirmed)
    false
  end
end

def pending_reconfirmation?

def pending_reconfirmation?
  self.class.reconfirmable && unconfirmed_email.present?
end

def postpone_email_change?

def postpone_email_change?
  postpone = self.class.reconfirmable && email_changed? && !@bypass_postpone
  @bypass_postpone = nil
  postpone
end

def postpone_email_change_until_confirmation

def postpone_email_change_until_confirmation
  @reconfirmation_required = true
  self.unconfirmed_email = self.email
  self.email = self.email_was
end

def reconfirmation_required?

def reconfirmation_required?
  self.class.reconfirmable && @reconfirmation_required
end

def resend_confirmation_token

Resend confirmation token. This method does not need to generate a new token.
def resend_confirmation_token
  pending_any_confirmation do
    self.confirmation_token = nil if confirmation_period_expired?
    send_confirmation_instructions
  end
end

def send_confirmation_instructions

Send confirmation instructions by email
def send_confirmation_instructions
  self.confirmation_token = nil if reconfirmation_required?
  @reconfirmation_required = false
  generate_confirmation_token! if self.confirmation_token.blank?
  opts = pending_reconfirmation? ? { :to => unconfirmed_email } : { }
  send_devise_notification(:confirmation_instructions, opts)
end

def send_on_create_confirmation_instructions

in models to map to a nice sign up e-mail.
instructions on creation. This can be overriden
A callback method used to deliver confirmation
def send_on_create_confirmation_instructions
  send_devise_notification(:confirmation_instructions)
end

def skip_confirmation!

to be generated, call skip_confirmation!
If you don't want confirmation to be sent on create, neither a code
def skip_confirmation!
  self.confirmed_at = Time.now.utc
end

def skip_reconfirmation!

to be generated, call skip_reconfirmation!
If you don't want reconfirmation to be sent, neither a code
def skip_reconfirmation!
  @bypass_postpone = true
end