Tìm hiểu thêm về gem Paranoia
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 ...
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.