Skip to content

Commit 9569816

Browse files
jazairiJPrevost
authored andcommitted
Migrate versions.object and versions.object_changes to JSON
Why these changes are being introduced: The versions table, used by paper_trail, has two columns that use YAML. PaperTrail prefers that these tables use JSON or JSONB. In order to update paper_trail to the latest version, we need either to update our config to use YAML.safe_load or migrate the data to JSON. Relevant ticket(s): * https://mitlibraries.atlassian.net/browse/ETD-626 * https://mitlibraries.atlassian.net/browse/ETD-615 How this addresses that need: This converts the columns to JSON as described here: https://github.com/paper-trail-gem/paper_trail/blob/v14.0.0/README.md#6b-custom-serializer Our migration uses `PaperTrail::Serializers::YAML.load`. This is effectively the same as `YAML.safe_load`. `YAML.load`, awhich is uggested in the readme, will no longer work due to a long-running bug in Psych: collectiveidea/audited#631 We are using JSON instead of JSONB for two reasons: 1. SQLite does not support JSONB, so our local environments will differ from Heroku; and 2. We are not actively leveraging JSONB's performance advantages in the codebase, so there is likely no functional difference. Long-term, it's worth considering whether we should use postgres locally, as this would support better dev/prod parity and allow us to use psql features like JSONB with more confidence. We discussed this briefly in a team meeting on 3/7/23 and decided that such a change could bring value, but is not necessary at this time. Side effects of this change: * One test has been updated to accommodate a value that change from a date to a string. * We are adding some `yaml_column_permitted_classes` to our ActiveRecord config. This is required to run the db migration because of the aforementioned bug in Psych. I've added a comment to remove it once this commit is deployed. * The migration is relatively inefficient. However, we tested it against a clone of our prod db and found that it completed in 83.12s, which we find acceptable. * Running db migrations sometimes incorrectly parses the `null: false` param into its own column. This bug occurs despite PaperTrail's claiming to have fixed it, and it's inconsistent (it occurs when Adam runs the migrations, but not when Jeremy does). There's not much we can do about this except to keep an eye on it in the future. co-authored-by: Jeremy Prevost <jprevost@mit.edu>
1 parent d0a1017 commit 9569816

File tree

7 files changed

+44
-10
lines changed

7 files changed

+44
-10
lines changed

Gemfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ gem 'net-pop', require: false
2424
gem 'net-smtp', require: false
2525
gem 'omniauth-rails_csrf_protection'
2626
gem 'omniauth-saml'
27-
gem 'paper_trail', '~> 12.3'
27+
gem 'paper_trail'
2828
gem 'puma'
2929
gem 'rails', '~> 7.0'
3030
gem 'rubyzip'

Gemfile.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -257,9 +257,9 @@ GEM
257257
omniauth (~> 2.0)
258258
ruby-saml (~> 1.12)
259259
orm_adapter (0.5.0)
260-
paper_trail (12.3.0)
261-
activerecord (>= 5.2)
262-
request_store (~> 1.1)
260+
paper_trail (14.0.0)
261+
activerecord (>= 6.0)
262+
request_store (~> 1.4)
263263
parallel (1.22.1)
264264
parser (3.2.1.0)
265265
ast (~> 2.4.1)
@@ -436,7 +436,7 @@ DEPENDENCIES
436436
net-smtp
437437
omniauth-rails_csrf_protection
438438
omniauth-saml
439-
paper_trail (~> 12.3)
439+
paper_trail
440440
pg
441441
puma
442442
rails (~> 7.0)

config/application.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,15 @@ class Application < Rails::Application
1919
# config.time_zone = "Central Time (US & Canada)"
2020
# config.eager_load_paths << Rails.root.join("extras")
2121
config.active_job.queue_adapter = :delayed_job
22+
23+
# This is required only for the db migration to convert YAML to JSON. We should remove it once we've run that
24+
# migration in all environments.
25+
config.active_record.yaml_column_permitted_classes = [
26+
ActiveSupport::HashWithIndifferentAccess,
27+
ActiveSupport::TimeWithZone,
28+
ActiveSupport::TimeZone,
29+
Date,
30+
Time
31+
]
2232
end
2333
end

config/initializers/paper_trail.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
PaperTrail.config.enabled = true
2+
PaperTrail.serializer = PaperTrail::Serializers::JSON
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
class ConvertVersionColumnsToJson < ActiveRecord::Migration[7.0]
2+
def change
3+
add_column :versions, :new_object, :json
4+
add_column :versions, :new_object_changes, :json
5+
6+
PaperTrail::Version.find_each do |version|
7+
version.update_column(:new_object, PaperTrail::Serializers::YAML.load(version.object)) if version.object
8+
9+
if version.object_changes
10+
version.update_column(
11+
:new_object_changes,
12+
PaperTrail::Serializers::YAML.load(version.object_changes)
13+
)
14+
end
15+
end
16+
17+
remove_column :versions, :object
18+
remove_column :versions, :object_changes
19+
rename_column :versions, :new_object, :object
20+
rename_column :versions, :new_object_changes, :object_changes
21+
end
22+
end

db/schema.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#
1111
# It's strongly recommended that you check this file into your version control system.
1212

13-
ActiveRecord::Schema[7.0].define(version: 2022_12_09_161518) do
13+
ActiveRecord::Schema[7.0].define(version: 2023_03_07_141544) do
1414
create_table "active_storage_attachments", force: :cascade do |t|
1515
t.string "name", null: false
1616
t.string "record_type", null: false
@@ -260,12 +260,12 @@
260260

261261
create_table "versions", force: :cascade do |t|
262262
t.string "item_type", null: false
263-
t.bigint "item_id", null: false
263+
t.integer "item_id", null: false
264264
t.string "event", null: false
265265
t.string "whodunnit"
266-
t.text "object", limit: 1073741823
267-
t.text "object_changes", limit: 1073741823
268266
t.datetime "created_at", precision: nil
267+
t.json "object"
268+
t.json "object_changes"
269269
t.index ["item_type", "item_id"], name: "index_versions_on_item_type_and_item_id"
270270
end
271271

test/integration/admin/admin_hold_test.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ def teardown
137137
patch admin_hold_path(hold), params: { hold: { status: 'released' } }
138138
hold.reload
139139
assert_equal 'released', hold.status
140-
assert_equal Date.today.strftime('%Y-%m-%d'), hold.date_released.strftime('%Y-%m-%d')
140+
assert_equal Date.today.strftime('%Y-%m-%d'), Date.parse(hold.date_released).strftime('%Y-%m-%d')
141141
end
142142

143143
test 'hold release date is the most recent released status change' do

0 commit comments

Comments
 (0)