mongoid-history 0.8.3 → 0.8.5
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/.coveralls.yml +1 -1
- data/.document +5 -5
- data/.github/workflows/test.yml +72 -0
- data/.gitignore +46 -46
- data/.rspec +2 -2
- data/.rubocop.yml +6 -6
- data/.rubocop_todo.yml +99 -99
- data/CHANGELOG.md +173 -163
- data/CONTRIBUTING.md +117 -118
- data/Dangerfile +1 -1
- data/Gemfile +49 -40
- data/LICENSE.txt +20 -20
- data/README.md +609 -608
- data/RELEASING.md +66 -67
- data/Rakefile +24 -24
- data/UPGRADING.md +53 -53
- data/lib/mongoid/history/attributes/base.rb +72 -72
- data/lib/mongoid/history/attributes/create.rb +45 -45
- data/lib/mongoid/history/attributes/destroy.rb +34 -34
- data/lib/mongoid/history/attributes/update.rb +104 -104
- data/lib/mongoid/history/options.rb +177 -177
- data/lib/mongoid/history/trackable.rb +588 -583
- data/lib/mongoid/history/tracker.rb +247 -247
- data/lib/mongoid/history/version.rb +5 -5
- data/lib/mongoid/history.rb +77 -77
- data/lib/mongoid-history.rb +1 -1
- data/mongoid-history.gemspec +25 -25
- data/perf/benchmark_modified_attributes_for_create.rb +65 -65
- data/perf/gc_suite.rb +21 -21
- data/spec/integration/embedded_in_polymorphic_spec.rb +112 -112
- data/spec/integration/integration_spec.rb +976 -976
- data/spec/integration/multi_relation_spec.rb +47 -47
- data/spec/integration/multiple_trackers_spec.rb +68 -68
- data/spec/integration/nested_embedded_documents_spec.rb +64 -64
- data/spec/integration/nested_embedded_documents_tracked_in_parent_spec.rb +124 -124
- data/spec/integration/nested_embedded_polymorphic_documents_spec.rb +115 -115
- data/spec/integration/subclasses_spec.rb +47 -47
- data/spec/integration/track_history_order_spec.rb +84 -84
- data/spec/integration/validation_failure_spec.rb +76 -76
- data/spec/spec_helper.rb +32 -30
- data/spec/support/error_helpers.rb +7 -0
- data/spec/support/mongoid.rb +11 -11
- data/spec/support/mongoid_history.rb +12 -12
- data/spec/unit/attributes/base_spec.rb +141 -141
- data/spec/unit/attributes/create_spec.rb +342 -342
- data/spec/unit/attributes/destroy_spec.rb +228 -228
- data/spec/unit/attributes/update_spec.rb +342 -342
- data/spec/unit/callback_options_spec.rb +165 -165
- data/spec/unit/embedded_methods_spec.rb +87 -87
- data/spec/unit/history_spec.rb +58 -58
- data/spec/unit/my_instance_methods_spec.rb +555 -555
- data/spec/unit/options_spec.rb +365 -365
- data/spec/unit/singleton_methods_spec.rb +406 -406
- data/spec/unit/store/default_store_spec.rb +11 -11
- data/spec/unit/store/request_store_spec.rb +13 -13
- data/spec/unit/trackable_spec.rb +1057 -987
- data/spec/unit/tracker_spec.rb +190 -190
- metadata +9 -7
- data/.travis.yml +0 -36
@@ -1,47 +1,47 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Mongoid::History::Tracker do
|
4
|
-
before :each do
|
5
|
-
class Model
|
6
|
-
include Mongoid::Document
|
7
|
-
include Mongoid::History::Trackable
|
8
|
-
|
9
|
-
field :name, type: String
|
10
|
-
belongs_to :user, inverse_of: :models
|
11
|
-
has_and_belongs_to_many :external_users, class_name: 'User', inverse_of: :external_models
|
12
|
-
|
13
|
-
track_history on: %i[name user external_user_ids], modifier_field_inverse_of: nil
|
14
|
-
end
|
15
|
-
|
16
|
-
class User
|
17
|
-
include Mongoid::Document
|
18
|
-
|
19
|
-
has_many :models, dependent: :destroy, inverse_of: :user
|
20
|
-
has_and_belongs_to_many :external_model, class_name: 'Model', inverse_of: :external_users
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
after :each do
|
25
|
-
Object.send(:remove_const, :Model)
|
26
|
-
Object.send(:remove_const, :User)
|
27
|
-
end
|
28
|
-
|
29
|
-
let(:user) { User.create! }
|
30
|
-
let(:model) { Model.create!(name: 'Foo', user: user, modifier: user) }
|
31
|
-
|
32
|
-
it 'should be possible to undo when having multiple relations to modifier class' do
|
33
|
-
model.update_attributes!(name: 'Bar', modifier: user)
|
34
|
-
|
35
|
-
model.undo! user
|
36
|
-
expect(model.name).to eq 'Foo'
|
37
|
-
|
38
|
-
model.redo! user, 2
|
39
|
-
expect(model.name).to eq 'Bar'
|
40
|
-
end
|
41
|
-
|
42
|
-
it 'should track foreign key relations' do
|
43
|
-
expect(Model.tracked_field?(:external_user_ids)).to be true
|
44
|
-
expect(Model.tracked_field?(:user)).to be true
|
45
|
-
expect(Model.tracked_field?(:user_id)).to be true
|
46
|
-
end
|
47
|
-
end
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Mongoid::History::Tracker do
|
4
|
+
before :each do
|
5
|
+
class Model
|
6
|
+
include Mongoid::Document
|
7
|
+
include Mongoid::History::Trackable
|
8
|
+
|
9
|
+
field :name, type: String
|
10
|
+
belongs_to :user, inverse_of: :models
|
11
|
+
has_and_belongs_to_many :external_users, class_name: 'User', inverse_of: :external_models
|
12
|
+
|
13
|
+
track_history on: %i[name user external_user_ids], modifier_field_inverse_of: nil
|
14
|
+
end
|
15
|
+
|
16
|
+
class User
|
17
|
+
include Mongoid::Document
|
18
|
+
|
19
|
+
has_many :models, dependent: :destroy, inverse_of: :user
|
20
|
+
has_and_belongs_to_many :external_model, class_name: 'Model', inverse_of: :external_users
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
after :each do
|
25
|
+
Object.send(:remove_const, :Model)
|
26
|
+
Object.send(:remove_const, :User)
|
27
|
+
end
|
28
|
+
|
29
|
+
let(:user) { User.create! }
|
30
|
+
let(:model) { Model.create!(name: 'Foo', user: user, modifier: user) }
|
31
|
+
|
32
|
+
it 'should be possible to undo when having multiple relations to modifier class' do
|
33
|
+
model.update_attributes!(name: 'Bar', modifier: user)
|
34
|
+
|
35
|
+
model.undo! user
|
36
|
+
expect(model.name).to eq 'Foo'
|
37
|
+
|
38
|
+
model.redo! user, 2
|
39
|
+
expect(model.name).to eq 'Bar'
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should track foreign key relations' do
|
43
|
+
expect(Model.tracked_field?(:external_user_ids)).to be true
|
44
|
+
expect(Model.tracked_field?(:user)).to be true
|
45
|
+
expect(Model.tracked_field?(:user_id)).to be true
|
46
|
+
end
|
47
|
+
end
|
@@ -1,68 +1,68 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Mongoid::History do
|
4
|
-
before :each do
|
5
|
-
class First
|
6
|
-
include Mongoid::Document
|
7
|
-
include Mongoid::History::Trackable
|
8
|
-
|
9
|
-
field :text, type: String
|
10
|
-
track_history on: [:text], tracker_class_name: :first_history_tracker
|
11
|
-
end
|
12
|
-
|
13
|
-
class Second
|
14
|
-
include Mongoid::Document
|
15
|
-
include Mongoid::History::Trackable
|
16
|
-
|
17
|
-
field :text, type: String
|
18
|
-
track_history on: [:text], tracker_class_name: :second_history_tracker
|
19
|
-
end
|
20
|
-
|
21
|
-
class User
|
22
|
-
include Mongoid::Document
|
23
|
-
end
|
24
|
-
|
25
|
-
class FirstHistoryTracker
|
26
|
-
include Mongoid::History::Tracker
|
27
|
-
end
|
28
|
-
|
29
|
-
class SecondHistoryTracker
|
30
|
-
include Mongoid::History::Tracker
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
after :each do
|
35
|
-
Object.send(:remove_const, :First)
|
36
|
-
Object.send(:remove_const, :Second)
|
37
|
-
Object.send(:remove_const, :User)
|
38
|
-
Object.send(:remove_const, :FirstHistoryTracker)
|
39
|
-
Object.send(:remove_const, :SecondHistoryTracker)
|
40
|
-
end
|
41
|
-
|
42
|
-
let(:user) { User.create! }
|
43
|
-
|
44
|
-
it 'should be possible to have different trackers for each class' do
|
45
|
-
expect(FirstHistoryTracker.count).to eq(0)
|
46
|
-
expect(SecondHistoryTracker.count).to eq(0)
|
47
|
-
expect(First.tracker_class).to be FirstHistoryTracker
|
48
|
-
expect(Second.tracker_class).to be SecondHistoryTracker
|
49
|
-
|
50
|
-
foo = First.create!(modifier: user)
|
51
|
-
bar = Second.create!(modifier: user)
|
52
|
-
|
53
|
-
expect(FirstHistoryTracker.count).to eq 1
|
54
|
-
expect(SecondHistoryTracker.count).to eq 1
|
55
|
-
|
56
|
-
foo.update_attributes!(text: "I'm foo")
|
57
|
-
bar.update_attributes!(text: "I'm bar")
|
58
|
-
|
59
|
-
expect(FirstHistoryTracker.count).to eq 2
|
60
|
-
expect(SecondHistoryTracker.count).to eq 2
|
61
|
-
|
62
|
-
foo.destroy
|
63
|
-
bar.destroy
|
64
|
-
|
65
|
-
expect(FirstHistoryTracker.count).to eq 3
|
66
|
-
expect(SecondHistoryTracker.count).to eq 3
|
67
|
-
end
|
68
|
-
end
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Mongoid::History do
|
4
|
+
before :each do
|
5
|
+
class First
|
6
|
+
include Mongoid::Document
|
7
|
+
include Mongoid::History::Trackable
|
8
|
+
|
9
|
+
field :text, type: String
|
10
|
+
track_history on: [:text], tracker_class_name: :first_history_tracker
|
11
|
+
end
|
12
|
+
|
13
|
+
class Second
|
14
|
+
include Mongoid::Document
|
15
|
+
include Mongoid::History::Trackable
|
16
|
+
|
17
|
+
field :text, type: String
|
18
|
+
track_history on: [:text], tracker_class_name: :second_history_tracker
|
19
|
+
end
|
20
|
+
|
21
|
+
class User
|
22
|
+
include Mongoid::Document
|
23
|
+
end
|
24
|
+
|
25
|
+
class FirstHistoryTracker
|
26
|
+
include Mongoid::History::Tracker
|
27
|
+
end
|
28
|
+
|
29
|
+
class SecondHistoryTracker
|
30
|
+
include Mongoid::History::Tracker
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
after :each do
|
35
|
+
Object.send(:remove_const, :First)
|
36
|
+
Object.send(:remove_const, :Second)
|
37
|
+
Object.send(:remove_const, :User)
|
38
|
+
Object.send(:remove_const, :FirstHistoryTracker)
|
39
|
+
Object.send(:remove_const, :SecondHistoryTracker)
|
40
|
+
end
|
41
|
+
|
42
|
+
let(:user) { User.create! }
|
43
|
+
|
44
|
+
it 'should be possible to have different trackers for each class' do
|
45
|
+
expect(FirstHistoryTracker.count).to eq(0)
|
46
|
+
expect(SecondHistoryTracker.count).to eq(0)
|
47
|
+
expect(First.tracker_class).to be FirstHistoryTracker
|
48
|
+
expect(Second.tracker_class).to be SecondHistoryTracker
|
49
|
+
|
50
|
+
foo = First.create!(modifier: user)
|
51
|
+
bar = Second.create!(modifier: user)
|
52
|
+
|
53
|
+
expect(FirstHistoryTracker.count).to eq 1
|
54
|
+
expect(SecondHistoryTracker.count).to eq 1
|
55
|
+
|
56
|
+
foo.update_attributes!(text: "I'm foo")
|
57
|
+
bar.update_attributes!(text: "I'm bar")
|
58
|
+
|
59
|
+
expect(FirstHistoryTracker.count).to eq 2
|
60
|
+
expect(SecondHistoryTracker.count).to eq 2
|
61
|
+
|
62
|
+
foo.destroy
|
63
|
+
bar.destroy
|
64
|
+
|
65
|
+
expect(FirstHistoryTracker.count).to eq 3
|
66
|
+
expect(SecondHistoryTracker.count).to eq 3
|
67
|
+
end
|
68
|
+
end
|
@@ -1,64 +1,64 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Mongoid::History::Tracker do
|
4
|
-
before :each do
|
5
|
-
class ModelOne
|
6
|
-
include Mongoid::Document
|
7
|
-
include Mongoid::History::Trackable
|
8
|
-
|
9
|
-
field :name, type: String
|
10
|
-
belongs_to :user, inverse_of: :model_ones
|
11
|
-
embeds_many :emb_ones
|
12
|
-
|
13
|
-
track_history
|
14
|
-
end
|
15
|
-
|
16
|
-
class EmbOne
|
17
|
-
include Mongoid::Document
|
18
|
-
include Mongoid::History::Trackable
|
19
|
-
|
20
|
-
field :name
|
21
|
-
embeds_many :emb_twos, store_as: :ems
|
22
|
-
embedded_in :model_one
|
23
|
-
|
24
|
-
track_history
|
25
|
-
end
|
26
|
-
|
27
|
-
class EmbTwo
|
28
|
-
include Mongoid::Document
|
29
|
-
include Mongoid::History::Trackable
|
30
|
-
|
31
|
-
field :name
|
32
|
-
embedded_in :emb_one
|
33
|
-
|
34
|
-
track_history scope: :model_one
|
35
|
-
end
|
36
|
-
|
37
|
-
class User
|
38
|
-
include Mongoid::Document
|
39
|
-
|
40
|
-
has_many :model_ones, dependent: :destroy, inverse_of: :user
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
after :each do
|
45
|
-
Object.send(:remove_const, :ModelOne)
|
46
|
-
Object.send(:remove_const, :EmbOne)
|
47
|
-
Object.send(:remove_const, :EmbTwo)
|
48
|
-
Object.send(:remove_const, :User)
|
49
|
-
end
|
50
|
-
|
51
|
-
let(:user) { User.create! }
|
52
|
-
|
53
|
-
it 'should be able to track history for nested embedded documents' do
|
54
|
-
model = ModelOne.create!(name: 'm1name', user: user, modifier: user)
|
55
|
-
embedded1 = model.emb_ones.create!(name: 'e1name', modifier: user)
|
56
|
-
embedded2 = embedded1.emb_twos.create!(name: 'e2name', modifier: user)
|
57
|
-
|
58
|
-
embedded2.update_attributes!(name: 'a new name')
|
59
|
-
|
60
|
-
model.history_tracks[-1].undo! user
|
61
|
-
expect(embedded1.reload.name).to eq('e1name')
|
62
|
-
expect(embedded2.reload.name).to eq('e2name')
|
63
|
-
end
|
64
|
-
end
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Mongoid::History::Tracker do
|
4
|
+
before :each do
|
5
|
+
class ModelOne
|
6
|
+
include Mongoid::Document
|
7
|
+
include Mongoid::History::Trackable
|
8
|
+
|
9
|
+
field :name, type: String
|
10
|
+
belongs_to :user, inverse_of: :model_ones
|
11
|
+
embeds_many :emb_ones
|
12
|
+
|
13
|
+
track_history
|
14
|
+
end
|
15
|
+
|
16
|
+
class EmbOne
|
17
|
+
include Mongoid::Document
|
18
|
+
include Mongoid::History::Trackable
|
19
|
+
|
20
|
+
field :name
|
21
|
+
embeds_many :emb_twos, store_as: :ems
|
22
|
+
embedded_in :model_one
|
23
|
+
|
24
|
+
track_history
|
25
|
+
end
|
26
|
+
|
27
|
+
class EmbTwo
|
28
|
+
include Mongoid::Document
|
29
|
+
include Mongoid::History::Trackable
|
30
|
+
|
31
|
+
field :name
|
32
|
+
embedded_in :emb_one
|
33
|
+
|
34
|
+
track_history scope: :model_one
|
35
|
+
end
|
36
|
+
|
37
|
+
class User
|
38
|
+
include Mongoid::Document
|
39
|
+
|
40
|
+
has_many :model_ones, dependent: :destroy, inverse_of: :user
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
after :each do
|
45
|
+
Object.send(:remove_const, :ModelOne)
|
46
|
+
Object.send(:remove_const, :EmbOne)
|
47
|
+
Object.send(:remove_const, :EmbTwo)
|
48
|
+
Object.send(:remove_const, :User)
|
49
|
+
end
|
50
|
+
|
51
|
+
let(:user) { User.create! }
|
52
|
+
|
53
|
+
it 'should be able to track history for nested embedded documents' do
|
54
|
+
model = ModelOne.create!(name: 'm1name', user: user, modifier: user)
|
55
|
+
embedded1 = model.emb_ones.create!(name: 'e1name', modifier: user)
|
56
|
+
embedded2 = embedded1.emb_twos.create!(name: 'e2name', modifier: user)
|
57
|
+
|
58
|
+
embedded2.update_attributes!(name: 'a new name')
|
59
|
+
|
60
|
+
model.history_tracks[-1].undo! user
|
61
|
+
expect(embedded1.reload.name).to eq('e1name')
|
62
|
+
expect(embedded2.reload.name).to eq('e2name')
|
63
|
+
end
|
64
|
+
end
|
@@ -1,124 +1,124 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Mongoid::History::Tracker do
|
4
|
-
describe 'Tracking of changes from embedded documents' do
|
5
|
-
before :each do
|
6
|
-
# Child model (will be embedded in Parent)
|
7
|
-
class Child
|
8
|
-
include Mongoid::Document
|
9
|
-
include Mongoid::History::Trackable
|
10
|
-
|
11
|
-
field :name
|
12
|
-
embedded_in :parent, inverse_of: :child
|
13
|
-
embeds_one :child, inverse_of: :parent, class_name: 'NestedChild'
|
14
|
-
end
|
15
|
-
|
16
|
-
# NestedChild model (will be embedded in Child)
|
17
|
-
class NestedChild
|
18
|
-
include Mongoid::Document
|
19
|
-
include Mongoid::History::Trackable
|
20
|
-
|
21
|
-
field :name
|
22
|
-
embedded_in :parent, inverse_of: :child, class_name: 'Child'
|
23
|
-
end
|
24
|
-
|
25
|
-
# Parent model (embeds one Child)
|
26
|
-
class Parent
|
27
|
-
include Mongoid::Document
|
28
|
-
include Mongoid::History::Trackable
|
29
|
-
|
30
|
-
field :name, type: String
|
31
|
-
embeds_one :child
|
32
|
-
|
33
|
-
store_in collection: :parent
|
34
|
-
|
35
|
-
track_history(
|
36
|
-
on: %i[fields embedded_relations],
|
37
|
-
version_field: :version,
|
38
|
-
track_create: true,
|
39
|
-
track_update: true,
|
40
|
-
track_destroy: false,
|
41
|
-
modifier_field: nil
|
42
|
-
)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
after :each do
|
47
|
-
Object.send(:remove_const, :Parent)
|
48
|
-
Object.send(:remove_const, :Child)
|
49
|
-
Object.send(:remove_const, :NestedChild)
|
50
|
-
end
|
51
|
-
|
52
|
-
context 'with a parent-child hierarchy' do
|
53
|
-
let(:parent) do
|
54
|
-
Parent.create!(name: 'bowser', child: Child.new(name: 'todd'))
|
55
|
-
end
|
56
|
-
|
57
|
-
it 'tracks history for the nested embedded documents in the parent' do
|
58
|
-
expect(parent.history_tracks.length).to eq(1)
|
59
|
-
|
60
|
-
aggregate_failures do
|
61
|
-
track = parent.history_tracks.last
|
62
|
-
expect(track.modified['name']).to eq('bowser')
|
63
|
-
expect(track.modified.dig('child', 'name')).to eq('todd')
|
64
|
-
end
|
65
|
-
|
66
|
-
parent.update_attributes(name: 'brow')
|
67
|
-
expect(parent.history_tracks.length).to eq(2)
|
68
|
-
|
69
|
-
parent.child.name = 'mario'
|
70
|
-
parent.save!
|
71
|
-
expect(parent.history_tracks.length).to eq(3)
|
72
|
-
|
73
|
-
aggregate_failures do
|
74
|
-
track = parent.history_tracks.last
|
75
|
-
expect(track.original.dig('child', 'name')).to eq('todd')
|
76
|
-
expect(track.modified.dig('child', 'name')).to eq('mario')
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
context 'with a deeply nested hierarchy' do
|
82
|
-
let(:parent) do
|
83
|
-
Parent.create!(
|
84
|
-
name: 'bowser',
|
85
|
-
child: Child.new(
|
86
|
-
name: 'todd',
|
87
|
-
child: NestedChild.new(name: 'peach')
|
88
|
-
)
|
89
|
-
)
|
90
|
-
end
|
91
|
-
|
92
|
-
it 'tracks history for deeply nested embedded documents in parent' do
|
93
|
-
pending('Figure out a way to track deeply nested relation changes')
|
94
|
-
|
95
|
-
expect(parent.history_tracks.length).to eq(1)
|
96
|
-
|
97
|
-
aggregate_failures do
|
98
|
-
track = parent.history_tracks.last
|
99
|
-
expect(track.modified['name']).to eq('bowser')
|
100
|
-
expect(track.modified.dig('child', 'name')).to eq('todd')
|
101
|
-
expect(track.modified.dig('child', 'child', 'name')).to eq('peach')
|
102
|
-
end
|
103
|
-
|
104
|
-
parent.name = 'brow'
|
105
|
-
parent.child.name = 'mario'
|
106
|
-
parent.child.child.name = 'luigi'
|
107
|
-
parent.save!
|
108
|
-
expect(parent.history_tracks.length).to eq(2)
|
109
|
-
|
110
|
-
aggregate_failures do
|
111
|
-
track = parent.history_tracks.last
|
112
|
-
expect(track.original['name']).to eq('bowser')
|
113
|
-
expect(track.modified['name']).to eq('brow')
|
114
|
-
|
115
|
-
expect(track.original['child']['name']).to eq('todd')
|
116
|
-
expect(track.modified['child']['name']).to eq('mario')
|
117
|
-
|
118
|
-
expect(track.original['child']['child']['name']).to eq('peach')
|
119
|
-
expect(track.modified['child']['child']['name']).to eq('luigi')
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|
123
|
-
end
|
124
|
-
end
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Mongoid::History::Tracker do
|
4
|
+
describe 'Tracking of changes from embedded documents' do
|
5
|
+
before :each do
|
6
|
+
# Child model (will be embedded in Parent)
|
7
|
+
class Child
|
8
|
+
include Mongoid::Document
|
9
|
+
include Mongoid::History::Trackable
|
10
|
+
|
11
|
+
field :name
|
12
|
+
embedded_in :parent, inverse_of: :child
|
13
|
+
embeds_one :child, inverse_of: :parent, class_name: 'NestedChild'
|
14
|
+
end
|
15
|
+
|
16
|
+
# NestedChild model (will be embedded in Child)
|
17
|
+
class NestedChild
|
18
|
+
include Mongoid::Document
|
19
|
+
include Mongoid::History::Trackable
|
20
|
+
|
21
|
+
field :name
|
22
|
+
embedded_in :parent, inverse_of: :child, class_name: 'Child'
|
23
|
+
end
|
24
|
+
|
25
|
+
# Parent model (embeds one Child)
|
26
|
+
class Parent
|
27
|
+
include Mongoid::Document
|
28
|
+
include Mongoid::History::Trackable
|
29
|
+
|
30
|
+
field :name, type: String
|
31
|
+
embeds_one :child
|
32
|
+
|
33
|
+
store_in collection: :parent
|
34
|
+
|
35
|
+
track_history(
|
36
|
+
on: %i[fields embedded_relations],
|
37
|
+
version_field: :version,
|
38
|
+
track_create: true,
|
39
|
+
track_update: true,
|
40
|
+
track_destroy: false,
|
41
|
+
modifier_field: nil
|
42
|
+
)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
after :each do
|
47
|
+
Object.send(:remove_const, :Parent)
|
48
|
+
Object.send(:remove_const, :Child)
|
49
|
+
Object.send(:remove_const, :NestedChild)
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'with a parent-child hierarchy' do
|
53
|
+
let(:parent) do
|
54
|
+
Parent.create!(name: 'bowser', child: Child.new(name: 'todd'))
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'tracks history for the nested embedded documents in the parent' do
|
58
|
+
expect(parent.history_tracks.length).to eq(1)
|
59
|
+
|
60
|
+
aggregate_failures do
|
61
|
+
track = parent.history_tracks.last
|
62
|
+
expect(track.modified['name']).to eq('bowser')
|
63
|
+
expect(track.modified.dig('child', 'name')).to eq('todd')
|
64
|
+
end
|
65
|
+
|
66
|
+
parent.update_attributes(name: 'brow')
|
67
|
+
expect(parent.history_tracks.length).to eq(2)
|
68
|
+
|
69
|
+
parent.child.name = 'mario'
|
70
|
+
parent.save!
|
71
|
+
expect(parent.history_tracks.length).to eq(3)
|
72
|
+
|
73
|
+
aggregate_failures do
|
74
|
+
track = parent.history_tracks.last
|
75
|
+
expect(track.original.dig('child', 'name')).to eq('todd')
|
76
|
+
expect(track.modified.dig('child', 'name')).to eq('mario')
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
context 'with a deeply nested hierarchy' do
|
82
|
+
let(:parent) do
|
83
|
+
Parent.create!(
|
84
|
+
name: 'bowser',
|
85
|
+
child: Child.new(
|
86
|
+
name: 'todd',
|
87
|
+
child: NestedChild.new(name: 'peach')
|
88
|
+
)
|
89
|
+
)
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'tracks history for deeply nested embedded documents in parent' do
|
93
|
+
pending('Figure out a way to track deeply nested relation changes')
|
94
|
+
|
95
|
+
expect(parent.history_tracks.length).to eq(1)
|
96
|
+
|
97
|
+
aggregate_failures do
|
98
|
+
track = parent.history_tracks.last
|
99
|
+
expect(track.modified['name']).to eq('bowser')
|
100
|
+
expect(track.modified.dig('child', 'name')).to eq('todd')
|
101
|
+
expect(track.modified.dig('child', 'child', 'name')).to eq('peach')
|
102
|
+
end
|
103
|
+
|
104
|
+
parent.name = 'brow'
|
105
|
+
parent.child.name = 'mario'
|
106
|
+
parent.child.child.name = 'luigi'
|
107
|
+
parent.save!
|
108
|
+
expect(parent.history_tracks.length).to eq(2)
|
109
|
+
|
110
|
+
aggregate_failures do
|
111
|
+
track = parent.history_tracks.last
|
112
|
+
expect(track.original['name']).to eq('bowser')
|
113
|
+
expect(track.modified['name']).to eq('brow')
|
114
|
+
|
115
|
+
expect(track.original['child']['name']).to eq('todd')
|
116
|
+
expect(track.modified['child']['name']).to eq('mario')
|
117
|
+
|
118
|
+
expect(track.original['child']['child']['name']).to eq('peach')
|
119
|
+
expect(track.modified['child']['child']['name']).to eq('luigi')
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|