Tìm hiểu thêm về gem Paranoia
Bài đăng này đã không được cập nhật trong 7 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