插件开发-- 如果电子邮件地址更改,是否触发事件?

我正在开发一个插件,当用户的电子邮件地址与白名单匹配时,自动将其添加到某个用户组。

目前,我已经为新建用户实现了以下功能:

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

接下来,我希望当用户修改其电子邮件地址为匹配域时,也能自动将其移动到该用户组。我原本以为以下代码可以实现:

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

但实际并不起作用。(后来我发现,如果用户先修改了电子邮件地址,然后再修改用户记录中的其他内容,该逻辑就会生效!)

是否存在某个事件,可以在用户电子邮件地址被修改时触发?(我只是个新手,不太熟悉这些机制。)

我越想越觉得,当邮箱地址被更改时 :user_updated 未被触发似乎是一个 bug。在我们拥有 user_email 模型之前,更改邮箱地址会触发 :user_updated

但是,让 UserEmail 执行以下操作:

  do

    after_update :trigger_user_updated_event

并配合:

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

会导致该事件比预期更频繁地触发(例如通过邮箱链接登录时),并且还会引发:

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

有那么几分钟,我还以为自己搞懂了。:crying_cat_face:

这并不是因为它们是不同的模型,正如你所发现的。由于 @LeoMcA 的更改已合并,User 和 UserEmail 现在是不同的模型,因此更改 UserEmail 的实例不会触发 User 实例中的观察者。

请问,当电子邮件地址发生变化时,调用 conditionally_add_to_group 函数的最佳方法是什么?

我觉得在 plugin.rb 中像这样写应该就可以了

after_initialize do

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

end

太好了!IT 工作正常!

  self.add_model_callback(UserEmail, :after_commit, on: :update) do
    puts "#{'-'*50}\nEMAIL YES ADDRESS IS UPDATED for #{self.user_id}!!!!\n#{'-'*50}\n"
    user = User.find(self.user_id)
    GroupDomain.add_to_group_if_in_whitelisted_domain(user)
  end

非常感谢,@Falco