Skip to content

Commit

Permalink
Merge pull request #849 from DFE-Digital/1173-data-versioning
Browse files Browse the repository at this point in the history
Add data versioning.
  • Loading branch information
slawosz authored Aug 1, 2023
2 parents 8f076d8 + b8be12c commit 653ccc7
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 0 deletions.
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ gem "omniauth", "~> 2.1"
gem "omniauth-oauth2", "~> 1.8"
gem "omniauth-rails_csrf_protection"
gem "pagy"
gem "paper_trail", "~> 14.0"
gem "pg", ">= 0.18", "< 2.0"
gem "pg_search"
gem "puma", "~> 6.3"
Expand Down
4 changes: 4 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,9 @@ GEM
omniauth (~> 2.0)
orm_adapter (0.5.0)
pagy (6.0.4)
paper_trail (14.0.0)
activerecord (>= 6.0)
request_store (~> 1.4)
parallel (1.23.0)
parallel_tests (4.2.1)
parallel
Expand Down Expand Up @@ -554,6 +557,7 @@ DEPENDENCIES
omniauth-oauth2 (~> 1.8)
omniauth-rails_csrf_protection
pagy
paper_trail (~> 14.0)
parallel_tests
pg (>= 0.18, < 2.0)
pg_search
Expand Down
2 changes: 2 additions & 0 deletions app/models/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ class Application < ApplicationRecord
# within the rails model
self.ignored_columns = %w[DEPRECATED_cohort]

has_paper_trail only: %i[lead_provider_approval_status participant_outcome_state]

belongs_to :user
belongs_to :course
belongs_to :lead_provider
Expand Down
1 change: 1 addition & 0 deletions config/initializers/paper_trail.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
PaperTrail.serializer = PaperTrail::Serializers::JSON
37 changes: 37 additions & 0 deletions db/migrate/20230720114510_create_versions.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# This migration creates the `versions` table, the only schema PT requires.
# All other migrations PT provides are optional.
class CreateVersions < ActiveRecord::Migration[6.1]
# 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.bigint :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
10 changes: 10 additions & 0 deletions db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -272,4 +272,14 @@
t.index ["uid"], name: "index_users_on_uid", unique: true
end

create_table "versions", force: :cascade do |t|
t.string "item_type", null: false
t.bigint "item_id", null: false
t.string "event", null: false
t.string "whodunnit"
t.text "object"
t.datetime "created_at"
t.index ["item_type", "item_id"], name: "index_versions_on_item_type_and_item_id"
end

end
19 changes: 19 additions & 0 deletions spec/models/application_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,23 @@
end
end
end

describe "versioning" do
context "when changing versioned fields" do
let(:application) { create(:application, lead_provider_approval_status: "pending", participant_outcome_state: nil) }

before do
application.update!(lead_provider_approval_status: "accepted", participant_outcome_state: "passed")
end

it "has history of changes" do
previous_application = application.versions.last.reify
expect(application.lead_provider_approval_status).to eq("accepted")
expect(application.participant_outcome_state).to eq("passed")

expect(previous_application.lead_provider_approval_status).to eq("pending")
expect(previous_application.participant_outcome_state).to eq(nil)
end
end
end
end

0 comments on commit 653ccc7

Please sign in to comment.