You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails中获取字段旧值应使用哪个回调?状态变更触发邮件场景

问题分析与解决方案

原代码的核心问题在于使用了before_action回调,它会在update动作处理参数更新之前执行。此时@ad还是数据库里的旧数据,新的status值还没被赋值到对象上,所以@ad.status_published?判断的是旧状态,永远满足不了“新值为published”的条件,导致邮件无法发送。

方案一:控制器改用after_action

把回调改成after_action,确保在update动作完成、@ad已经更新后再执行判断逻辑:

class Shop::AdsController < Admin2Controller
  before_action :set_ad, only: %i[edit update destroy]
  after_action :send_notification_if_published, only: :update

  def send_notification_if_published
    # 用status_was获取旧值,判断旧值不是published且新值是published
    return unless @ad.status_was != 'published' && @ad.status == 'published'
    notification = Notification.find_by(action: 'ad_published')

    subscribed_users = User.joins(:notification_preferences)
                           .where(notification_preferences: { notification_id: notification.id })

    subscribed_users.each do |user|
      NotificationsMailer.new(user, notification, self).deliver_later
    end
  end
end

方案二:将逻辑移至模型层(推荐)

业务逻辑放在模型层更符合MVC设计原则,也能让控制器更简洁,且逻辑适用场景更通用:

模型代码(示例路径:app/models/ad.rb):

class Ad < ApplicationRecord
  after_save :send_published_notification, if: :just_published?

  private

  def just_published?
    status_was != 'published' && status == 'published'
  end

  def send_published_notification
    notification = Notification.find_by(action: 'ad_published')
    return unless notification

    subscribed_users = User.joins(:notification_preferences)
                           .where(notification_preferences: { notification_id: notification.id })

    subscribed_users.each do |user|
      NotificationsMailer.new(user, notification, self).deliver_later
    end
  end
end

控制器代码简化:

class Shop::AdsController < Admin2Controller
  before_action :set_ad, only: %i[edit update destroy]

  # 原有update动作保持不变,无需额外回调
end

这样不管是通过控制器更新,还是其他方式(比如后台任务、控制台)修改广告状态,只要满足“从非published变为published”的条件,都会自动触发邮件通知。

内容的提问来源于stack exchange,提问作者Ben

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 08:07:46