My custom validation seems to run before my before_save
block, which is odd to me. I'm aware of before_validation
, but I'm trying to test my custom validator, so a before_validation hook wouldn't allow me to. I've also read that testing a private method (my validator) is bad practice. What should I do?
More info: We want users to be able to upload a Document with either a URL or File, but not both or none (xor). My validator checks the xor of these. If a user edits a Document, the before_save
hook removes the current URL or File. In theory, the flow should be:
But in my tests, I get validation errors, suggesting that the before_save
is not occurring.
after_initialize ↓ (1)
before_validation ↓ (2)
after_validation ↓ (3)
before_save ↓ (4)
before_create ↓ (5)
after_create ↓ (6)
after_save ↓ (7)
after_commit ↓ (8)
Per https://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html, as of Ruby on Rails 5.2.0:
Active Record Callbacks
Callbacks are hooks into the life cycle of an Active Record object that allow you to trigger logic before or after an alteration of the object state. This can be used to make sure that associated and dependent objects are deleted when ActiveRecord::Base#destroy is called (by overwriting before_destroy
) or to massage attributes before they're validated (by overwriting before_validation
). As an example of the callbacks initiated, consider the ActiveRecord::Base#save call for a new record:
(-) 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
Also, an after_rollback
callback can be configured to be triggered whenever a rollback is issued. Check out ActiveRecord::Transactions for more details about after_commit
and after_rollback
.
Additionally, an after_touch
callback is triggered whenever an object is touched.
Lastly an after_find
and after_initialize
callback is triggered for each object that is found and instantiated by a finder, with after_initialize
being triggered after new objects are instantiated as well.
There are nineteen callbacks in total, which give you immense power to react and prepare for each state in the Active Record life cycle. The sequence for calling ActiveRecord::Base#save for an existing record is similar, except that each _create
callback is replaced by the corresponding _update
callback.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With