تطوير الإضافات: هل يتم إطلاق حدث عند تغيير عنوان البريد الإلكتروني؟

أعمل على إضافة (plugin) ستقوم بإضافة المستخدمين إلى مجموعة إذا تطابق عنوان بريدهم الإلكتروني مع قائمة بيضاء (whitelist).

لقد نجحت في جعلها تعمل للمستخدمين الجدد باستخدام:

  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 عند تغيير عنوان البريد الإلكتروني يبدو وكأنه عيب. في الماضي، قبل وجود نموذج 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 لن يُفعّل مراقبًا (watcher) في مثيل من User.

هل يمكنك إخباري بأفضل طريقة لاستدعاء دالة conditionally_add_to_group عند تغيير عنوان البريد الإلكتروني؟

أعتقد أن شيئًا مثل هذا في plugin.rb سيعمل

after_initialize do

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

end

هاو! يعمل!

  self.add_model_callback(UserEmail, :after_commit, on: :update) do
    puts "#{'-'*50}\nتم تحديث عنوان البريد الإلكتروني بنجاح لـ #{self.user_id}!!!!\n#{'-'*50}\n"
    user = User.find(self.user_id)
    GroupDomain.add_to_group_if_in_whitelisted_domain(user)
  end

شكرًا جزيلًا لك، @Falco!