0

Làm chủ Callbacks trong Active Record (Rails)

Trong Ruby on Rails, Callbacks là những phương thức được tự động kích hoạt vào các thời điểm nhất định trong vòng đời (lifecycle) của một đối tượng Active Record (chẳng hạn như khi đối tượng được tạo, cập nhật, xóa, v.v.).

Việc sử dụng callback giúp chúng ta thực thi các logic nghiệp vụ (business logic) một cách tự động mà không cần gọi thủ công mỗi khi thao tác với database.


1. Cách khai báo Callbacks

Chúng ta có 3 cách chính để khai báo một callback trong Model:

Cách 1: Khai báo bằng Symbol (Khuyên dùng)

Đây là cách phổ biến nhất, giúp mã nguồn sạch sẽ và dễ đọc.

class User < ApplicationRecord
  before_save :normalize_email

  private

  def normalize_email
    self.email = email.downcase
  end
end

Cách 2: Khai báo bằng Block

Sử dụng khi logic xử lý ngắn gọn, đơn giản.

class User < ApplicationRecord
  before_create do
    self.status = "active"
  end
end

Cách 3: Khai báo bằng một Class riêng biệt

Khi logic callback quá phức tạp và muốn tái sử dụng ở nhiều Model khác nhau.

class User < ApplicationRecord
  before_destroy IdentityCleanupCallback
end

Lưu ý: Bạn có nhắc đến "action controller" trong bản thảo. Cần phân biệt rõ: Trong Controller, chúng ta gọi là Filters (như before_action), còn trong Model mới gọi là Callbacks.


2. Các sự kiện chính trong vòng đời đối tượng

Dưới đây là thứ tự thực thi của các callback phổ biến:

Tạo mới đối tượng (Creating)

  1. before_validation
  2. after_validation
  3. before_save
  4. around_save
  5. before_create
  6. around_create
  7. Lưu vào Database
  8. after_create
  9. after_save
  10. after_commit / after_rollback

Cập nhật đối tượng (Updating)

  1. before_validation
  2. after_validation
  3. before_save
  4. around_save
  5. before_update
  6. around_update
  7. Lưu vào Database
  8. after_update
  9. after_save
  10. after_commit / after_rollback

Xóa đối tượng (Destroying)

  1. before_destroy
  2. around_destroy
  3. Xóa khỏi Database
  4. after_destroy
  5. after_commit / after_rollback

3. Các phương thức kích hoạt và bỏ qua Callbacks

Không phải phương thức nào tác động vào database cũng kích hoạt callback. Bạn cần nắm rõ để tránh các lỗi logic tiềm ẩn.

Các phương thức CÓ kích hoạt Callbacks:

  • create, create!
  • save, save!, save(validate: false)
  • update, update!
  • destroy, destroy!, destroy_all
  • valid? (chỉ kích hoạt validation callbacks)
  • touch

Các phương thức BỎ QUA Callbacks (Cẩn thận khi dùng):

Các phương thức này chạy truy vấn SQL trực tiếp nên hiệu năng nhanh hơn nhưng không chạy callback:

  • update_column, update_columns, update_all
  • delete, delete_all
  • increment!, decrement!
  • toggle!

4. Callback có điều kiện (Conditional Callbacks)

Bạn có thể kiểm soát khi nào một callback được phép chạy bằng cách sử dụng :if hoặc :unless.

class Order < ApplicationRecord
  before_save :calculate_discount, if: :vouchers_applied?
  after_commit :send_email, unless: :skip_notification?

  def vouchers_applied?
    self.voucher_code.present?
  end
end


5. Một số lưu ý quan trọng (Best Practices)

  1. Hạn chế logic phức tạp: Đừng để callback thực hiện quá nhiều việc (như gọi API bên thứ ba). Hãy dùng Background Job trong after_commit.
  2. Thứ tự ưu tiên: Callback được thực hiện theo thứ tự mà chúng được khai báo trong model.
  3. Tránh thay đổi thuộc tính trong after_save: Nếu bạn thay đổi thuộc tính và gọi .save trong after_save, bạn sẽ tạo ra một vòng lặp vô tận. Hãy dùng before_save để thay đổi dữ liệu của chính đối tượng đó.
  4. Transaction: Các callback từ before_validation đến after_save đều nằm trong một Database Transaction. Nếu có bất kỳ lỗi nào xảy ra, toàn bộ quá trình sẽ bị rollback.

Tổng kết Callbacks là một công cụ mạnh mẽ giúp code Rails của bạn ngắn gọn và tự động hóa tốt hơn. Tuy nhiên, hãy sử dụng chúng một cách thông minh để tránh biến Model thành một "tảng băng chìm" khó debug.

Happy Coding! 🚀


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí