mongoid-history 0.8.1 → 0.8.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.rubocop_todo.yml +26 -25
- data/.travis.yml +1 -1
- data/CHANGELOG.md +7 -0
- data/LICENSE.txt +1 -1
- data/README.md +1 -1
- data/lib/mongoid/history.rb +11 -2
- data/lib/mongoid/history/attributes/update.rb +72 -13
- data/lib/mongoid/history/options.rb +11 -3
- data/lib/mongoid/history/trackable.rb +39 -8
- data/lib/mongoid/history/version.rb +1 -1
- data/spec/integration/integration_spec.rb +22 -0
- data/spec/integration/nested_embedded_documents_tracked_in_parent_spec.rb +124 -0
- data/spec/support/mongoid_history.rb +0 -1
- data/spec/unit/history_spec.rb +21 -0
- data/spec/unit/options_spec.rb +9 -0
- data/spec/unit/trackable_spec.rb +60 -8
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 84ee622b782d764b3a15ea31bfac94cbedf3fa023d8ae0302022562d6a5a6ec2
|
4
|
+
data.tar.gz: abf09c6ed9db7126b9d7754f42a0f1b00317919ad6744f0486b4d970601eb3f4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 484eb94fae5bba8b787ffda61403e65c95684f9e3a77c03daa56952e056c440d639d58d3a381760e7996ec1bec1415fe409f6688fab38ed24d6e0315f53c9369
|
7
|
+
data.tar.gz: f66b6abc4dcf17696bafea67faddbcd0b97f194e8b8b36c48f32461a31987b9867a6dbf204a8604a391654ebace4c94c76b4b745ac2511b74db8df26f886d54a
|
data/.rubocop_todo.yml
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# This configuration was generated by
|
2
2
|
# `rubocop --auto-gen-config`
|
3
|
-
# on
|
3
|
+
# on 2019-06-09 13:41:12 +0200 using RuboCop version 0.60.0.
|
4
4
|
# The point is for the user to remove these configuration records
|
5
5
|
# one by one as the offenses are removed from the code base.
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
@@ -8,16 +8,16 @@
|
|
8
8
|
|
9
9
|
# Offense count: 7
|
10
10
|
# Configuration parameters: Include.
|
11
|
-
# Include: **/Gemfile, **/gems.rb
|
11
|
+
# Include: **/*.gemfile, **/Gemfile, **/gems.rb
|
12
12
|
Bundler/DuplicatedGem:
|
13
13
|
Exclude:
|
14
14
|
- 'Gemfile'
|
15
15
|
|
16
16
|
# Offense count: 1
|
17
17
|
# Cop supports --auto-correct.
|
18
|
-
# Configuration parameters: EnforcedStyleAlignWith,
|
18
|
+
# Configuration parameters: EnforcedStyleAlignWith, AutoCorrect, Severity.
|
19
19
|
# SupportedStylesAlignWith: keyword, variable, start_of_line
|
20
|
-
|
20
|
+
Layout/EndAlignment:
|
21
21
|
Exclude:
|
22
22
|
- 'lib/mongoid/history/options.rb'
|
23
23
|
|
@@ -32,44 +32,47 @@ Lint/ParenthesesAsGroupedExpression:
|
|
32
32
|
- 'spec/integration/integration_spec.rb'
|
33
33
|
- 'spec/integration/nested_embedded_polymorphic_documents_spec.rb'
|
34
34
|
|
35
|
-
# Offense count:
|
35
|
+
# Offense count: 22
|
36
36
|
Metrics/AbcSize:
|
37
37
|
Max: 52
|
38
38
|
|
39
|
-
# Offense count:
|
39
|
+
# Offense count: 122
|
40
40
|
# Configuration parameters: CountComments, ExcludedMethods.
|
41
|
+
# ExcludedMethods: refine
|
41
42
|
Metrics/BlockLength:
|
42
|
-
Max:
|
43
|
+
Max: 837
|
43
44
|
|
44
45
|
# Offense count: 1
|
45
46
|
# Configuration parameters: CountComments.
|
46
47
|
Metrics/ClassLength:
|
47
|
-
Max:
|
48
|
+
Max: 125
|
48
49
|
|
49
50
|
# Offense count: 6
|
50
51
|
Metrics/CyclomaticComplexity:
|
51
52
|
Max: 13
|
52
53
|
|
53
|
-
# Offense count:
|
54
|
-
# Configuration parameters:
|
55
|
-
# URISchemes: http, https
|
56
|
-
Metrics/LineLength:
|
57
|
-
Max: 688
|
58
|
-
|
59
|
-
# Offense count: 15
|
60
|
-
# Configuration parameters: CountComments.
|
54
|
+
# Offense count: 17
|
55
|
+
# Configuration parameters: CountComments, ExcludedMethods.
|
61
56
|
Metrics/MethodLength:
|
62
57
|
Max: 23
|
63
58
|
|
64
59
|
# Offense count: 2
|
65
60
|
# Configuration parameters: CountComments.
|
66
61
|
Metrics/ModuleLength:
|
67
|
-
Max:
|
62
|
+
Max: 191
|
68
63
|
|
69
64
|
# Offense count: 6
|
70
65
|
Metrics/PerceivedComplexity:
|
71
66
|
Max: 15
|
72
67
|
|
68
|
+
# Offense count: 1
|
69
|
+
# Configuration parameters: ExpectMatchingDefinition, Regex, IgnoreExecutableScripts, AllowedAcronyms.
|
70
|
+
# AllowedAcronyms: CLI, DSL, ACL, API, ASCII, CPU, CSS, DNS, EOF, GUID, HTML, HTTP, HTTPS, ID, IP, JSON, LHS, QPS, RAM, RHS, RPC, SLA, SMTP, SQL, SSH, TCP, TLS, TTL, UDP, UI, UID, UUID, URI, URL, UTF8, VM, XML, XMPP, XSRF, XSS
|
71
|
+
Naming/FileName:
|
72
|
+
Exclude:
|
73
|
+
- 'Dangerfile'
|
74
|
+
- 'lib/mongoid-history.rb'
|
75
|
+
|
73
76
|
# Offense count: 12
|
74
77
|
Style/Documentation:
|
75
78
|
Exclude:
|
@@ -91,15 +94,13 @@ Style/EachWithObject:
|
|
91
94
|
- 'lib/mongoid/history/trackable.rb'
|
92
95
|
- 'lib/mongoid/history/tracker.rb'
|
93
96
|
|
94
|
-
# Offense count: 2
|
95
|
-
# Configuration parameters: ExpectMatchingDefinition, Regex, IgnoreExecutableScripts, AllowedAcronyms.
|
96
|
-
# AllowedAcronyms: CLI, DSL, ACL, API, ASCII, CPU, CSS, DNS, EOF, GUID, HTML, HTTP, HTTPS, ID, IP, JSON, LHS, QPS, RAM, RHS, RPC, SLA, SMTP, SQL, SSH, TCP, TLS, TTL, UDP, UI, UID, UUID, URI, URL, UTF8, VM, XML, XMPP, XSRF, XSS
|
97
|
-
Style/FileName:
|
98
|
-
Exclude:
|
99
|
-
- 'Dangerfile'
|
100
|
-
- 'lib/mongoid-history.rb'
|
101
|
-
|
102
97
|
# Offense count: 1
|
103
98
|
Style/MultilineBlockChain:
|
104
99
|
Exclude:
|
105
100
|
- 'lib/mongoid/history/tracker.rb'
|
101
|
+
|
102
|
+
# Offense count: 404
|
103
|
+
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
|
104
|
+
# URISchemes: http, https
|
105
|
+
Metrics/LineLength:
|
106
|
+
Max: 688
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
### 0.8.2 (2019/12/02)
|
2
|
+
|
3
|
+
* [#233](https://github.com/mongoid/mongoid-history/pull/233): Bug fix-Track ALL embedded relations when used with fields and filtered attributes on embedded objects - [@jagdeepsingh](https://github.com/jagdeepsingh).
|
4
|
+
* [#232](https://github.com/mongoid/mongoid-history/pull/232): Bug/187 track changes from embedded documents (not deeply nested) - [@Startouf](https://github.com/Startouf).
|
5
|
+
* [#227](https://github.com/mongoid/mongoid-history/pull/227): Store options in inheritable class attributes - [@jnfeinstein](https://github.com/jnfeinstein).
|
6
|
+
* [#229](https://github.com/mongoid/mongoid-history/pull/229), [#225](https://github.com/mongoid/mongoid-history/pull/225): Fixed inheritance of `history_trackable_options` - [@jnfeinstein](https://github.com/jnfeinstein).
|
7
|
+
|
1
8
|
### 0.8.1 (2018/06/28)
|
2
9
|
|
3
10
|
* [#221](https://github.com/mongoid/mongoid-history/pull/221): Mongoid 7 support - [@dblock](https://github.com/dblock).
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -580,6 +580,6 @@ You're encouraged to contribute to this library. See [CONTRIBUTING](CONTRIBUTING
|
|
580
580
|
Copyright
|
581
581
|
---------
|
582
582
|
|
583
|
-
Copyright (c) 2011-
|
583
|
+
Copyright (c) 2011-2018 Aaron Qian and Contributors.
|
584
584
|
|
585
585
|
MIT License. See [LICENSE.txt](LICENSE.txt) for further details.
|
data/lib/mongoid/history.rb
CHANGED
@@ -15,7 +15,6 @@ module Mongoid
|
|
15
15
|
|
16
16
|
class << self
|
17
17
|
attr_accessor :tracker_class_name
|
18
|
-
attr_accessor :trackable_class_options
|
19
18
|
attr_accessor :trackable_settings
|
20
19
|
attr_accessor :modifier_class_name
|
21
20
|
attr_accessor :current_user_method
|
@@ -45,9 +44,19 @@ module Mongoid
|
|
45
44
|
|
46
45
|
def reset!
|
47
46
|
Mongoid::History.modifier_class_name = 'User'
|
48
|
-
Mongoid::History.trackable_class_options = {}
|
49
47
|
Mongoid::History.trackable_settings = {}
|
50
48
|
Mongoid::History.current_user_method ||= :current_user
|
49
|
+
|
50
|
+
Mongoid.models.each do |model|
|
51
|
+
next unless model.included_modules.include? Mongoid::History::Trackable
|
52
|
+
|
53
|
+
model.singleton_class.class_eval do
|
54
|
+
# Inverse of class_attribute
|
55
|
+
%i[mongoid_history_options
|
56
|
+
mongoid_history_options=
|
57
|
+
mongoid_history_options?].each { |m| remove_possible_method(m) }
|
58
|
+
end
|
59
|
+
end
|
51
60
|
end
|
52
61
|
end
|
53
62
|
end
|
@@ -2,33 +2,91 @@ module Mongoid
|
|
2
2
|
module History
|
3
3
|
module Attributes
|
4
4
|
class Update < ::Mongoid::History::Attributes::Base
|
5
|
+
# @example when both an attribute `foo` and a child's attribute `nested_bar.baz` are changed
|
6
|
+
#
|
7
|
+
# {
|
8
|
+
# 'foo' => ['foo_before_changes', 'foo_after_changes']
|
9
|
+
# 'nested_bar.baz' => ['nested_bar_baz_before_changes', 'nested_bar_baz_after_changes']
|
10
|
+
# }
|
11
|
+
# }
|
12
|
+
#
|
13
|
+
# @return [Hash<String, Array<(?,?)>>] Hash of changes
|
5
14
|
def attributes
|
6
|
-
|
15
|
+
changes_from_parent.deep_merge(changes_from_children)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def changes_from_parent
|
21
|
+
parent_changes = {}
|
7
22
|
changes.each do |k, v|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
23
|
+
change_value = begin
|
24
|
+
if trackable_class.tracked_embeds_one?(k)
|
25
|
+
embeds_one_changes_from_parent(k, v)
|
26
|
+
elsif trackable_class.tracked_embeds_many?(k)
|
27
|
+
embeds_many_changes_from_parent(k, v)
|
28
|
+
elsif trackable_class.tracked?(k, :update)
|
29
|
+
{ k => format_field(k, v) } unless v.all?(&:blank?)
|
30
|
+
end
|
14
31
|
end
|
32
|
+
parent_changes.merge!(change_value) if change_value.present?
|
15
33
|
end
|
16
|
-
|
34
|
+
parent_changes
|
17
35
|
end
|
18
36
|
|
19
|
-
|
37
|
+
def changes_from_children
|
38
|
+
embeds_one_changes_from_embedded_documents
|
39
|
+
end
|
40
|
+
|
41
|
+
# Retrieve the list of changes applied directly to the nested documents
|
42
|
+
#
|
43
|
+
# @example when a child's name is changed from "todd" to "mario"
|
44
|
+
#
|
45
|
+
# child = Child.new(name: 'todd')
|
46
|
+
# Parent.create(child: child)
|
47
|
+
# child.name = "Mario"
|
48
|
+
#
|
49
|
+
# embeds_one_changes_from_embedded_documents # when called from "Parent"
|
50
|
+
# # => { "child.name"=>["todd", "mario"] }
|
51
|
+
#
|
52
|
+
# @return [Hash<String, Array<(?,?)>] changes of embeds_ones from embedded documents
|
53
|
+
def embeds_one_changes_from_embedded_documents
|
54
|
+
embedded_doc_changes = {}
|
55
|
+
trackable_class.tracked_embeds_one.each do |rel|
|
56
|
+
rel_class = trackable_class.relation_class_of(rel)
|
57
|
+
paranoia_field = Mongoid::History.trackable_class_settings(rel_class)[:paranoia_field]
|
58
|
+
paranoia_field = rel_class.aliased_fields.key(paranoia_field) || paranoia_field
|
59
|
+
rel = aliased_fields.key(rel) || rel
|
60
|
+
obj = trackable.send(rel)
|
61
|
+
next if !obj || (obj.respond_to?(paranoia_field) && obj.public_send(paranoia_field).present?)
|
20
62
|
|
21
|
-
|
63
|
+
obj.changes.each do |k, v|
|
64
|
+
embedded_doc_changes["#{rel}.#{k}"] = [v.first, v.last]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
embedded_doc_changes
|
68
|
+
end
|
69
|
+
|
70
|
+
# @param [String] relation
|
71
|
+
# @param [String] value
|
72
|
+
#
|
73
|
+
# @return [Hash<String, Array<(?,?)>>]
|
74
|
+
def embeds_one_changes_from_parent(relation, value)
|
22
75
|
relation = trackable_class.database_field_name(relation)
|
23
76
|
relation_class = trackable_class.relation_class_of(relation)
|
24
77
|
paranoia_field = Mongoid::History.trackable_class_settings(relation_class)[:paranoia_field]
|
25
78
|
original_value = value[0][paranoia_field].present? ? {} : format_embeds_one_relation(relation, value[0])
|
26
79
|
modified_value = value[1][paranoia_field].present? ? {} : format_embeds_one_relation(relation, value[1])
|
27
80
|
return if original_value == modified_value
|
28
|
-
|
81
|
+
|
82
|
+
{ relation => [original_value, modified_value] }
|
29
83
|
end
|
30
84
|
|
31
|
-
|
85
|
+
# @param [String] relation
|
86
|
+
# @param [String] value
|
87
|
+
#
|
88
|
+
# @return [Hash<Array<(?,?)>>]
|
89
|
+
def embeds_many_changes_from_parent(relation, value)
|
32
90
|
relation = trackable_class.database_field_name(relation)
|
33
91
|
relation_class = trackable_class.relation_class_of(relation)
|
34
92
|
paranoia_field = Mongoid::History.trackable_class_settings(relation_class)[:paranoia_field]
|
@@ -37,7 +95,8 @@ module Mongoid
|
|
37
95
|
modified_value = value[1].reject { |rel| rel[paranoia_field].present? }
|
38
96
|
.map { |v_attrs| format_embeds_many_relation(relation, v_attrs) }
|
39
97
|
return if original_value == modified_value
|
40
|
-
|
98
|
+
|
99
|
+
{ relation => [original_value, modified_value] }
|
41
100
|
end
|
42
101
|
end
|
43
102
|
end
|
@@ -95,12 +95,20 @@ module Mongoid
|
|
95
95
|
@options[:relations] = { embeds_one: {}, embeds_many: {} }
|
96
96
|
|
97
97
|
options[:on].each do |option|
|
98
|
-
|
99
|
-
|
100
|
-
|
98
|
+
if option.is_a?(Hash)
|
99
|
+
option.each { |k, v| split_and_categorize(k => v) }
|
100
|
+
else
|
101
|
+
split_and_categorize(option)
|
102
|
+
end
|
101
103
|
end
|
102
104
|
end
|
103
105
|
|
106
|
+
def split_and_categorize(field_and_options)
|
107
|
+
field = get_database_field_name(field_and_options)
|
108
|
+
field_options = get_field_options(field_and_options)
|
109
|
+
categorize_tracked_option(field, field_options)
|
110
|
+
end
|
111
|
+
|
104
112
|
# Returns the database_field_name key for tracked option
|
105
113
|
#
|
106
114
|
# @param [ String | Symbol | Array | Hash ] option The field or relation name to track
|
@@ -29,8 +29,11 @@ module Mongoid
|
|
29
29
|
around_create :track_create, callback_options if history_options.options[:track_create]
|
30
30
|
around_destroy :track_destroy, callback_options if history_options.options[:track_destroy]
|
31
31
|
|
32
|
-
|
33
|
-
|
32
|
+
unless respond_to? :mongoid_history_options
|
33
|
+
class_attribute :mongoid_history_options, instance_accessor: false
|
34
|
+
end
|
35
|
+
|
36
|
+
self.mongoid_history_options = history_options
|
34
37
|
end
|
35
38
|
|
36
39
|
def history_settings(options = {})
|
@@ -260,18 +263,43 @@ module Mongoid
|
|
260
263
|
@history_tracks = nil
|
261
264
|
end
|
262
265
|
|
266
|
+
# Transform hash of pair of changes into an `original` and `modified` hash
|
267
|
+
# Nested document keys (key name with dots) are expanded
|
268
|
+
#
|
269
|
+
# @param [Hash<Array>] changes
|
270
|
+
#
|
271
|
+
# @return [Array<Hash<?>,Hash<?>>] <description>
|
263
272
|
def transform_changes(changes)
|
264
273
|
original = {}
|
265
274
|
modified = {}
|
266
|
-
changes.each_pair do |k,
|
267
|
-
o, m =
|
268
|
-
original
|
269
|
-
modified
|
275
|
+
changes.each_pair do |k, modification_pair|
|
276
|
+
o, m = modification_pair
|
277
|
+
original.deep_merge!(expand_nested_document_key_value(k, o)) unless o.nil?
|
278
|
+
modified.deep_merge!(expand_nested_document_key_value(k, m)) unless m.nil?
|
270
279
|
end
|
271
280
|
|
272
281
|
[original, modified]
|
273
282
|
end
|
274
283
|
|
284
|
+
# Handle nested document tracking of changes
|
285
|
+
#
|
286
|
+
# @example
|
287
|
+
#
|
288
|
+
# expand_nested_document_key('embedded.document.changed_field', 'old'])
|
289
|
+
# #=> { 'embedded' => {'document' => { 'changed_field' => 'old' }}}
|
290
|
+
#
|
291
|
+
# @param [String] document_key key with dots
|
292
|
+
# @param [?] value
|
293
|
+
#
|
294
|
+
# @return [Hash<String, ?>]
|
295
|
+
def expand_nested_document_key_value(document_key, value)
|
296
|
+
expanded_key = value
|
297
|
+
document_key.to_s.split('.').reverse.each do |key|
|
298
|
+
expanded_key = { key => expanded_key }
|
299
|
+
end
|
300
|
+
expanded_key
|
301
|
+
end
|
302
|
+
|
275
303
|
def increment_current_version
|
276
304
|
current_version = (send(history_trackable_options[:version_field]) || 0) + 1
|
277
305
|
send("#{history_trackable_options[:version_field]}=", current_version)
|
@@ -287,7 +315,10 @@ module Mongoid
|
|
287
315
|
def track_history_for_action(action)
|
288
316
|
if track_history_for_action?(action)
|
289
317
|
current_version = increment_current_version
|
290
|
-
last_track = self.class.tracker_class.create!(
|
318
|
+
last_track = self.class.tracker_class.create!(
|
319
|
+
history_tracker_attributes(action.to_sym)
|
320
|
+
.merge(version: current_version, action: action.to_s, trackable: self)
|
321
|
+
)
|
291
322
|
end
|
292
323
|
|
293
324
|
clear_trackable_memoization
|
@@ -518,7 +549,7 @@ module Mongoid
|
|
518
549
|
end
|
519
550
|
|
520
551
|
def history_trackable_options
|
521
|
-
@history_trackable_options ||=
|
552
|
+
@history_trackable_options ||= mongoid_history_options.prepared
|
522
553
|
end
|
523
554
|
|
524
555
|
def clear_trackable_memoization
|
@@ -950,5 +950,27 @@ describe Mongoid::History do
|
|
950
950
|
expect(sausage.reload.flavour).to eq('Guinness')
|
951
951
|
end
|
952
952
|
end
|
953
|
+
|
954
|
+
describe 'changing collection' do
|
955
|
+
before :each do
|
956
|
+
class Fish
|
957
|
+
include Mongoid::Document
|
958
|
+
include Mongoid::History::Trackable
|
959
|
+
|
960
|
+
track_history on: [:species], modifier_field_optional: true
|
961
|
+
store_in collection: :animals
|
962
|
+
|
963
|
+
field :species
|
964
|
+
end
|
965
|
+
end
|
966
|
+
|
967
|
+
after :each do
|
968
|
+
Object.send(:remove_const, :Fish)
|
969
|
+
end
|
970
|
+
|
971
|
+
it 'should track history' do
|
972
|
+
Fish.new.save!
|
973
|
+
end
|
974
|
+
end
|
953
975
|
end
|
954
976
|
end
|
@@ -0,0 +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
|
data/spec/unit/history_spec.rb
CHANGED
@@ -34,4 +34,25 @@ describe Mongoid::History do
|
|
34
34
|
it { expect(described_class.trackable_class_settings(ModelOne)).to eq(paranoia_field: 'deleted_at') }
|
35
35
|
end
|
36
36
|
end
|
37
|
+
|
38
|
+
describe '#reset!' do
|
39
|
+
before :each do
|
40
|
+
class ModelTwo
|
41
|
+
include Mongoid::Document
|
42
|
+
include Mongoid::History::Trackable
|
43
|
+
|
44
|
+
track_history
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
after :each do
|
49
|
+
Object.send(:remove_const, :ModelTwo)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should remove all configurations' do
|
53
|
+
expect(ModelTwo).to have_attributes mongoid_history_options: be_a(Mongoid::History::Options)
|
54
|
+
Mongoid::History.reset!
|
55
|
+
expect(ModelTwo).to_not respond_to :mongoid_history_options
|
56
|
+
end
|
57
|
+
end
|
37
58
|
end
|
data/spec/unit/options_spec.rb
CHANGED
@@ -275,6 +275,15 @@ describe Mongoid::History::Options do
|
|
275
275
|
it { expect(subject[:relations][:embeds_many]).to eq('emb_threes' => %w[_id fmb]) }
|
276
276
|
end
|
277
277
|
|
278
|
+
context 'with fields, and multiple embeds_one, and embeds_many relations' do
|
279
|
+
let(:options) { { on: [:foo, :bar, :emb_two, { emb_threes: %i[f_em_foo f_em_bar], emb_fours: :f_em_baz }] } }
|
280
|
+
it 'should categorize fields and associations correctly' do
|
281
|
+
expect(subject[:fields]).to eq(%w[foo b])
|
282
|
+
expect(subject[:relations][:embeds_one]).to eq('emtw' => %w[_id f_em_baz])
|
283
|
+
expect(subject[:relations][:embeds_many]).to eq('emb_threes' => %w[_id f_em_foo fmb], 'emfs' => %w[_id f_em_baz])
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
278
287
|
context 'with field alias' do
|
279
288
|
let(:options) { { on: :bar } }
|
280
289
|
it { expect(subject[:fields]).to eq %w[b] }
|
data/spec/unit/trackable_spec.rb
CHANGED
@@ -37,12 +37,6 @@ describe Mongoid::History::Trackable do
|
|
37
37
|
expect(MyModel).to respond_to :track_history
|
38
38
|
end
|
39
39
|
|
40
|
-
it 'should append trackable_class_options ONLY when #track_history is called' do
|
41
|
-
expect(Mongoid::History.trackable_class_options).to be_blank
|
42
|
-
MyModel.track_history
|
43
|
-
expect(Mongoid::History.trackable_class_options.keys).to eq([:my_model])
|
44
|
-
end
|
45
|
-
|
46
40
|
describe '#track_history' do
|
47
41
|
before :each do
|
48
42
|
class MyModelWithNoModifier
|
@@ -85,7 +79,7 @@ describe Mongoid::History::Trackable do
|
|
85
79
|
let(:reserved_fields) { %w[_id version modifier_id] }
|
86
80
|
|
87
81
|
it 'should have default options' do
|
88
|
-
expect(
|
82
|
+
expect(MyModel.mongoid_history_options.prepared).to eq(expected_option)
|
89
83
|
end
|
90
84
|
|
91
85
|
it 'should define callback function #track_update' do
|
@@ -266,7 +260,7 @@ describe Mongoid::History::Trackable do
|
|
266
260
|
end
|
267
261
|
|
268
262
|
it 'should have default options' do
|
269
|
-
expect(
|
263
|
+
expect(MyModel.mongoid_history_options.prepared).to eq(expected_option)
|
270
264
|
end
|
271
265
|
|
272
266
|
it 'should define #history_trackable_options' do
|
@@ -784,4 +778,62 @@ describe Mongoid::History::Trackable do
|
|
784
778
|
end.to change(Tracker, :count).by(0)
|
785
779
|
end
|
786
780
|
end
|
781
|
+
|
782
|
+
context 'changing collection' do
|
783
|
+
before :each do
|
784
|
+
class Fish
|
785
|
+
include Mongoid::Document
|
786
|
+
include Mongoid::History::Trackable
|
787
|
+
|
788
|
+
track_history on: [:species], modifier_field_optional: true
|
789
|
+
store_in collection: :animals
|
790
|
+
|
791
|
+
field :species
|
792
|
+
end
|
793
|
+
end
|
794
|
+
|
795
|
+
after :each do
|
796
|
+
Object.send(:remove_const, :Fish)
|
797
|
+
end
|
798
|
+
|
799
|
+
it 'should track history' do
|
800
|
+
expect do
|
801
|
+
expect { Fish.new.save! }.to_not raise_error
|
802
|
+
end.to change(Tracker, :count).by(1)
|
803
|
+
end
|
804
|
+
end
|
805
|
+
|
806
|
+
context "extending a #{described_class}" do
|
807
|
+
before :each do
|
808
|
+
MyModel.track_history
|
809
|
+
|
810
|
+
class CustomTracker < MyModel
|
811
|
+
field :key
|
812
|
+
|
813
|
+
track_history on: :key, changes_method: :my_changes, track_create: true
|
814
|
+
|
815
|
+
def my_changes
|
816
|
+
changes.merge('key' => "Save history-#{key}")
|
817
|
+
end
|
818
|
+
end
|
819
|
+
|
820
|
+
MyModel.history_trackable_options
|
821
|
+
end
|
822
|
+
|
823
|
+
after :each do
|
824
|
+
Object.send(:remove_const, :CustomTracker)
|
825
|
+
end
|
826
|
+
|
827
|
+
it 'should not override in parent class' do
|
828
|
+
expect(MyModel.history_trackable_options[:changes_method]).to eq :changes
|
829
|
+
expect(CustomTracker.history_trackable_options[:changes_method]).to eq :my_changes
|
830
|
+
end
|
831
|
+
|
832
|
+
it 'should default to :changes' do
|
833
|
+
m = MyModel.create!(modifier: user)
|
834
|
+
expect(m).to receive(:changes).exactly(3).times.and_call_original
|
835
|
+
expect(m).not_to receive(:my_changes)
|
836
|
+
m.save!
|
837
|
+
end
|
838
|
+
end
|
787
839
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongoid-history
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aaron Qian
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2019-12-02 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: easy_diff
|
@@ -117,6 +117,7 @@ files:
|
|
117
117
|
- spec/integration/multi_relation_spec.rb
|
118
118
|
- spec/integration/multiple_trackers_spec.rb
|
119
119
|
- spec/integration/nested_embedded_documents_spec.rb
|
120
|
+
- spec/integration/nested_embedded_documents_tracked_in_parent_spec.rb
|
120
121
|
- spec/integration/nested_embedded_polymorphic_documents_spec.rb
|
121
122
|
- spec/integration/subclasses_spec.rb
|
122
123
|
- spec/integration/track_history_order_spec.rb
|
@@ -157,8 +158,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
157
158
|
- !ruby/object:Gem::Version
|
158
159
|
version: '0'
|
159
160
|
requirements: []
|
160
|
-
|
161
|
-
rubygems_version: 2.6.13
|
161
|
+
rubygems_version: 3.0.3
|
162
162
|
signing_key:
|
163
163
|
specification_version: 4
|
164
164
|
summary: Track and audit, undo and redo changes on Mongoid documents.
|
@@ -168,6 +168,7 @@ test_files:
|
|
168
168
|
- spec/integration/multi_relation_spec.rb
|
169
169
|
- spec/integration/multiple_trackers_spec.rb
|
170
170
|
- spec/integration/nested_embedded_documents_spec.rb
|
171
|
+
- spec/integration/nested_embedded_documents_tracked_in_parent_spec.rb
|
171
172
|
- spec/integration/nested_embedded_polymorphic_documents_spec.rb
|
172
173
|
- spec/integration/subclasses_spec.rb
|
173
174
|
- spec/integration/track_history_order_spec.rb
|