验证后 before_save 运行 吗?

Does before_save run after validations?

我的自定义验证似乎 运行 在我的 before_save 块之前,这对我来说很奇怪。我知道 before_validation,但我正在尝试测试我的自定义验证器,因此 before_validation 挂钩不允许我这样做。我还读到测试私有方法(我的验证器)是不好的做法。我该怎么办?

更多信息:我们希望用户能够上传带有 URL 或文件的文档,但不能同时上传或 none (xor)。我的验证器检查这些的异或。如果用户编辑文档,before_save 挂钩会删除当前的 URL 或文件。理论上流量应该是:

  1. 上传文件
  2. 验证并保存
  3. 上传URL
  4. before_save、验证、保存

但在我的测试中,我收到验证错误,表明 before_save 没有发生。

after_initialize ↓ (1)

before_validation ↓ (2)
after_validation ↓ (3)

before_save ↓ (4) 

before_create ↓ (5)
after_create ↓ (6)

after_save ↓ (7)

after_commit ↓ (8)

根据 https://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html,从 Ruby 到 Rails 5.2.0:

活动记录回调

回调是 Active Record 对象生命周期的挂钩,允许您在对象状态更改之前或之后触发逻辑。这可用于确保在调用 ActiveRecord::Base#destroy 时删除关联和依赖对象(通过覆盖 before_destroy)或在验证属性之前对其进行处理(通过覆盖 before_validation ).作为启动回调的示例,考虑对新记录的 ActiveRecord::Base#save 调用:

  • (-) save

  • (-) valid

  • (1) before_validation

  • (-) validate

  • (2) after_validation

  • (3) before_save

  • (4) before_create

  • (-) create

  • (5) after_create

  • (6) after_save

  • (7) after_commit

此外,可以将 after_rollback 回调配置为在发出回滚时触发。查看 ActiveRecord::Transactions 了解有关 after_commitafter_rollback 的更多详细信息。

此外,只要触摸对象,就会触发 after_touch 回调。

最后,为查找器找到并实例化的每个对象触发 after_findafter_initialize 回调,在实例化新对象后也会触发 after_initialize

总共有 19 个回调,它们为您提供了强大的反应能力,可以为 Active Record 生命周期中的每个状态做好准备。为现有记录调用 ActiveRecord::Base#save 的顺序类似,只是每个 _create 回调被相应的 _update 回调替换。