paper_trail 7.0.0 → 7.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +0 -3
- data/CHANGELOG.md +15 -0
- data/README.md +29 -28
- data/lib/generators/paper_trail/install_generator.rb +59 -1
- data/lib/generators/paper_trail/templates/{add_object_changes_to_versions.rb → add_object_changes_to_versions.rb.erb} +0 -0
- data/lib/generators/paper_trail/templates/{add_transaction_id_column_to_versions.rb → add_transaction_id_column_to_versions.rb.erb} +0 -0
- data/lib/generators/paper_trail/templates/{create_version_associations.rb → create_version_associations.rb.erb} +0 -0
- data/lib/generators/paper_trail/templates/create_versions.rb.erb +36 -0
- data/lib/paper_trail/version_number.rb +1 -1
- data/paper_trail.gemspec +1 -1
- data/spec/generators/install_generator_spec.rb +18 -2
- data/spec/models/boolit_spec.rb +23 -31
- data/spec/models/callback_modifier_spec.rb +74 -78
- data/spec/models/gadget_spec.rb +26 -27
- data/spec/models/joined_version_spec.rb +22 -28
- data/spec/models/skipper_spec.rb +29 -33
- data/spec/models/version_spec.rb +184 -183
- metadata +9 -11
- data/lib/generators/paper_trail/templates/create_versions.rb +0 -80
- data/spec/generators/paper_trail/templates/create_versions_spec.rb +0 -51
|
@@ -1,96 +1,92 @@
|
|
|
1
1
|
require "rails_helper"
|
|
2
2
|
|
|
3
|
-
describe CallbackModifier, type: :model do
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
expect(modifier.paper_trail_options[:on]).to eq [:destroy]
|
|
10
|
-
end
|
|
3
|
+
RSpec.describe CallbackModifier, type: :model, versioning: true do
|
|
4
|
+
describe "paper_trail_on_destroy" do
|
|
5
|
+
it "adds :destroy to paper_trail_options[:on]" do
|
|
6
|
+
modifier = NoArgDestroyModifier.create!(some_content: FFaker::Lorem.sentence)
|
|
7
|
+
expect(modifier.paper_trail_options[:on]).to eq([:destroy])
|
|
8
|
+
end
|
|
11
9
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
10
|
+
context "when :before" do
|
|
11
|
+
it "creates the version before destroy" do
|
|
12
|
+
modifier = BeforeDestroyModifier.create!(some_content: FFaker::Lorem.sentence)
|
|
13
|
+
modifier.test_destroy
|
|
14
|
+
expect(modifier.versions.last.reify).not_to be_flagged_deleted
|
|
15
|
+
end
|
|
16
|
+
end
|
|
19
17
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
18
|
+
context "when :after" do
|
|
19
|
+
it "creates the version after destroy" do
|
|
20
|
+
modifier = AfterDestroyModifier.create!(some_content: FFaker::Lorem.sentence)
|
|
21
|
+
modifier.test_destroy
|
|
22
|
+
expect(modifier.versions.last.reify).to be_flagged_deleted
|
|
23
|
+
end
|
|
24
|
+
end
|
|
27
25
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
end
|
|
34
|
-
end
|
|
26
|
+
context "when no argument" do
|
|
27
|
+
it "defaults to before destroy" do
|
|
28
|
+
modifier = NoArgDestroyModifier.create!(some_content: FFaker::Lorem.sentence)
|
|
29
|
+
modifier.test_destroy
|
|
30
|
+
expect(modifier.versions.last.reify).not_to be_flagged_deleted
|
|
35
31
|
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
36
34
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
35
|
+
describe "paper_trail_on_update" do
|
|
36
|
+
it "adds :update to paper_trail_options[:on]" do
|
|
37
|
+
modifier = UpdateModifier.create!(some_content: FFaker::Lorem.sentence)
|
|
38
|
+
expect(modifier.paper_trail_options[:on]).to eq [:update]
|
|
39
|
+
end
|
|
42
40
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
41
|
+
it "creates a version" do
|
|
42
|
+
modifier = UpdateModifier.create!(some_content: FFaker::Lorem.sentence)
|
|
43
|
+
modifier.update_attributes! some_content: "modified"
|
|
44
|
+
expect(modifier.versions.last.event).to eq "update"
|
|
45
|
+
end
|
|
46
|
+
end
|
|
49
47
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
48
|
+
describe "paper_trail_on_create" do
|
|
49
|
+
it "adds :create to paper_trail_options[:on]" do
|
|
50
|
+
modifier = CreateModifier.create!(some_content: FFaker::Lorem.sentence)
|
|
51
|
+
expect(modifier.paper_trail_options[:on]).to eq [:create]
|
|
52
|
+
end
|
|
55
53
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
54
|
+
it "creates a version" do
|
|
55
|
+
modifier = CreateModifier.create!(some_content: FFaker::Lorem.sentence)
|
|
56
|
+
expect(modifier.versions.last.event).to eq "create"
|
|
57
|
+
end
|
|
58
|
+
end
|
|
61
59
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
60
|
+
context "when no callback-method used" do
|
|
61
|
+
it "sets paper_trail_options[:on] to [:create, :update, :destroy]" do
|
|
62
|
+
modifier = DefaultModifier.create!(some_content: FFaker::Lorem.sentence)
|
|
63
|
+
expect(modifier.paper_trail_options[:on]).to eq %i(create update destroy)
|
|
64
|
+
end
|
|
67
65
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
66
|
+
it "tracks destroy" do
|
|
67
|
+
modifier = DefaultModifier.create!(some_content: FFaker::Lorem.sentence)
|
|
68
|
+
modifier.destroy
|
|
69
|
+
expect(modifier.versions.last.event).to eq "destroy"
|
|
70
|
+
end
|
|
73
71
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
72
|
+
it "tracks update" do
|
|
73
|
+
modifier = DefaultModifier.create!(some_content: FFaker::Lorem.sentence)
|
|
74
|
+
modifier.update_attributes! some_content: "modified"
|
|
75
|
+
expect(modifier.versions.last.event).to eq "update"
|
|
76
|
+
end
|
|
79
77
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
78
|
+
it "tracks create" do
|
|
79
|
+
modifier = DefaultModifier.create!(some_content: FFaker::Lorem.sentence)
|
|
80
|
+
expect(modifier.versions.last.event).to eq "create"
|
|
81
|
+
end
|
|
82
|
+
end
|
|
85
83
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
end
|
|
93
|
-
end
|
|
84
|
+
context "when only one callback-method" do
|
|
85
|
+
it "does only track the corresponding event" do
|
|
86
|
+
modifier = CreateModifier.create!(some_content: FFaker::Lorem.sentence)
|
|
87
|
+
modifier.update_attributes!(some_content: "modified")
|
|
88
|
+
modifier.test_destroy
|
|
89
|
+
expect(modifier.versions.collect(&:event)).to eq ["create"]
|
|
94
90
|
end
|
|
95
91
|
end
|
|
96
92
|
end
|
data/spec/models/gadget_spec.rb
CHANGED
|
@@ -23,41 +23,40 @@ describe Gadget, type: :model do
|
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
describe "#changed_notably?", versioning: true do
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
context "create events" do
|
|
26
|
+
context "new record" do
|
|
29
27
|
it "returns true" do
|
|
30
|
-
|
|
28
|
+
g = Gadget.new(created_at: Time.now)
|
|
29
|
+
expect(g.paper_trail.changed_notably?).to eq(true)
|
|
31
30
|
end
|
|
32
31
|
end
|
|
33
32
|
|
|
34
|
-
context "update
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
expect(subject.paper_trail.changed_notably?).to be true
|
|
41
|
-
end
|
|
33
|
+
context "persisted record without update timestamps" do
|
|
34
|
+
it "only acknowledges non-ignored attrs" do
|
|
35
|
+
subject = Gadget.create!(created_at: Time.now)
|
|
36
|
+
subject.name = "Wrench"
|
|
37
|
+
expect(subject.paper_trail.changed_notably?).to be true
|
|
38
|
+
end
|
|
42
39
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
40
|
+
it "does not acknowledge ignored attr (brand)" do
|
|
41
|
+
subject = Gadget.create!(created_at: Time.now)
|
|
42
|
+
subject.brand = "Acme"
|
|
43
|
+
expect(subject.paper_trail.changed_notably?).to be false
|
|
47
44
|
end
|
|
45
|
+
end
|
|
48
46
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
47
|
+
context "persisted record with update timestamps" do
|
|
48
|
+
it "only acknowledges non-ignored attrs" do
|
|
49
|
+
subject = Gadget.create!(created_at: Time.now)
|
|
50
|
+
subject.name = "Wrench"
|
|
51
|
+
subject.updated_at = Time.now
|
|
52
|
+
expect(subject.paper_trail.changed_notably?).to be true
|
|
53
|
+
end
|
|
55
54
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
55
|
+
it "does not acknowledge ignored attrs and timestamps only" do
|
|
56
|
+
subject = Gadget.create!(created_at: Time.now)
|
|
57
|
+
subject.brand = "Acme"
|
|
58
|
+
subject.updated_at = Time.now
|
|
59
|
+
expect(subject.paper_trail.changed_notably?).to be false
|
|
61
60
|
end
|
|
62
61
|
end
|
|
63
62
|
end
|
|
@@ -1,47 +1,41 @@
|
|
|
1
1
|
require "rails_helper"
|
|
2
2
|
|
|
3
|
-
describe JoinedVersion, type: :model, versioning: true do
|
|
4
|
-
it { expect(JoinedVersion.superclass).to be PaperTrail::Version }
|
|
5
|
-
|
|
3
|
+
RSpec.describe JoinedVersion, type: :model, versioning: true do
|
|
6
4
|
let(:widget) { Widget.create!(name: FFaker::Name.name) }
|
|
7
5
|
let(:version) { JoinedVersion.first }
|
|
8
6
|
|
|
9
|
-
describe "
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
end
|
|
7
|
+
describe "default_scope" do
|
|
8
|
+
it { expect(JoinedVersion.default_scopes).not_to be_empty }
|
|
9
|
+
end
|
|
13
10
|
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
describe "VersionConcern::ClassMethods" do
|
|
12
|
+
before { widget } # persist a widget
|
|
16
13
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
end
|
|
14
|
+
describe "#subsequent" do
|
|
15
|
+
it "does not raise error when there is a default_scope that joins" do
|
|
16
|
+
JoinedVersion.subsequent(version).first
|
|
21
17
|
end
|
|
18
|
+
end
|
|
22
19
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
end
|
|
20
|
+
describe "#preceding" do
|
|
21
|
+
it "does not raise error when there is a default scope that joins" do
|
|
22
|
+
JoinedVersion.preceding(version).first
|
|
27
23
|
end
|
|
24
|
+
end
|
|
28
25
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
end
|
|
26
|
+
describe "#between" do
|
|
27
|
+
it "does not raise error when there is a default scope that joins" do
|
|
28
|
+
JoinedVersion.between(Time.now, 1.minute.from_now).first
|
|
33
29
|
end
|
|
34
30
|
end
|
|
35
31
|
end
|
|
36
32
|
|
|
37
|
-
describe "
|
|
38
|
-
|
|
39
|
-
it { is_expected.to respond_to(:index) }
|
|
33
|
+
describe "#index" do
|
|
34
|
+
it { is_expected.to respond_to(:index) }
|
|
40
35
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
end
|
|
36
|
+
it "does not raise error when there is a default scope that joins" do
|
|
37
|
+
widget # persist a widget
|
|
38
|
+
version.index
|
|
45
39
|
end
|
|
46
40
|
end
|
|
47
41
|
end
|
data/spec/models/skipper_spec.rb
CHANGED
|
@@ -1,45 +1,41 @@
|
|
|
1
1
|
require "rails_helper"
|
|
2
2
|
|
|
3
|
-
describe Skipper, type: :model do
|
|
4
|
-
|
|
5
|
-
it { is_expected.to be_versioned }
|
|
3
|
+
RSpec.describe Skipper, type: :model, versioning: true do
|
|
4
|
+
it { is_expected.to be_versioned }
|
|
6
5
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
describe "#update_attributes!", versioning: true do
|
|
7
|
+
context "updating a skipped attribute" do
|
|
8
|
+
let(:t1) { Time.zone.local(2015, 7, 15, 20, 34, 0) }
|
|
9
|
+
let(:t2) { Time.zone.local(2015, 7, 15, 20, 34, 30) }
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
end
|
|
11
|
+
it "does not create a version" do
|
|
12
|
+
skipper = Skipper.create!(another_timestamp: t1)
|
|
13
|
+
expect {
|
|
14
|
+
skipper.update_attributes!(another_timestamp: t2)
|
|
15
|
+
}.not_to(change { skipper.versions.length })
|
|
18
16
|
end
|
|
19
17
|
end
|
|
18
|
+
end
|
|
20
19
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
let(:t2) { Time.zone.local(2015, 7, 15, 20, 34, 30) }
|
|
20
|
+
describe "#reify" do
|
|
21
|
+
let(:t1) { Time.zone.local(2015, 7, 15, 20, 34, 0) }
|
|
22
|
+
let(:t2) { Time.zone.local(2015, 7, 15, 20, 34, 30) }
|
|
25
23
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
24
|
+
context "without preserve (default)" do
|
|
25
|
+
it "has no timestamp" do
|
|
26
|
+
skipper = Skipper.create!(another_timestamp: t1)
|
|
27
|
+
skipper.update_attributes!(another_timestamp: t2, name: "Foobar")
|
|
28
|
+
skipper = skipper.versions.last.reify
|
|
29
|
+
expect(skipper.another_timestamp).to be(nil)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
34
32
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
end
|
|
42
|
-
end
|
|
33
|
+
context "with preserve" do
|
|
34
|
+
it "preserves its timestamp" do
|
|
35
|
+
skipper = Skipper.create!(another_timestamp: t1)
|
|
36
|
+
skipper.update_attributes!(another_timestamp: t2, name: "Foobar")
|
|
37
|
+
skipper = skipper.versions.last.reify(unversioned_attributes: :preserve)
|
|
38
|
+
expect(skipper.another_timestamp).to eq(t2)
|
|
43
39
|
end
|
|
44
40
|
end
|
|
45
41
|
end
|
data/spec/models/version_spec.rb
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
require "rails_helper"
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
expect(PaperTrail::Version).to include(PaperTrail::VersionConcern)
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
describe "Attributes" do
|
|
3
|
+
module PaperTrail
|
|
4
|
+
describe Version, type: :model do
|
|
9
5
|
describe "object_changes column", versioning: true do
|
|
10
6
|
let(:widget) { Widget.create!(name: "Dashboard") }
|
|
11
7
|
let(:value) { widget.versions.last.object_changes }
|
|
@@ -28,226 +24,231 @@ describe PaperTrail::Version, type: :model do
|
|
|
28
24
|
after(:all) { PaperTrail.serializer = PaperTrail::Serializers::YAML }
|
|
29
25
|
end
|
|
30
26
|
end
|
|
31
|
-
end
|
|
32
27
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
describe "#paper_trail_originator" do
|
|
38
|
-
context "No previous versions" do
|
|
39
|
-
specify { expect(subject.previous).to be_nil }
|
|
40
|
-
|
|
41
|
-
it "return nil" do
|
|
42
|
-
expect(subject.paper_trail_originator).to be_nil
|
|
43
|
-
end
|
|
28
|
+
describe "#paper_trail_originator" do
|
|
29
|
+
context "no previous versions" do
|
|
30
|
+
it "returns nil" do
|
|
31
|
+
expect(PaperTrail::Version.new.paper_trail_originator).to be_nil
|
|
44
32
|
end
|
|
33
|
+
end
|
|
45
34
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
widget.versions.first.update_attributes!(whodunnit: name)
|
|
54
|
-
widget.update_attributes!(name: FFaker::Name.first_name)
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
specify { expect(subject.previous).to be_instance_of(PaperTrail::Version) }
|
|
58
|
-
|
|
59
|
-
it "return nil" do
|
|
60
|
-
expect(subject.paper_trail_originator).to eq(name)
|
|
61
|
-
end
|
|
35
|
+
context "has previous version", versioning: true do
|
|
36
|
+
it "returns name of whodunnit" do
|
|
37
|
+
name = FFaker::Name.name
|
|
38
|
+
widget = Widget.create!(name: FFaker::Name.name)
|
|
39
|
+
widget.versions.first.update_attributes!(whodunnit: name)
|
|
40
|
+
widget.update_attributes!(name: FFaker::Name.first_name)
|
|
41
|
+
expect(widget.versions.last.paper_trail_originator).to eq(name)
|
|
62
42
|
end
|
|
63
43
|
end
|
|
44
|
+
end
|
|
64
45
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
subject.originator
|
|
46
|
+
describe "#previous" do
|
|
47
|
+
context "no previous versions" do
|
|
48
|
+
it "returns nil" do
|
|
49
|
+
expect(PaperTrail::Version.new.previous).to be_nil
|
|
70
50
|
end
|
|
51
|
+
end
|
|
71
52
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
53
|
+
context "has previous version", versioning: true do
|
|
54
|
+
it "returns a PaperTrail::Version" do
|
|
55
|
+
name = FFaker::Name.name
|
|
56
|
+
widget = Widget.create!(name: FFaker::Name.name)
|
|
57
|
+
widget.versions.first.update_attributes!(whodunnit: name)
|
|
58
|
+
widget.update_attributes!(name: FFaker::Name.first_name)
|
|
59
|
+
expect(widget.versions.last.previous).to be_instance_of(PaperTrail::Version)
|
|
76
60
|
end
|
|
77
61
|
end
|
|
62
|
+
end
|
|
78
63
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
expect(subject.terminator).to eq(attributes[:whodunnit])
|
|
86
|
-
end
|
|
64
|
+
describe "#originator" do
|
|
65
|
+
it "sets the invoke `paper_trail_originator`" do
|
|
66
|
+
allow(ActiveSupport::Deprecation).to receive(:warn)
|
|
67
|
+
subject = PaperTrail::Version.new
|
|
68
|
+
expect(subject).to receive(:paper_trail_originator)
|
|
69
|
+
subject.originator
|
|
87
70
|
end
|
|
88
71
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
72
|
+
it "displays a deprecation warning" do
|
|
73
|
+
expect(ActiveSupport::Deprecation).to receive(:warn).
|
|
74
|
+
with(/Use paper_trail_originator instead of originator/)
|
|
75
|
+
subject = PaperTrail::Version.new
|
|
76
|
+
subject.originator
|
|
93
77
|
end
|
|
94
78
|
end
|
|
95
79
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
80
|
+
describe "#terminator" do
|
|
81
|
+
it "is an alias for the `whodunnit` attribute" do
|
|
82
|
+
attributes = { whodunnit: FFaker::Name.first_name }
|
|
83
|
+
subject = PaperTrail::Version.new(attributes)
|
|
84
|
+
expect(subject.terminator).to eq(attributes[:whodunnit])
|
|
85
|
+
end
|
|
101
86
|
end
|
|
102
87
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
ActiveRecord::Base.connection.execute(
|
|
110
|
-
"ALTER TABLE versions DROP COLUMN #{column};"
|
|
111
|
-
)
|
|
112
|
-
ActiveRecord::Base.connection.execute(
|
|
113
|
-
"ALTER TABLE versions ADD COLUMN #{column} #{override};"
|
|
114
|
-
)
|
|
115
|
-
end
|
|
116
|
-
PaperTrail::Version.reset_column_information
|
|
117
|
-
end
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
after do
|
|
121
|
-
if override
|
|
122
|
-
ActiveRecord::Base.connection.execute("ROLLBACK TO SAVEPOINT pgtest;")
|
|
123
|
-
PaperTrail::Version.reset_column_information
|
|
124
|
-
end
|
|
125
|
-
end
|
|
88
|
+
describe "#version_author" do
|
|
89
|
+
it "is an alias for the `terminator` method" do
|
|
90
|
+
subject = PaperTrail::Version.new
|
|
91
|
+
expect(subject.method(:version_author)).to eq(subject.method(:terminator))
|
|
92
|
+
end
|
|
93
|
+
end
|
|
126
94
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
95
|
+
describe "Methods" do
|
|
96
|
+
column_overrides = [false]
|
|
97
|
+
if ENV["DB"] == "postgres" && ::ActiveRecord::VERSION::MAJOR >= 4
|
|
98
|
+
column_overrides << "json"
|
|
99
|
+
# 'jsonb' column types are only supported for ActiveRecord 4.2+
|
|
100
|
+
column_overrides << "jsonb" if ::ActiveRecord::VERSION::STRING >= "4.2"
|
|
101
|
+
end
|
|
131
102
|
|
|
103
|
+
column_overrides.shuffle.each do |override|
|
|
104
|
+
context "with a #{override || 'text'} column" do
|
|
132
105
|
before do
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
PaperTrail::Version.
|
|
144
|
-
}.to raise_error(ArgumentError)
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
context "`serializer == YAML`" do
|
|
148
|
-
specify do
|
|
149
|
-
expect(PaperTrail.serializer).to be PaperTrail::Serializers::YAML
|
|
106
|
+
if override
|
|
107
|
+
ActiveRecord::Base.connection.execute("SAVEPOINT pgtest;")
|
|
108
|
+
%w(object object_changes).each do |column|
|
|
109
|
+
ActiveRecord::Base.connection.execute(
|
|
110
|
+
"ALTER TABLE versions DROP COLUMN #{column};"
|
|
111
|
+
)
|
|
112
|
+
ActiveRecord::Base.connection.execute(
|
|
113
|
+
"ALTER TABLE versions ADD COLUMN #{column} #{override};"
|
|
114
|
+
)
|
|
115
|
+
end
|
|
116
|
+
PaperTrail::Version.reset_column_information
|
|
150
117
|
end
|
|
118
|
+
end
|
|
151
119
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
expect(
|
|
157
|
-
PaperTrail::Version.where_object(an_integer: 100)
|
|
158
|
-
).to eq([widget.versions[2]])
|
|
120
|
+
after do
|
|
121
|
+
if override
|
|
122
|
+
ActiveRecord::Base.connection.execute("ROLLBACK TO SAVEPOINT pgtest;")
|
|
123
|
+
PaperTrail::Version.reset_column_information
|
|
159
124
|
end
|
|
160
125
|
end
|
|
161
126
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
127
|
+
describe "#where_object", versioning: true do
|
|
128
|
+
let(:widget) { Widget.new }
|
|
129
|
+
let(:name) { FFaker::Name.first_name }
|
|
130
|
+
let(:int) { rand(10) + 1 }
|
|
166
131
|
|
|
167
|
-
|
|
168
|
-
|
|
132
|
+
before do
|
|
133
|
+
widget.update_attributes!(name: name, an_integer: int)
|
|
134
|
+
widget.update_attributes!(name: "foobar", an_integer: 100)
|
|
135
|
+
widget.update_attributes!(name: FFaker::Name.last_name, an_integer: 15)
|
|
169
136
|
end
|
|
170
137
|
|
|
171
|
-
it "
|
|
172
|
-
expect
|
|
173
|
-
PaperTrail::Version.where_object(
|
|
174
|
-
|
|
175
|
-
expect
|
|
176
|
-
PaperTrail::Version.where_object(
|
|
177
|
-
|
|
138
|
+
it "requires its argument to be a Hash" do
|
|
139
|
+
expect {
|
|
140
|
+
PaperTrail::Version.where_object(:foo)
|
|
141
|
+
}.to raise_error(ArgumentError)
|
|
142
|
+
expect {
|
|
143
|
+
PaperTrail::Version.where_object([])
|
|
144
|
+
}.to raise_error(ArgumentError)
|
|
178
145
|
end
|
|
179
146
|
|
|
180
|
-
|
|
181
|
-
|
|
147
|
+
context "`serializer == YAML`" do
|
|
148
|
+
specify do
|
|
149
|
+
expect(PaperTrail.serializer).to be PaperTrail::Serializers::YAML
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
it "locates versions according to their `object` contents" do
|
|
153
|
+
expect(
|
|
154
|
+
PaperTrail::Version.where_object(name: name)
|
|
155
|
+
).to eq([widget.versions[1]])
|
|
156
|
+
expect(
|
|
157
|
+
PaperTrail::Version.where_object(an_integer: 100)
|
|
158
|
+
).to eq([widget.versions[2]])
|
|
159
|
+
end
|
|
182
160
|
end
|
|
183
|
-
end
|
|
184
|
-
end
|
|
185
|
-
|
|
186
|
-
describe "#where_object_changes", versioning: true do
|
|
187
|
-
let(:widget) { Widget.new }
|
|
188
|
-
let(:name) { FFaker::Name.first_name }
|
|
189
|
-
let(:int) { rand(5) + 2 }
|
|
190
161
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
162
|
+
context "JSON serializer" do
|
|
163
|
+
before(:all) do
|
|
164
|
+
PaperTrail.serializer = PaperTrail::Serializers::JSON
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
specify do
|
|
168
|
+
expect(PaperTrail.serializer).to be PaperTrail::Serializers::JSON
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
it "locates versions according to their `object` contents" do
|
|
172
|
+
expect(
|
|
173
|
+
PaperTrail::Version.where_object(name: name)
|
|
174
|
+
).to eq([widget.versions[1]])
|
|
175
|
+
expect(
|
|
176
|
+
PaperTrail::Version.where_object(an_integer: 100)
|
|
177
|
+
).to eq([widget.versions[2]])
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
after(:all) do
|
|
181
|
+
PaperTrail.serializer = PaperTrail::Serializers::YAML
|
|
182
|
+
end
|
|
183
|
+
end
|
|
195
184
|
end
|
|
196
185
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
expect {
|
|
202
|
-
PaperTrail::Version.where_object_changes([])
|
|
203
|
-
}.to raise_error(ArgumentError)
|
|
204
|
-
end
|
|
186
|
+
describe "#where_object_changes", versioning: true do
|
|
187
|
+
let(:widget) { Widget.new }
|
|
188
|
+
let(:name) { FFaker::Name.first_name }
|
|
189
|
+
let(:int) { rand(5) + 2 }
|
|
205
190
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
expect(
|
|
211
|
-
widget.versions.where_object_changes(name: name)
|
|
212
|
-
).to eq(widget.versions[0..1])
|
|
213
|
-
expect(
|
|
214
|
-
widget.versions.where_object_changes(an_integer: 77)
|
|
215
|
-
).to eq(widget.versions[1..2])
|
|
216
|
-
expect(
|
|
217
|
-
widget.versions.where_object_changes(an_integer: int)
|
|
218
|
-
).to eq([widget.versions.last])
|
|
191
|
+
before do
|
|
192
|
+
widget.update_attributes!(name: name, an_integer: 0)
|
|
193
|
+
widget.update_attributes!(name: "foobar", an_integer: 77)
|
|
194
|
+
widget.update_attributes!(name: FFaker::Name.last_name, an_integer: int)
|
|
219
195
|
end
|
|
220
196
|
|
|
221
|
-
it "
|
|
222
|
-
expect
|
|
223
|
-
|
|
224
|
-
|
|
197
|
+
it "requires its argument to be a Hash" do
|
|
198
|
+
expect {
|
|
199
|
+
PaperTrail::Version.where_object_changes(:foo)
|
|
200
|
+
}.to raise_error(ArgumentError)
|
|
201
|
+
expect {
|
|
202
|
+
PaperTrail::Version.where_object_changes([])
|
|
203
|
+
}.to raise_error(ArgumentError)
|
|
225
204
|
end
|
|
226
|
-
end
|
|
227
205
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
widget.versions
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
widget.versions
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
widget.versions.
|
|
241
|
-
|
|
206
|
+
context "YAML serializer" do
|
|
207
|
+
specify { expect(PaperTrail.serializer).to be PaperTrail::Serializers::YAML }
|
|
208
|
+
|
|
209
|
+
it "locates versions according to their `object_changes` contents" do
|
|
210
|
+
expect(
|
|
211
|
+
widget.versions.where_object_changes(name: name)
|
|
212
|
+
).to eq(widget.versions[0..1])
|
|
213
|
+
expect(
|
|
214
|
+
widget.versions.where_object_changes(an_integer: 77)
|
|
215
|
+
).to eq(widget.versions[1..2])
|
|
216
|
+
expect(
|
|
217
|
+
widget.versions.where_object_changes(an_integer: int)
|
|
218
|
+
).to eq([widget.versions.last])
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
it "handles queries for multiple attributes" do
|
|
222
|
+
expect(
|
|
223
|
+
widget.versions.where_object_changes(an_integer: 77, name: "foobar")
|
|
224
|
+
).to eq(widget.versions[1..2])
|
|
225
|
+
end
|
|
242
226
|
end
|
|
243
227
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
228
|
+
context "JSON serializer" do
|
|
229
|
+
before(:all) { PaperTrail.serializer = PaperTrail::Serializers::JSON }
|
|
230
|
+
specify { expect(PaperTrail.serializer).to be PaperTrail::Serializers::JSON }
|
|
231
|
+
|
|
232
|
+
it "locates versions according to their `object_changes` contents" do
|
|
233
|
+
expect(
|
|
234
|
+
widget.versions.where_object_changes(name: name)
|
|
235
|
+
).to eq(widget.versions[0..1])
|
|
236
|
+
expect(
|
|
237
|
+
widget.versions.where_object_changes(an_integer: 77)
|
|
238
|
+
).to eq(widget.versions[1..2])
|
|
239
|
+
expect(
|
|
240
|
+
widget.versions.where_object_changes(an_integer: int)
|
|
241
|
+
).to eq([widget.versions.last])
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
it "handles queries for multiple attributes" do
|
|
245
|
+
expect(
|
|
246
|
+
widget.versions.where_object_changes(an_integer: 77, name: "foobar")
|
|
247
|
+
).to eq(widget.versions[1..2])
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
after(:all) { PaperTrail.serializer = PaperTrail::Serializers::YAML }
|
|
248
251
|
end
|
|
249
|
-
|
|
250
|
-
after(:all) { PaperTrail.serializer = PaperTrail::Serializers::YAML }
|
|
251
252
|
end
|
|
252
253
|
end
|
|
253
254
|
end
|