Tìm hiểu thêm về gem Paranoia
Bài đăng này đã không được cập nhật trong 8 năm
Trong công việc, đôi khi bạn phải sử dụng gem Paranoia việc hiểu thêm về gem này gíup bạn chủ động hơn trong công việc.
Link: https://github.com/rubysherpas/paranoia
Gem Paranoia đơn gỉan là thêm cột deleted_at vào bảng mà chúng ta muốn đánh dấu đã bị xóa đi.
Đầu tiên, paranoia thêm một class method cho class ActiveRecord::Base là self.acts_as_paranoid (https://github.com/rubysherpas/paranoia/blob/core/lib/paranoia.rb#L209):
class ActiveRecord::Base
def self.acts_as_paranoid(options={})
...
def self.paranoia_scope
where(paranoia_column => paranoia_sentinel_value)
end
...
unless options[:without_default_scope]
default_scope { paranoia_scope }
end
...
end
end
Do vậy trong model mỗi khi ta khai báo acts_as_paranoid thì class method này sẽ chạy. Ta cũng có thể gọi ngoài console như một method bình thường vì các model của ta viết đều kế thừa ActiveRecord::Base.
Việc thêm default_scope để loại bỏ những record theo setting của Paranoia. Giả sử đã add acts_as_paranoid vào model Order, khi gọi 1 câu scope bất kỳ từ bảng Order ta đều thấy:
2.3.1 :001 > Order.all
Order Load (1.9ms) SELECT `t_order`.* FROM `t_order` WHERE `t_order`.`deleted_at` IS NULL
Muốn bỏ paranoia scope này đơn gỉan ta chỉ cần gọi unscoped.
2.3.1 :002 > Order.all.unscoped
Order Load (7.3ms) SELECT `t_order`.* FROM `t_order`
Đối với những model chưa add acts_as_paranoid ta chỉ việc gọi method này, thử đối với model Okan, trước khi goi method này:
2.3.1 :001 > Okan.first
Okan Load (0.2ms) SELECT `t_okan`.* FROM `t_okan` ORDER BY `t_okan`.`okan_id` ASC LIMIT 1
Sau đó gọi method acts_as_paranoid ta thấy câu query đã thay đổi:
2.3.1 :002 > Okan.acts_as_paranoid
=> [Okan(okan_id: string, member_id: string, ...
2.3.1 :003 > Okan.first
Okan Load (1.1ms) SELECT `t_okan`.* FROM `t_okan` WHERE `t_okan`.`deleted_at` IS NULL ORDER BY `t_okan`.`okan_id` ASC LIMIT 1
Ta chú ý thấy trong câu query trên có đoạn WHERE t_okan.deleted_at IS NULL, đây là default_scope mà paranoia thêm vào, tên column để gem này check được set tại (https://github.com/rubysherpas/paranoia/blob/core/lib/paranoia.rb#L217) self.paranoia_column = (options[:column] || :deleted_at).to_s, muốn thay đổi ta chỉ cần thêm vào khi gọi method acts_as_paranoid
2.3.1 :001 > Okan.acts_as_paranoid column: :my_column
2.3.1 :002 > Okan.first
Okan Load (7.2ms) SELECT `t_okan`.* FROM `t_okan` WHERE `t_okan`.`my_column` IS NULL ORDER BY `t_okan`.`okan_id` ASC LIMIT 1
Muốn xem gía trị của column ta chỉ cần gọi Okan.paranoia_column
2.3.1 :003 > Okan.paranoia_column
=> "my_column"
Giá trị để paranoia check xem record đã bị xóa hay chưa được set tại: (https://github.com/rubysherpas/paranoia/blob/core/lib/paranoia.rb#L218) self.paranoia_sentinel_value = options.fetch(:sentinel_value) { Paranoia.default_sentinel_value }, muốn thay đổi ta cũng làm như trên.
2.3.1 :006 > Okan.acts_as_paranoid sentinel_value: 'my_value'
=> [Okan(okan_id: string, member_id: string, ...
2.3.1 :007 > Okan.first
Okan Load (1.9ms) SELECT `t_okan`.* FROM `t_okan` WHERE `t_okan`.`deleted_at` = 'my_value' ORDER BY `t_okan`.`okan_id` ASC LIMIT 1
Muốn xem gía trị của sentinel_value ta chỉ cần gọi Okan.paranoia_sentinel_value
2.3.1 :006 > Okan.paranoia_sentinel_value
=> 'my_value'
Khi destroy record, paranoia overide lại hàm destroy (https://github.com/rubysherpas/paranoia/blob/core/lib/paranoia.rb#L104):
def restore!(opts = {})
self.class.transaction do
...
write_attribute paranoia_column, paranoia_sentinel_value
...
end
end
Đoạn code write_attribute paranoia_column, paranoia_sentinel_value chính là update cột được định nghĩa tại paranoia_column gía trị được định nghĩa tại paranoia_sentinel_value.
Cảm ơn và hi vọng bài viết có ích cho công việc của bạn.
All rights reserved