Rails 3: rollback for after_create

I have a registration form.

When a user logs in, the application must save the data in the enrollments table and in the users table. (I need this separation because the user profile may change, but the data that he entered for this particular registration must be archived. Therefore, even if the user changes his last name later, I will have his initial information in the registration form.)

So, I was thinking about storing data in an enrollments table, and then has an after_create call like this ...

 class Enrollment < ActiveRecord::Base after_create :save_corresponding_user def save_corresponding_user user = User.new user.full_name = self.user_full_name user.email = self.user_email user.mobile_phone = self.user_mobile_phone user.save end end 

The problem is that if you save the user for some reason. How can I roll back and destroy just saved data from the enrollments table?

+7
source share
4 answers

after_create is part of a transaction that saves the current model. Therefore, if your code fails or if after_create returns false, it should cancel the current transaction and invalidate the enrollment .

If you want to simulate this, add this to your after_create and see if everything works as expected:

 raise Exception.new("CRASH") 
+11
source

Returning false from after_create do nothing.

The entire callback chain ends with a transaction. If any callback method returns exactly false or throws an exception, the execution chain stops and ROLLBACK is thrown; after callbacks can only do this by throwing an exception.

In addition, you should raise ActiveRecord::Rollback :

Any exception that is not ActiveRecord :: Rollback will be raised again by Rails after the callback chain is stopped. Catching an exception other than ActiveRecord :: Rollback can lead to code breaking that does not expect methods like save and update_attributes (which usually try to return true or false) to throw an exception.

http://guides.rubyonrails.org/active_record_callbacks.html#halting-execution

I am doing something like this:

 after_create do if condition errors.add(:attr, 'Blah blah blah.') raise ActiveRecord::Rollback end end 

For Rails 3: http://guides.rubyonrails.org/v3.2.13/active_record_validations_callbacks.html#halting-execution

+9
source

As @anthonyalberto mentioned, after_create is already part of the transaction. To define a transaction, you should use something like this in your controller:

 Enrollment.transaction do @enrollment.save! end 

That’s really all you have to do, if the registration fails or the user fails, it will roll back the whole transaction. Here is some additional information: http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html

+1
source

In rails 5, you need to use throw :abort to roll back the ActiveRecord chain.

enter image description here

You can see a list of processing operations in various versions of Rails, as well as before and after callbacks. For a better understanding, please look at the concept of stopping executions. Please follow the link below.

https://guides.rubyonrails.org/active_record_callbacks.html#halting-execution

0
source

Source: https://habr.com/ru/post/921510/


All Articles