Hook失效的灵异事件:为什么我的`after_save`回调不执行?

小助手
小助手 版主圣羽星庭 勋望元宿志愿先锋
社区管理
插件开发 100 浏览 13 回复

最近开发会员插件时踩了个坑:在用户模型注册的`after_save`钩子死活不触发,但相同代码在测试环境正常。经过3小时排查,最后发现问题出在模型继承关系上。

错误示范:

class User < ThirdParty::OauthModel
  after_save :sync_member_level

  def sync_member_level
    # 永远执行不到这里
  end
end
```</p>

<p>根本原因是第三方SDK重写了`save`方法却没调用`super`,导致ActiveRecord的回调链断裂。临时解决方案:</p>

```ruby
# 猴子补丁修正父类方法
ThirdParty::OauthModel.class_eval do
  def save(*args)
    super.tap do |result|
      run_callbacks(:save) if result
    end
  end
end

更健壮的方案应该是:

1. 通过`method_defined?`检查父类方法完整性
2. 使用`prepend`方式注入修正逻辑
3. 在插件文档明确标注继承要求

这种隐蔽问题尤其容易出现在:
- 多层继承的模型
- 混用不同ORM框架
- 重写了`save/create/update`等关键方法

评论13
回复 · 13
发光的少年
发光的少年 初级 · #13 ·
感谢分享!
初见
初见 初级 · #12 ·
同求,期待更新
Nina
Nina 初级 · #11 ·
同求,期待更新
Kate
Kate 初级时梦乐园 · #10 ·
写得很清楚,收藏了
SunnyDay
SunnyDay 初级流金绮梦 · #9 ·
已解决,谢谢楼主
张雪博
张雪博 新手赤羽栖云 · #8 ·
已解决,谢谢楼主
GraceSnow
GraceSnow 初级赏金猎人 · #7 ·
已解决,谢谢楼主
BrightPath
BrightPath 初级番响心动 · #6 ·
学到了,顶一下
YukiRain
YukiRain 新手番响心动 · #5 ·
同求,期待更新
MayaPark
MayaPark 初级 · #4 ·
感谢分享!
不期而遇的企鹅
不期而遇的企鹅 初级清瑶问鼎 · #3 ·
感谢分享!
GraceWei
GraceWei 初级 · #2 ·
支持了~
小北
小北 初级圣羽星庭 · #1 ·
同求,期待更新
微信客服 微信客服 QQ官方交流群 QQ官方交流群