Duplication of confirmation email when the callback is triggered from the User DEVISE model

1

I just finished following this guide link which worked perfectly, and activate the confirmable module so that when the admin approves the user's account after registration, a confirmation email will be sent after the parameter of the approved field will change from false to true , because this is achieved through the following callback within the User model:

after_update :user_approved_true

def user_approved_true
   if self.approved == true
      send_confirmation_instructions
   end
end

Well it works perfectly, but in what it fails, is what it does double, I have searched for different methods, used different codes, but I can not get it to avoid duplicate email, someone could help me, some solution!

class AddAdminToUsers < ActiveRecord::Migration
   def change
      add_column :users, :admin, :boolean, default: false
   end
end

PS: I have not generated any Devise driver, I have conditioned everything from the User model.

Here you can see more information about my model:

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable, :confirmable,
         :recoverable, :rememberable, :trackable, :validatable


# Anula el email de confirmacion de usuario una vez este se registra

   after_create :skip_confirmation!

   def skip_confirmation!
     self.confirmed_at = Time.now.utc
   end


# Envia el email de confirmacion una vez el admin aprueba su cuenta [ EL PROBLEMA SE ORIGINA AQUI ]

   after_update :user_approved_true

   def user_approved_true
     if self.approved == true
       send_confirmation_instructions
     end
   end


# Verifica el estado de aprobacion de la cuenta

   def active_for_authentication?
     super && approved?
   end


# Activa el mensaje de alerta de no aprobado por el admin

   def inactive_message
     if !approved?
       :not_approved
     else
       super # Use whatever other message
     end
   end


# Condiciona el reseteo de contraseñas dependiendo el estado aprobacion de la cuenta

   def self.send_reset_password_instructions(attributes={})
     recoverable = find_or_initialize_with_errors(reset_password_keys, attributes, :not_found)
     if !recoverable.approved?
       recoverable.errors[:base] << I18n.t("devise.failure.not_approved")
     elsif recoverable.persisted?
       recoverable.send_reset_password_instructions
     end
     recoverable
   end


# Condiciona confirmar cuenta dependiendo el estado aprobacion de la cuenta

   def self.send_confirmation_instructions(attributes={})
     confirmable = find_or_initialize_with_errors(confirmation_keys, attributes, :not_found)
     if !confirmable.approved?
       confirmable.errors[:base] << I18n.t("devise.failure.not_approved")
     elsif confirmable.persisted?
       confirmable.send_confirmation_instructions
     end
     confirmable
   end

end
    
asked by Hector Hernandez 19.07.2016 в 03:27
source

1 answer

1

Your problem is that when the user is approved this code will be executed every time the user is updated:

   after_update :user_approved_true

   def user_approved_true
     if self.approved == true
       send_confirmation_instructions
     end
   end

This implies that if the name or password is changed, for example, and the user is approved, it will also send the confirmation. You could try:

   def user_approved_true
     send_confirmation_instructions if approved_changed? && approved
   end

This will only call the confirmation method when the value of approved has gone from false to true .

    
answered by 19.07.2016 в 22:38