diff --git a/Gemfile b/Gemfile index cd1b2bf..3ca00f6 100644 --- a/Gemfile +++ b/Gemfile @@ -7,6 +7,7 @@ gem "bootsnap", require: false gem "clearance" gem "dotenv-rails" gem "importmap-rails" +gem "paper_trail" gem "pg", "~> 1.1" gem "propshaft" gem "puma", "~> 5.0" diff --git a/Gemfile.lock b/Gemfile.lock index daf3448..5d8a8ab 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -136,6 +136,9 @@ GEM nio4r (2.5.8) nokogiri (1.13.6-x86_64-linux) racc (~> 1.4) + paper_trail (12.3.0) + activerecord (>= 5.2) + request_store (~> 1.1) pg (1.4.0) propshaft (0.6.4) actionpack (>= 7.0.0) @@ -183,6 +186,8 @@ GEM i18n reline (0.3.1) io-console (~> 0.5) + request_store (1.5.1) + rack (>= 1.4) strscan (3.0.3) thor (1.2.1) timecop (0.9.5) @@ -208,6 +213,7 @@ DEPENDENCIES debug dotenv-rails importmap-rails + paper_trail pg (~> 1.1) propshaft puma (~> 5.0) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 789d46b..38c6085 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,3 +1,4 @@ class ApplicationController < ActionController::Base include Clearance::Controller + before_action :set_paper_trail_whodunnit end diff --git a/app/models/contribution.rb b/app/models/contribution.rb index 8596bab..4d624fe 100644 --- a/app/models/contribution.rb +++ b/app/models/contribution.rb @@ -1,3 +1,4 @@ class Contribution < ApplicationRecord belongs_to :member + has_paper_trail end diff --git a/app/models/member.rb b/app/models/member.rb index 7f7024a..25156be 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -2,6 +2,7 @@ class Member < ApplicationRecord default_scope { where(excluded: false) } has_many :contributions has_many :notifications + has_paper_trail def cancelled_on expires_on + 90.days diff --git a/config/initializers/paper_trail.rb b/config/initializers/paper_trail.rb new file mode 100644 index 0000000..30038ee --- /dev/null +++ b/config/initializers/paper_trail.rb @@ -0,0 +1 @@ +PaperTrail.serializer = PaperTrail::Serializers::JSON diff --git a/db/migrate/20220626100609_create_versions.rb b/db/migrate/20220626100609_create_versions.rb new file mode 100644 index 0000000..edea34c --- /dev/null +++ b/db/migrate/20220626100609_create_versions.rb @@ -0,0 +1,38 @@ +# This migration creates the `versions` table, the only schema PT requires. +# All other migrations PT provides are optional. +class CreateVersions < ActiveRecord::Migration[7.0] + + # The largest text column available in all supported RDBMS is + # 1024^3 - 1 bytes, roughly one gibibyte. We specify a size + # so that MySQL will use `longtext` instead of `text`. Otherwise, + # when serializing very large objects, `text` might not be big enough. + TEXT_BYTES = 1_073_741_823 + + def change + create_table :versions do |t| + t.string :item_type, null: false + t.string :item_id, null: false + t.string :event, null: false + t.string :whodunnit + #t.text :object, limit: TEXT_BYTES + + # Known issue in MySQL: fractional second precision + # ------------------------------------------------- + # + # MySQL timestamp columns do not support fractional seconds unless + # defined with "fractional seconds precision". MySQL users should manually + # add fractional seconds precision to this migration, specifically, to + # the `created_at` column. + # (https://dev.mysql.com/doc/refman/5.6/en/fractional-seconds.html) + # + # MySQL users should also upgrade to at least rails 4.2, which is the first + # version of ActiveRecord with support for fractional seconds in MySQL. + # (https://github.com/rails/rails/pull/14359) + # + # MySQL users should use the following line for `created_at` + # t.datetime :created_at, limit: 6 + t.datetime :created_at + end + add_index :versions, %i(item_type item_id) + end +end diff --git a/db/migrate/20220626100610_add_object_changes_to_versions.rb b/db/migrate/20220626100610_add_object_changes_to_versions.rb new file mode 100644 index 0000000..fbb9326 --- /dev/null +++ b/db/migrate/20220626100610_add_object_changes_to_versions.rb @@ -0,0 +1,8 @@ +# This migration adds the optional `object_changes` column, in which PaperTrail +# will store the `changes` diff for each update event. See the readme for +# details. +class AddObjectChangesToVersions < ActiveRecord::Migration[7.0] + def change + add_column :versions, :object_changes, :json + end +end diff --git a/db/schema.rb b/db/schema.rb index 652f0eb..6cc02b2 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2022_06_25_224650) do +ActiveRecord::Schema[7.0].define(version: 2022_06_26_100610) do # These are extensions that must be enabled in order to support this database enable_extension "pgcrypto" enable_extension "plpgsql" @@ -71,6 +71,16 @@ ActiveRecord::Schema[7.0].define(version: 2022_06_25_224650) do t.index ["remember_token"], name: "index_users_on_remember_token", unique: true end + create_table "versions", force: :cascade do |t| + t.string "item_type", null: false + t.string "item_id", null: false + t.string "event", null: false + t.string "whodunnit" + t.datetime "created_at" + t.text "object_changes" + t.index ["item_type", "item_id"], name: "index_versions_on_item_type_and_item_id" + end + add_foreign_key "contributions", "members" add_foreign_key "notifications", "members" end