Add PaperTrail.config.association_reify_error_behaviour (#1091)

* add PaperTrail.config.association_reify_error_behaviour

* fix test for Rails 4.2

* PaperTrail.config.association_reify_error_behaviour test in isolation, fixes

* association_error_behaviour fix specs

* fix rubocop errors

* assoication_reify_error_behaviour fixes
This commit is contained in:
Weston Ganger 2018-05-22 22:37:48 -07:00 committed by Jared Beck
parent 547dd1172f
commit d056c7e13b
12 changed files with 121 additions and 10 deletions

View File

@ -95,6 +95,12 @@ Naming/PredicateName:
Naming/UncommunicativeMethodParamName:
Enabled: false
RSpec/FilePath:
Exclude:
- spec/paper_trail/association_reify_error_behaviour/error.rb
- spec/paper_trail/association_reify_error_behaviour/warn.rb
- spec/paper_trail/association_reify_error_behaviour/ignore.rb
# In an ideal world, each example has a single expectation. In the real world,
# sometimes setup is a pain and you don't want to duplicate setup in multiple
# examples, or make the specs more confusing with many nested `context`s, and

View File

@ -11,7 +11,7 @@ recommendations of [keepachangelog.com](http://keepachangelog.com/).
### Added
- None
- [#1089] Sometimes the has_one association will find more than one possible candidate and will raise a `PaperTrail::Reifiers::HasOne::FoundMoreThanOne` when NOT using STI. You may want to just assume the first result (of multiple) is the correct one and continue. Versions pre v8.1.2 and below did this without error or warning. To do so add the following line to your initializer: `PaperTrail.config.association_reify_error_behaviour = :warn`. Valid options are: `[:error, :warn, :ignore]`
### Fixed

View File

@ -948,8 +948,9 @@ Associations are an **experimental feature** and have the following known
issues, in order of descending importance.
1. PaperTrail only reifies the first level of associations.
1. Does not fully support STI (For example, see `spec/models/person_spec.rb` and
`PaperTrail::Reifiers::HasOne::FoundMoreThanOne` error)
1. Sometimes the has_one association will find more than one possible candidate and will raise a `PaperTrail::Reifiers::HasOne::FoundMoreThanOne` error. For example, see `spec/models/person_spec.rb`
- If you are not using STI, you may want to just assume the first result (of multiple) is the correct one and continue. Versions pre v8.1.2 and below did this without error or warning. To do so add the following line to your initializer: `PaperTrail.config.association_reify_error_behaviour = :warn`. Valid options are: `[:error, :warn, :ignore]`
- When using STI, even if you enable `:warn` you will likely still end up recieving an `ActiveRecord::AssociationTypeMismatch` error.
1. [#542](https://github.com/paper-trail-gem/paper_trail/issues/542) -
Not compatible with [transactional tests][34], aka. transactional fixtures.
1. Requires database timestamp columns with fractional second precision.

View File

@ -45,7 +45,8 @@ module PaperTrail
def create_initializer
create_file(
"config/initializers/paper_trail.rb",
"PaperTrail.config.track_associations = #{!!options.with_associations?}\n"
"PaperTrail.config.track_associations = true\n",
"PaperTrail.config.association_reify_error_behaviour = :error"
)
end

View File

@ -26,7 +26,7 @@ module PaperTrail
STR
include Singleton
attr_accessor :serializer, :version_limit
attr_accessor :serializer, :version_limit, :association_reify_error_behaviour
def initialize
# Variables which affect all threads, whose access is synchronized.

View File

@ -74,7 +74,18 @@ module PaperTrail
when 1
versions.first
else
raise FoundMoreThanOne.new(base_class_name, versions.length)
case PaperTrail.config.association_reify_error_behaviour.to_s
when "warn"
version = versions.first
version.logger&.warn(
FoundMoreThanOne.new(base_class_name, versions.length).message
)
version
when "ignore"
versions.first
else # "error"
raise FoundMoreThanOne.new(base_class_name, versions.length)
end
end
end

View File

@ -12,6 +12,9 @@ class Person < ActiveRecord::Base
has_one :car, foreign_key: :owner_id
has_one :bicycle, foreign_key: :owner_id
has_one :thing
has_one :thing_2, class_name: "Thing"
if ActiveRecord.gem_version >= Gem::Version.new("5.0")
belongs_to :mentor, class_name: "Person", foreign_key: :mentor_id, optional: true
else

View File

@ -2,4 +2,10 @@
class Thing < ActiveRecord::Base
has_paper_trail save_changes: false
if ActiveRecord.gem_version >= Gem::Version.new("5.0")
belongs_to :person, optional: true
else
belongs_to :person
end
end

View File

@ -238,6 +238,7 @@ class SetUpTestTables < (
create_table :things, force: true do |t|
t.string :name
t.references :person
end
create_table :translations, force: true do |t|

View File

@ -2,13 +2,16 @@
require "spec_helper"
RSpec.describe Person, type: :model, versioning: true do
RSpec.describe PaperTrail, versioning: true do
it "baseline test setup" do
expect(Person.new).to be_versioned
end
describe "#cars and bicycles" do
it "can be reified" do
# See https://github.com/paper-trail-gem/paper_trail/issues/594
describe "#association reify error behaviour" do
it "association reify error behaviour = :error" do
::PaperTrail.config.association_reify_error_behaviour = :error
person = Person.create(name: "Frank")
car = Car.create(name: "BMW 325")
bicycle = Bicycle.create(name: "BMX 1.0")
@ -23,7 +26,6 @@ RSpec.describe Person, type: :model, versioning: true do
expect(person.reload.versions.length).to(eq(3))
# See https://github.com/paper-trail-gem/paper_trail/issues/594
expect {
person.reload.versions.second.reify(has_one: true)
}.to(

View File

@ -0,0 +1,40 @@
# frozen_string_literal: true
require "spec_helper"
RSpec.describe PaperTrail, versioning: true do
it "baseline test setup" do
expect(Person.new).to be_versioned
end
# See https://github.com/paper-trail-gem/paper_trail/issues/594
describe "#association reify error behaviour" do
it "association reify error behaviour = :ignore" do
::PaperTrail.config.association_reify_error_behaviour = :ignore
person = Person.create(name: "Frank")
thing = Thing.create(name: "BMW 325")
thing2 = Thing.create(name: "BMX 1.0")
person.thing = thing
person.thing_2 = thing2
person.update_attributes(name: "Steve")
thing.update_attributes(name: "BMW 330")
thing.update_attributes(name: "BMX 2.0")
person.update_attributes(name: "Peter")
expect(person.reload.versions.length).to(eq(3))
logger = person.versions.first.logger
allow(logger).to receive(:warn)
person.reload.versions.second.reify(has_one: true)
expect(logger).not_to(
have_received(:warn).with(/Unable to reify has_one association/)
)
end
end
end

View File

@ -0,0 +1,40 @@
# frozen_string_literal: true
require "spec_helper"
RSpec.describe PaperTrail, versioning: true do
it "baseline test setup" do
expect(Person.new).to be_versioned
end
# See https://github.com/paper-trail-gem/paper_trail/issues/594
describe "#association reify error behaviour" do
it "association reify error behaviour = :warn" do
::PaperTrail.config.association_reify_error_behaviour = :warn
person = Person.create(name: "Frank")
thing = Thing.create(name: "BMW 325")
thing2 = Thing.create(name: "BMX 1.0")
person.thing = thing
person.thing_2 = thing2
person.update_attributes(name: "Steve")
thing.update_attributes(name: "BMW 330")
thing.update_attributes(name: "BMX 2.0")
person.update_attributes(name: "Peter")
expect(person.reload.versions.length).to(eq(3))
logger = person.versions.first.logger
allow(logger).to receive(:warn)
person.reload.versions.second.reify(has_one: true)
expect(logger).to(
have_received(:warn).with(/Unable to reify has_one association/).twice
)
end
end
end