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)
before_validationafter_validationbefore_savearound_savebefore_createaround_create- Lưu vào Database
after_createafter_saveafter_commit/after_rollback
Cập nhật đối tượng (Updating)
before_validationafter_validationbefore_savearound_savebefore_updatearound_update- Lưu vào Database
after_updateafter_saveafter_commit/after_rollback
Xóa đối tượng (Destroying)
before_destroyaround_destroy- Xóa khỏi Database
after_destroyafter_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_allvalid?(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_alldelete,delete_allincrement!,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)
- 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. - Thứ tự ưu tiên: Callback được thực hiện theo thứ tự mà chúng được khai báo trong model.
- Tránh thay đổi thuộc tính trong
after_save: Nếu bạn thay đổi thuộc tính và gọi.savetrongafter_save, bạn sẽ tạo ra một vòng lặp vô tận. Hãy dùngbefore_saveđể thay đổi dữ liệu của chính đối tượng đó. - Transaction: Các callback từ
before_validationđếnafter_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