Ruby on Rails


Ruby on Rails Tutorial: Understanding Callbacks and Observers

As a Ruby on Rails developer, you’re familiar with the framework’s convention-over-configuration approach, allowing you to focus on building robust web applications. Callbacks and observers are essential features in Rails that enable you to execute code at specific points during the object lifecycle, providing flexibility and maintainability. In this tutorial, we’ll dive into the world of callbacks and observers, exploring how they work, their differences, and best practices for using them effectively.

Ruby on Rails Tutorial: Understanding Callbacks and Observers

1. Understanding Callbacks

1.1. What are Callbacks?

Callbacks in Ruby on Rails are methods that get triggered at certain points during the lifecycle of an object. These points are tied to specific actions, such as creating, updating, or deleting records. The callback mechanism allows you to extend the behavior of your models without modifying the core logic, keeping your code organized and maintainable.

1.2. Types of Callbacks

1.2.1. Before Callbacks:

Before callbacks are executed right before the specified event occurs. They are commonly used for tasks like setting default values or performing validations.

class Article < ApplicationRecord
  before_save :set_published_at


  def set_published_at
    self.published_at ||= if self.published

1.2.2. After Callbacks:

After callbacks run after the specified event has taken place. These are useful for tasks like sending notifications or updating associated records.

class Order < ApplicationRecord
  after_create :send_order_confirmation


  def send_order_confirmation

1.2.3. Around Callbacks:

Around callbacks wrap the entire action, allowing you to execute custom logic before and after the specified event. These are less common but can be useful for complex operations.

class Transaction < ApplicationRecord
  around_save :perform_audit_log


  def perform_audit_log
    TransactionAudit.log(self) do

1.3. The Callback Chain

Rails organizes callbacks into a chain, ensuring they are executed in a specific order. The order for ActiveRecord models is as follows:

  • before_validation
  • after_validation
  • before_save
  • around_save
  • before_create / before_update
  • around_create / around_update
  • after_create / after_update
  • after_save
  • after_commit / after_rollback

1.4. Controlling Callback Execution

In some scenarios, you may want to conditionally trigger a callback or prevent it from executing. Rails provides the :if and :unless options for this purpose.

class Product < ApplicationRecord
  before_save :calculate_discount, if: :discount_applicable?


  def discount_applicable?
    category == 'Electronics'

  def calculate_discount
    # Calculate and apply discount

In the example above, the before_save callback calculate_discount will only execute if the discount_applicable? method returns true.

1.5. Skipping Callbacks

You can also skip callbacks explicitly when invoking certain methods. This can be useful, for instance, when performing bulk updates and avoiding unnecessary callbacks.

class User < ApplicationRecord
  has_many :posts, dependent: :destroy_without_callbacks

  # ...

In this example, we’re using the :destroy_without_callbacks option to skip the callbacks when destroying associated posts.

1.6. Handling Callback Exceptions

If an exception is raised within a callback, Rails will stop the chain and immediately roll back the operation. This ensures data consistency and prevents partial updates.

2. Exploring Observers

2.1. What are Observers?

Observers are another way to decouple additional functionality from your models. While callbacks are directly tied to the lifecycle events of an object, observers are standalone classes observing changes in the models they are associated with. This separation promotes better code organization and easier testing.

2.2. Creating an Observer

To create an observer, use the rails generate observer command:

rails generate observer UserObserver

This will create a user_observer.rb file in the app/observers directory.

2.3. Registering Observers

To make an observer work, you must register it in the application configuration. Open config/application.rb and add the following line:

config.active_record.observers = :user_observer

2.4. Observing Model Events

In the observer class, you can define methods that will be triggered on specific model events, such as before_save, after_create, or custom events.

class UserObserver < ActiveRecord::Observer
  def after_create(user)

  def after_update(user)
    # Perform other actions after user update

3. Observers vs. Callbacks

While both observers and callbacks can achieve similar outcomes, observers provide a cleaner separation of concerns. They encapsulate the additional behavior away from the model, making it easier to maintain and test.

4. Best Practices for Using Callbacks and Observers

4.1. Keep Callbacks Simple:

Avoid adding complex logic within callbacks, as it can make your code harder to understand and maintain. Consider using callbacks primarily for simple tasks like setting default values or triggering notifications.

4.2. Use Observers for Complex Functionality:

For more intricate operations or actions that are not directly tied to the model’s lifecycle, observers offer a more organized and testable approach.

4.3. Avoid Skipping Callbacks Unnecessarily:

While skipping callbacks can improve performance in certain scenarios, use this feature judiciously. Skipping callbacks may lead to unexpected behavior if not used carefully.

4.4. Test Callbacks and Observers:

Ensure that your callbacks and observers work correctly by writing appropriate tests. This will help you catch bugs early and maintain the integrity of your application.


In this tutorial, we’ve explored the world of callbacks and observers in Ruby on Rails. Understanding these powerful features can significantly enhance your application’s functionality while keeping your codebase clean and maintainable. By mastering the art of utilizing callbacks and observers effectively, you’ll be well-equipped to build robust and scalable web applications with Ruby on Rails. Happy coding!

Previously at
Flag Argentina
time icon
Senior Software Engineer with a focus on remote work. Proficient in Ruby on Rails. Expertise spans y6ears in Ruby on Rails development, contributing to B2C financial solutions and data engineering.