Callbacks trong Rails

Trong quá trình xây dựng ứng dụng Rails thì chúng ta làm việc với các đối tượng.

Active Record cung cấp cho chúng ta Callbacks có thể chạy trước sau vòng đời của một đối tượng khi có sự thay đổi trạng thái như tạo, cập nhật, xóa... Nó có thể gọi bất kì lúc nào với action nào tùy vào cách gọi và mục đích sử dụng của chúng ta.

Sử dụng Callbacks

Để sử dụng Callback thì ta phải sử dụng chúng, ví dụ ta có 1 model user.rb như thế này.

class User < ApplicationRecord
  before_save :downcase_email
 
  private
   def downcase_email
    email.downcase!
  end
end

Callbacks trên như là trước mỗi khi chúng ta lưu trường email vào table users thì phải downcase email.

Ta có thể gọi nó định nghĩa trong 1 block như là:

class User < ApplicationRecord
  before_save do
    self.email = email.downcase!
  end
end

Hoặc là có thể giới hạn cho nó vòng đời nhất định nào đó như là:

class User < ApplicationRecord
  before_validation :downcase_email, on: [:create, :update]
  #before_validation :downcase_email, on: :create
 
  private
    def downcase_email
      self.email = email.downcase!
    end
end

Callbacks

Sau đây là danh sách một số callbacks theo vòng đời theo chức năng được định nghĩa tương ứng.

Creating:

  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

Updating:

  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

Destroying:

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

Như ta thấy thì cả tạo và cập nhật đối tượng đều có những callback dạng như before_save thì tức nghĩa là nó bao gồm cả before_create và before_update.

after_touch

Callback after_touch sẽ hoạt động khi bất cứ hoạt động nào tác động.

class User < ApplicationRecord
  after_touch do |user|
    puts "DepZaiKhoQuaMoiNguoiOi"
  end
end
 
>>  = User.create(name: 'xnxx')
=> #<User id: 1, name: "Xnxx", created_at: "2019-10-18 21:17:49", updated_at: "2019-10-18 21:17:49">
 
>> user.touch
DepZaiKhoQuaMoiNguoiOi
=> true

Có thể dùng chung với belongs_to

class Employee < ApplicationRecord
  belongs_to :company, touch: true
  after_touch do
    puts 'DepZaiKhoQuaMoiNguoiOi'
  end
end
 
class Company < ApplicationRecord
  has_many :employees
  after_touch :log_when_employees_or_company_touched
 
  private
    def log_when_employees_or_company_touched
      puts 'Locdeptrai'
    end
end
 
>> @employee = Employee.last
=> #<Employee id: 1, company_id: 1, created_at: "2019-10-18 21:17:49", updated_at: "2019-10-18 21:17:49">
 
>> @employee.touch
DepZaiKhoQuaMoiNguoiOi
Locdeptrai
=> true

Callback trong relationship

Giả sử có 2 đối tượng là User và Article(1-n). Callbacks hoạt động thông qua relationship và thậm chí có thể được xác định bởi chúng. Giả sử một ví dụ trong đó User có nhiều Article. Article của người dùng nên bị xóa nếu User bị xóa. Ta thêm một callback after_destroy cho model User bằng mối quan hệ của nó với model Article:


class User < ApplicationRecord
  has_many :articles, dependent: :destroy
end
 
class Article < ApplicationRecord
  after_destroy :log_destroy_action
 
  def log_destroy_action
    puts 'Article đã được xóa'
  end
end
 
>> user = User.first
=> #<User id: 1>

>> user.articles.create!
=> #<Article id: 1, user_id: 1>

>> user.destroy
Article đã được xóa
=> #<User id: 1>

Kết

Trên đây mình chia sẻ về một số vấn đề cơ bản về Callbacks trong rails, còn nhiều thứ vân vân mây mây mà có lẽ mình chưa sử dụng bao giờ. Hy vọng bài viết tìm hiểu từ 1 số nguồn và mình đã biên tập lại theo cách hiểu của mình sẽ giúp ích cho một số bạn chưa biết. Cám ơn các bạn đã đọc bài viết của mình./.