How to save the history of the user action
This post hasn't been updated for 6 years
Sau đây mình xin giới thiệu thử viện dùng để lưu các hành động của người dùng đó là gem "paper_trail"
Cài đặt
- Thêm gem "paper_trail" vào Gemfile
- bundle exec rails generate paper_trail:install
- bundle exec rake db:migrate
- Xong khi chạy xong thì nó sẽ sinh ra bảng "versions".
class CreateVersions < ActiveRecord::Migration[5.1]
def change
create_table :versions, {options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci"} do |t|
t.string :item_type, null: false
t.integer :item_id, null: false
t.string :event, null: false
t.string :whodunnit
t.text :object
t.datetime :created_at
end
add_index :versions, %i(item_type item_id)
end
end
Trong đó:
- item_type: Lưu tên bảng dữ liệu thay đổi.
- item_id: Lưu id của bản ghi có sự thay đổi.
- event: Sự kiện xảy ra với bản ghi thay đổi.
- whodunnit: Lưu thông tin về người thay đổi bản ghi.
- datetime: Lưu thời gian bản ghi versions được tạo.
- add_index: Đánh index cho bản ghi versions
Ngoài ra có thể thêm một số trường cần dùng
Cách sử dụng
- Thêm method has_paper_trail vào trong model
class Admin < ApplicationRecord
...
has_paper_trail
end
- Bây giờ muốn thực hiên các hành động rồi sau đó làm thế nào để biết người nào đang thực hiện hành động đó thì dựa vào trường "whodunnit"
class Admin::BaseController < ApplicationController
before_action :set_paper_trail_whodunnit
# Trong method set_paper_trail_whodunnit sẽ gọi method user_for_paper_trail
def user_for_paper_trail
current_admin.id
end
# Nếu muốn đưa thêm dữ liệu vào bảng versions, vd: thêm trường whodunnit_type
def info_for_paper_trail
{whodunnit_type: Admin.name}
end
end
- Ngoài ra, khi gọi Api hay trực tiếp vào model thì làm thế nào chúng ta có thể thêm người thực hiện:
def set_whodunnit current_user
::PaperTrail.whodunnit = current_user.id
end
- Nếu muốn dùng khi nào thì lưu hành động hay không thì sử dụng các options của nó
vd: :ignore, :skip, :only, :meta and condition
has_paper_trail only: :attributes
has_paper_trail skip: :attributes
has_paper_trail ignore: :attributes
has_paper_trail if: proc {|record| record.name_changed?}, unless: proc{|record| record.password_changed?}
- Có thể cho phép lưu hay không lưu, bằng lệnh:
PaperTrail.enabled = false # Không lưu
PaperTrail.enabled = true # cho phép lưu
- Muốn kiểm tra các version đã lưu, trước đó, người đã thực hiện hành động, ...
Admin.first.paper_trail.live?
Admin.first.paper_trail.originator
Admin.first.paper_trail.version_at(timestamp)
Admin.first.paper_trail.previous_version
Admin.first.paper_trail.next_version
Admin.first.paper_trail.touch_with_version
Tài liệu tham khảo
All Rights Reserved