Learn about Active Record Callbacks in Ruby on Rails

Tram Ho

Introduce

Callbacks are not a new concept, it is quite familiar and appears in most programming languages. In C ++, we know callback through delegate concept (function pointer). For a Rails application, when we use methods such as before_action, before_create, etc., we are using callbacks. And in this article we are going to learn more about callbacks in ruby ​​on rails. First, we will learn about the development life cycle of the object.

1. The development life cycle of the object

During the operation of the Rails application, objects are created, which can be updated and destroyed. Active Record in Rails provides us with “hooks” in the object’s development lifecycle so that we can control and control their data. Callback allows us to activate a certain logic before or after the object state changes. And we can define it as below.

2. Definition.

Callback is a method of Active Record, it will be called at some point in the lifecycle of an object. Allows us to execute previously declared methods automatically before or after the object has been created, saved, updated, deleted, validated or loaded from the database. So when should we use callback?

3. When to use callbacks.

Consider the following small example: Assume in UsersController need to handle actions like show, edit, update, delete as follows:

As you can see, all four actions perform a job at the beginning of the action, to find the user in the users table using the params [: id] passed. Instead of duplicating such code, we can handle generating callbacks to find the user before the action. As follows:

With the above code we have done a number of operations:

  • Declare the load_user method to find the user and handle it when the user cannot be found based on the passed id id.
  • Use callbacks before_action call to load_user has been declared, and only callback for these 4 methods.

Compared to the older code that may be longer but looks neat and clean, the program is also easy to fix or fix errors

4. Create and register callbacks.

As in the example above, we will first write the logical method we need to handle as in the above example:

Then we register them:

Or we can declare quickly and briefly as block as follows:

5. List of available callbacks

The following is a list of all Active Record callbacks available, listed in the order they will be called in their respective operations:

5.1 Create object

  1. before_validation
  2. after_validation
  3. before_save
  4. around_save
  5. before_create
  6. around_create
  7. after_create
  8. after_save
  9. after_commit / after_rollback

5.2 Updating object

  1. before_validation
  2. after_validation
  3. before_save
  4. around_save
  5. before_update
  6. around_update
  7. after_update
  8. after_save
  9. after_commit / after_rollback

5.3 Delete the object

  1. before_destroy
  2. around_destroy
  3. after_destroy
  4. after_commit / after_rollback

The after_save callbacks run after create and update. If you only want after creating, you can use after_create and after update to after_update.

Before_destroy callbacks should be placed before dependent:: destroy associations (or use the Prepend: true option) to ensure they execute before the dependent records are deleted.

There are also some other callbacks like:

  • after_initialize is called whenever an Active Record Object is created, regardless of whether it is new with new or just a record loaded from the database.
  • after_find is called whenever Active Record loads a record from the database. After_find is called before after_initialize if both are defined
  • after_commit / after_rollback are two callbacks triggered by the completion of a transaction against the database. They will not be executed until the changes in the database are committed or rollback

6. Run callbacks.

6.1 The following methods trigger run callbacks:

  • create
  • create!
  • destroy
  • destroy!
  • destroy_all
  • save
  • save!
  • save (validate: false)
  • toggle!
  • touch
  • update_attribute
  • update
  • update!
  • valid?

6.2 After_find callbacks are triggered by the following search methods:

  • all
  • first
  • find
  • find_by
  • find_by_ *
  • find_by_ *!
  • find_by_sql
  • last

6.3 After_initialize callbacks are triggered every time a new class object is instantiated.

7 Ignore callbacks

Like validation, we can bypass callbacks by doing one of the following:

  • decrement!
  • decrement_counter
  • delete
  • delete_all
  • increment!
  • increment_counter
  • update_column
  • update_columns
  • update_all
  • update_counters

Or simply, if you want the execution of the handling in the callbacks to apply only to certain actions, you can use keywords like only or except as we used in the original example.

However, the use of these callbacks should be careful and scrutinized. Ignore callbacks may result in invalid data.

8. Conditional callbacks.

We can set up calling a callbacks if we meet certain conditions. To do that, we’ll use two if and unless options together with the symbol, proc or an array.

8.1 Use if or unless with symbol.

Specific example:

Before the action will call load_rate callback if is_rated? returns true. Or we can use unless! : is_rated? instead of using unless.

This means that it will load out the rate if this user has rated it.

8.2 Use if or unless with proc.

Similarly we can use conditional with proc:

The same meaning as the above example

8.3 Callbacks are multiple conditions.

We can use multiple conditions for a callbacks, for example:

In callbacks before_action will load the assessment if this user has rated, and this user is not the author of this article.

9. Customize Callbacks

To be able to customize the callbacks, then we need to understand the mechanism of operation of the callbacks, everything will be much easier.

9.1 ActiveSupport

Callback methods in Active Record are created with the support of ActiveSupport.

ActiveSupport is a module in Rails that provides the most necessary tools to allow other modules after including ActiveSupport to create its own callback.

In ActiveSupport, we declare three important and most essential methods to create a callback:

  • define_callbacks: Defining events in an operation cycle of the object will be supported callback, such as save, destroy, update, … are quite common events, with define_callback we can customize one by ourselves. Callback for yourself.
  • set_callback: Set the instance method or proc, … to be ready to be called, can understand to install the methods declared earlier and ready to wait until being called.
  • run_callback: Run methods that have been previously installed by set_callback at an appropriate time.

9.2 How ActiveRecord uses ActiveSupport to create Callback

First, consider ActiveRecord :: Callbacks module:

It can be seen that the define_model_callbacks method passes the parameters: initialize,: find,: touch,: save,: create,: update,: destroy this is where the callbacks are created.

When declaring methods create, update, destroy, … every method calls run_callback which means that every time these methods are activated, it will call the callback first, run the callback and then run the commands. inside.

9.3 Customize callbacks

To make it easier to understand, we will go into a specific example. Take the example of the Viblo page, when a user changes the post from Private draft to Public status, the users who are following this user will receive notification of new posts. To create a callback in the model we must extend the ActiveModel :: Callbacks module that Rails provides:

ActiveModel :: Callbacks provide several methods to make callback very easy:

  • define_model_callbacks always implement the function of the set_callback function when determining when to run the callback with an options parameter. In this case, only:: before
  • The method: publish method and the scope of the code will be specified to run the callback
  • Method declaration will be callback. In this case notify_subscribed_users will be run immediately below the code line puts “Make this post public”

summary

So we have learned about callbacks in rails. It gives us a lot of benefits, but we shouldn’t overdo it.

My article here is the end. Hope your post can help you better understand callbacks and use it optimally. The article is also difficult to avoid mistakes, hope everyone is sympathetic, and look forward to the comments of everyone to make the article more complete. Thank you for taking the time to read my article !!!

References

https://guides.rubyonrails.org/active_record_callbacks.html

https://github.com/rails/rails/blob/master/activesupport/lib/active_support/callbacks.rb#L94

Share the news now

Source : Viblo