diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 859c2c2e..808a109d 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -74,9 +74,8 @@ DB=postgres bundle exec appraisal ar-5.2 rake ## Adding new schema Edit `spec/dummy_app/db/migrate/20110208155312_set_up_test_tables.rb`. Migration -will be performed by `spec_helper.rb`, so you can just run rake as shown above. -Also, `spec/dummy_app/db/schema.rb` is deliberately `.gitignore`d, we don't use -it. +will be performed by `rake`, so you can just run it as shown above. Also, +`spec/dummy_app/db/schema.rb` is deliberately `.gitignore`d, we don't use it. ## Documentation diff --git a/CHANGELOG.md b/CHANGELOG.md index 71a3a4b0..6cd902d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ recommendations of [keepachangelog.com](http://keepachangelog.com/). ### Breaking Changes +- TODO: Remove all the deprecated methods like `MyModel.paper_trail.disable` - [#1108](https://github.com/paper-trail-gem/paper_trail/pull/1108) - In `versions.item_type`, we now store the subclass name instead of the base_class. diff --git a/README.md b/README.md index d1eae956..b83435a6 100644 --- a/README.md +++ b/README.md @@ -1101,7 +1101,7 @@ path to the class (e.g. `Foo::BarVersion` if your class is inside the module 1. For models which have a lot of versions, storing each model's versions in a separate table can improve the performance of certain database queries. -1. Store different version [metadata](#storing-metadata) for different models. +1. Store different version [metadata](#4c-storing-metadata) for different models. #### Configuration diff --git a/spec/dummy_app/app/models/no_object.rb b/spec/dummy_app/app/models/no_object.rb new file mode 100644 index 00000000..04444649 --- /dev/null +++ b/spec/dummy_app/app/models/no_object.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +# Demonstrates a table that omits the `object` column. +class NoObject < ActiveRecord::Base + has_paper_trail( + class_name: "NoObjectVersion", + meta: { metadatum: 42 } + ) + validates :letter, length: { is: 1 }, presence: true +end diff --git a/spec/dummy_app/app/versions/no_object_version.rb b/spec/dummy_app/app/versions/no_object_version.rb new file mode 100644 index 00000000..5b5beb90 --- /dev/null +++ b/spec/dummy_app/app/versions/no_object_version.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +# Demonstrates a table that omits the `object` column. +class NoObjectVersion < ::PaperTrail::Version + self.table_name = "no_object_versions" +end diff --git a/spec/dummy_app/db/migrate/20110208155312_set_up_test_tables.rb b/spec/dummy_app/db/migrate/20110208155312_set_up_test_tables.rb index 81e6b314..d102aa90 100644 --- a/spec/dummy_app/db/migrate/20110208155312_set_up_test_tables.rb +++ b/spec/dummy_app/db/migrate/20110208155312_set_up_test_tables.rb @@ -124,6 +124,24 @@ class SetUpTestTables < ( end add_index :post_versions, %i[item_type item_id] + # Uses custom versions table `no_object_versions`. + create_table :no_objects, force: true do |t| + t.string :letter, null: false, limit: 1 + t.timestamps null: false, limit: 6 + end + + # This table omits the `object` column. + create_table :no_object_versions, force: true do |t| + t.string :item_type, null: false + t.integer :item_id, null: false + t.string :event, null: false + t.string :whodunnit + t.datetime :created_at, limit: 6 + t.text :object_changes, limit: TEXT_BYTES + t.integer :metadatum + end + add_index :no_object_versions, %i[item_type item_id] + if ENV["DB"] == "postgres" create_table :json_versions, force: true do |t| t.string :item_type, null: false diff --git a/spec/models/no_object_spec.rb b/spec/models/no_object_spec.rb new file mode 100644 index 00000000..dfd442f3 --- /dev/null +++ b/spec/models/no_object_spec.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe NoObject, versioning: true do + it "still creates version records" do + n = described_class.create!(letter: "A") + a = n.versions.last.attributes + expect(a).not_to include "object" + expect(a["event"]).to eq "create" + expect(a["object_changes"]).to start_with("---") + expect(a["metadatum"]).to eq(42) + + n.update!(letter: "B") + a = n.versions.last.attributes + expect(a).not_to include "object" + expect(a["event"]).to eq "update" + expect(a["object_changes"]).to start_with("---") + expect(a["metadatum"]).to eq(42) + + n.destroy! + a = n.versions.last.attributes + expect(a).not_to include "object" + expect(a["event"]).to eq "destroy" + expect(a["object_changes"]).to be_nil + expect(a["metadatum"]).to eq(42) + end + + describe "reify" do + it "raises error" do + n = NoObject.create!(letter: "A") + v = n.versions.last + expect { v.reify }.to( + raise_error( + ::RuntimeError, + "reify can't be called without an object column" + ) + ) + end + end + + describe "where_object" do + it "raises error" do + n = NoObject.create!(letter: "A") + expect { + n.versions.where_object(foo: "bar") + }.to( + raise_error( + ::RuntimeError, + "where_object can't be called without an object column" + ) + ) + end + end +end diff --git a/spec/paper_trail/model_spec.rb b/spec/paper_trail/model_spec.rb index bcd49c63..627e190b 100644 --- a/spec/paper_trail/model_spec.rb +++ b/spec/paper_trail/model_spec.rb @@ -877,55 +877,4 @@ RSpec.describe(::PaperTrail, versioning: true) do expect(widget.versions.empty?).to(eq(true)) end end - - context "without the object column" do - # rubocop:disable RSpec/BeforeAfterAll - before :all do - ActiveRecord::Migration.remove_column :versions, :object - PaperTrail::Version.reset_column_information - end - after :all do - ActiveRecord::Migration.add_column :versions, :object, :text - PaperTrail::Version.reset_column_information - end - # rubocop:enable RSpec/BeforeAfterAll - - it "versions are created" do - song = Song.create length: 4 - version = song.versions.last.attributes - expect(version).not_to include "object" - expect(version["event"]).to eq "create" - expect(version["object_changes"]).to start_with("---") - - song.update length: 5 - version = song.versions.last.attributes - expect(version).not_to include "object" - expect(version["event"]).to eq "update" - expect(version["object_changes"]).to start_with("---") - - song.destroy - version = song.versions.last.attributes - expect(version).not_to include "object" - expect(version["event"]).to eq "destroy" - expect(version["object_changes"]).to eq nil - end - - it "reify doesn't work" do - song = Song.create length: 4 - song.update length: 5 - - expect do - song.versions.first.reify - end.to raise_error "reify can't be called without an object column" - end - - it "where_object doesn't work" do - song = Song.create length: 4 - song.update length: 5 - - expect do - song.versions.where_object length: 4 - end.to raise_error "where_object can't be called without an object column" - end - end end