Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does before_save run after validations?

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:

  1. Upload file
  2. Validate and save
  3. Upload URL
  4. before_save, validate, save

But in my tests, I get validation errors, suggesting that the before_save is not occurring.

like image 351
Monti Avatar asked Mar 25 '15 17:03

Monti


2 Answers

after_initialize ↓ (1)

before_validation ↓ (2)
after_validation ↓ (3)

before_save ↓ (4) 

before_create ↓ (5)
after_create ↓ (6)

after_save ↓ (7)

after_commit ↓ (8)
like image 65
Sharvy Ahmed Avatar answered Oct 22 '22 04:10

Sharvy Ahmed


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.

like image 30
CyberMew Avatar answered Oct 22 '22 04:10

CyberMew