Skip callback trong Rails model
TIL
641
White

Hieu Nguyen viết ngày 16/06/2017

Hãy tưởng tượng: bạn là một tín đồ của Rails và DHH. Bạn thần tượng majestic monolith và luôn dùng callback để thực hiện các tác vụ liên quan đến persistence thay vì service object. Bạn gửi notification cho user ngay khi một transaction được tạo ra giống y như được chỉ dạy:

class Transaction < ActiveRecord::Base
  belongs_to :user
  after_create :create_notification

  private 

  def create_notification
    Notification.create! transaction: self, recipients: user
  end
end

Một ngày nọ, bạn nhận được một yêu cầu từ khách hàng cần tạo transaction dạng cash, và bạn sử dụng STI ngay lập tức:

class CashTransaction < Transaction
end

Nhưng sếp bạn lại bảo là không nên gửi notification cho khách hàng với transaction này, vậy giờ bạn phải làm sao?

Sử dụng ActiveRecord::Base.suppress

DHH cũng gặp vấn đề như bạn, nên anh ấy đã nghĩ ra một cách cực kỳ thông minh sáng lạng, ấy là tạo ra phương thức .suppress, và bạn ngay lập tức copy về:

module Chargable
  def charge(user)
    Notification.suppress do
      # Copy logic that creates new transactions that we do not want triggering Notifications
    end
  end
end

Tuy nhiên, chỉ Rails 5.1 mới có thể làm vậy, và rất xui là project của bạn đang ở Rails 4. Và bạn không thể thuyết phục sếp cho upgrade Rails chỉ vì lý do vô cùng cỏn con như vậy.

Sử dụng ActiveRecord::Base.skip_callback

Rất may là trước khi DHH tài ba nghĩ ra suppress, bà con đã thấy trước tình trạng này và tạo ra skip_callback, vậy bạn có thể dễ dàng bỏ qua cái callback này chỉ với:

class CashTransaction < Transaction
  skip_callback :create, :after, :create_notification
end

Ngoài ra bạn còn tìm ra rất nhiều cách khác:

Hoặc dùng tham số chỉ định

class Transaction < ActiveRecord::Base
  after_create :create_notification, if: -> { !is_a?(CashTransaction) }
end

Hoặc f*** magic, sử dụng kế thừa như bình thường:

class Transaction < ActiveRecord::Base
  private

  def create_notification
    # do not send anything to user
  end
end

Và cách tốt nhất:

May mắn làm sao, bạn không phải là tín đồ của DHH, và hẳn là bạn đã tạo ra một PORO object để lo chuyện persist transaction và không bao giờ phải lo về chuyện skip callback vớ vẩn này.

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

Hieu Nguyen

22 bài viết.
10 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
12 3
Khi làm việc với Ruby và Rails, có lẽ không ít lần các bạn đã gặp các tác vụ download file về server của mình. Ruby hỗ trợ nhiều công cụ download k...
Hieu Nguyen viết hơn 3 năm trước
12 3
White
12 4
Đối với những người đã từng xây dựng API server, chắc hẳn ai cũng đã từng hơn một lần đau đầu với việc lựa chọn thư viện JSON. Bài viết sau đây hi ...
Hieu Nguyen viết hơn 3 năm trước
12 4
White
11 0
Như đã nói trong (Link), mình sẽ chia sẻ tổng hợp kết quả của các benchmark mình đã dùng để so sánh tốc độ render JSON của các thư viện phổ biến hi...
Hieu Nguyen viết hơn 3 năm trước
11 0
Bài viết liên quan
White
0 2
fCC: Technical Documentation Page note So I have finished the HTML part of this exercise and I want to come here to lament about the lengthy HTML ...
HungHayHo viết 6 tháng trước
0 2
White
20 1
Toán tử XOR có tính chất: + A XOR A = 0 + 0 XOR A = A Với tính chất này, có thể cài đặt bài toán sau với độ phức tạp O(N) về runtime, và với O(1)...
kiennt viết 2 năm trước
20 1
White
9 0
Có một tuyên ngôn cho chủ nghĩa tối giản trong ngành phần mềm. Link: http://minifesto.org/ Fight for Pareto's law, look for the 20% of effort th...
Cẩm Huỳnh viết 3 tháng trước
9 0
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
22 bài viết.
10 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!