How to save the history of the user action

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

https://github.com/airblade/paper_trail


All Rights Reserved