before_save在验证后运行吗?

时间:2015-03-25 17:38:29

标签: ruby-on-rails ruby validation testing rspec

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

更多信息:我们希望用户能够使用URL或文件上传文档,但不能同时上传文件,也不能上传任何文件(xor)。我的验证器检查这些的xor。如果用户编辑了文档,before_save挂钩将删除当前的URL或文件。从理论上讲,流程应该是:

  1. 上传文件
  2. 验证并保存
  3. 上传网址
  4. before_save,验证,保存
  5. 但在我的测试中,我收到验证错误,表明before_save没有发生。

2 个答案:

答案 0 :(得分:24)

after_initialize ↓ (1)

before_validation ↓ (2)
after_validation ↓ (3)

before_save ↓ (4) 

before_create ↓ (5)
after_create ↓ (6)

after_save ↓ (7)

after_commit ↓ (8)

答案 1 :(得分:1)

从Ruby on Rails 5.2.0开始,每个https://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html

活动记录回调

回调是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回调代替。