Desenvolvimento de plugin: evento disparado se o endereço de e-mail for alterado?

Estou trabalhando em um plugin que adicionará usuários a um grupo se o endereço de e-mail deles corresponder a uma lista de permissões.

Funciona para novos usuários com:

  DiscourseEvent.on(:user_created) do |user|
    GroupDomain.add_to_group_if_in_whitelisted_domain(user)
  end

O que quero fazer a seguir é mover os usuários para o grupo se eles alterarem seu endereço para um domínio correspondente. Eu pensei que

  DiscourseEvent.on(:user_updated) do |user|
    GroupDomain.add_to_group_if_in_whitelisted_domain(user)
  end

resolveria o problema, mas não resolve. (Aí pensei que, se eles alterassem o endereço de e-mail e depois alterassem qualquer outra coisa no registro do usuário, funcionaria, e funciona!)

Existe algum evento que eu possa chamar/monitorar (sou apenas um cavernícola) que seja acionado quando o endereço de e-mail for alterado?

Quanto mais penso nisso, mais acho que não acionar :user_updated quando um endereço de e-mail é alterado parece ser um bug. Antes de termos um modelo user_email, alterar o endereço de e-mail acionava :user_updated.

Mas ter UserEmail assim:

  do

    after_update :trigger_user_updated_event

e com

  def trigger_user_updated_event
    user = User.find(self.user_id)
    DiscourseEvent.trigger(:user_updated, user)
    true
  end

aciona com mais frequência do que deveria (como ao fazer login via link de e-mail) e também causa um erro:

PG::UniqueViolation - ERROR:  duplicate key value violates unique constraint "index_group_users_on_group_id_and_user_id"

Por alguns minutos, achei que sabia o que estava acontecendo. :crying_cat_face:

Não é porque se trata de um modelo diferente, como você descobriu. Desde que as alterações de @LeoMcA foram mescladas, User e UserEmail são modelos distintos, e alterar uma instância de UserEmail não acionará um observador em uma instância de User.

Você pode me dizer a melhor maneira de fazer com que minha função conditionally_add_to_group seja chamada quando o endereço de e-mail for alterado?

Acho que algo assim no plugin.rb vai funcionar

after_initialize do

  add_model_callback(UserEmail, :after_commit, on: :update) do
     # Group.add blablabla
  end

end

Uhuu! Funcionou!

  self.add_model_callback(UserEmail, :after_commit, on: :update) do
    puts "#{'-'*50}\nSIM, O E-MAIL FOI ATUALIZADO para #{self.user_id}!!!!\n#{'-'*50}\n"
    user = User.find(self.user_id)
    GroupDomain.add_to_group_if_in_whitelisted_domain(user)
  end

Muito obrigado, @Falco!