mongoid-history 0.8.2 → 0.8.3
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 +21 -28
- data/CHANGELOG.md +8 -0
- data/Gemfile +1 -0
- data/README.md +25 -2
- data/lib/mongoid/history.rb +14 -2
- data/lib/mongoid/history/attributes/create.rb +2 -7
- data/lib/mongoid/history/options.rb +43 -44
- data/lib/mongoid/history/trackable.rb +22 -6
- data/lib/mongoid/history/version.rb +1 -1
- data/perf/benchmark_modified_attributes_for_create.rb +65 -0
- data/perf/gc_suite.rb +21 -0
- data/spec/integration/subclasses_spec.rb +8 -2
- data/spec/unit/options_spec.rb +6 -0
- data/spec/unit/trackable_spec.rb +154 -6
- metadata +5 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7f7558f1c6033e5350cdeb3732e385d483c7abfa71ffc7f89acfbba22befff97
|
|
4
|
+
data.tar.gz: 71c5f5ab67e1bd040e14b040211b1acc5532449f048919c83adcb4e875f7eac4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f528411205ca81444296803927b54c1bd1ef570611b2b4a9bb79f6e4165fb038c5b13ad5fb79c8adde96c62eaefa1142bf5f4c6b5f44d72a80743f38a0aa5d48
|
|
7
|
+
data.tar.gz: 4149122d3f6c474f5f0105772fa64a9fe237d299005e97ad021e887f42687d1a81ede778c589070231319704b9c71e2f99a5e660d04c2581a078178e965b0425
|
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 2020-04-10 17:25:32 -0500 using RuboCop version 0.48.1.
|
|
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,19 +8,11 @@
|
|
|
8
8
|
|
|
9
9
|
# Offense count: 7
|
|
10
10
|
# Configuration parameters: Include.
|
|
11
|
-
# Include:
|
|
11
|
+
# Include: **/Gemfile, **/gems.rb
|
|
12
12
|
Bundler/DuplicatedGem:
|
|
13
13
|
Exclude:
|
|
14
14
|
- 'Gemfile'
|
|
15
15
|
|
|
16
|
-
# Offense count: 1
|
|
17
|
-
# Cop supports --auto-correct.
|
|
18
|
-
# Configuration parameters: EnforcedStyleAlignWith, AutoCorrect, Severity.
|
|
19
|
-
# SupportedStylesAlignWith: keyword, variable, start_of_line
|
|
20
|
-
Layout/EndAlignment:
|
|
21
|
-
Exclude:
|
|
22
|
-
- 'lib/mongoid/history/options.rb'
|
|
23
|
-
|
|
24
16
|
# Offense count: 3
|
|
25
17
|
Lint/HandleExceptions:
|
|
26
18
|
Exclude:
|
|
@@ -38,21 +30,26 @@ Metrics/AbcSize:
|
|
|
38
30
|
|
|
39
31
|
# Offense count: 122
|
|
40
32
|
# Configuration parameters: CountComments, ExcludedMethods.
|
|
41
|
-
# ExcludedMethods: refine
|
|
42
33
|
Metrics/BlockLength:
|
|
43
34
|
Max: 837
|
|
44
35
|
|
|
45
36
|
# Offense count: 1
|
|
46
37
|
# Configuration parameters: CountComments.
|
|
47
38
|
Metrics/ClassLength:
|
|
48
|
-
Max:
|
|
39
|
+
Max: 120
|
|
49
40
|
|
|
50
41
|
# Offense count: 6
|
|
51
42
|
Metrics/CyclomaticComplexity:
|
|
52
43
|
Max: 13
|
|
53
44
|
|
|
45
|
+
# Offense count: 412
|
|
46
|
+
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
|
|
47
|
+
# URISchemes: http, https
|
|
48
|
+
Metrics/LineLength:
|
|
49
|
+
Max: 688
|
|
50
|
+
|
|
54
51
|
# Offense count: 17
|
|
55
|
-
# Configuration parameters: CountComments
|
|
52
|
+
# Configuration parameters: CountComments.
|
|
56
53
|
Metrics/MethodLength:
|
|
57
54
|
Max: 23
|
|
58
55
|
|
|
@@ -65,15 +62,7 @@ Metrics/ModuleLength:
|
|
|
65
62
|
Metrics/PerceivedComplexity:
|
|
66
63
|
Max: 15
|
|
67
64
|
|
|
68
|
-
# Offense count:
|
|
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
|
-
|
|
76
|
-
# Offense count: 12
|
|
65
|
+
# Offense count: 15
|
|
77
66
|
Style/Documentation:
|
|
78
67
|
Exclude:
|
|
79
68
|
- 'spec/**/*'
|
|
@@ -86,6 +75,8 @@ Style/Documentation:
|
|
|
86
75
|
- 'lib/mongoid/history/options.rb'
|
|
87
76
|
- 'lib/mongoid/history/trackable.rb'
|
|
88
77
|
- 'lib/mongoid/history/tracker.rb'
|
|
78
|
+
- 'perf/benchmark_modified_attributes_for_create.rb'
|
|
79
|
+
- 'perf/gc_suite.rb'
|
|
89
80
|
|
|
90
81
|
# Offense count: 3
|
|
91
82
|
# Cop supports --auto-correct.
|
|
@@ -94,13 +85,15 @@ Style/EachWithObject:
|
|
|
94
85
|
- 'lib/mongoid/history/trackable.rb'
|
|
95
86
|
- 'lib/mongoid/history/tracker.rb'
|
|
96
87
|
|
|
88
|
+
# Offense count: 2
|
|
89
|
+
# Configuration parameters: ExpectMatchingDefinition, Regex, IgnoreExecutableScripts, AllowedAcronyms.
|
|
90
|
+
# 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
|
|
91
|
+
Style/FileName:
|
|
92
|
+
Exclude:
|
|
93
|
+
- 'Dangerfile'
|
|
94
|
+
- 'lib/mongoid-history.rb'
|
|
95
|
+
|
|
97
96
|
# Offense count: 1
|
|
98
97
|
Style/MultilineBlockChain:
|
|
99
98
|
Exclude:
|
|
100
99
|
- '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/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
### 0.8.3 (2020/05/17)
|
|
2
|
+
|
|
3
|
+
* [#236](https://github.com/mongoid/mongoid-history/pull/236): Fix Ruby 2.7 keyword argument warnings - [@vasilysn](https://github.com/vasilysn).
|
|
4
|
+
* [#237](https://github.com/mongoid/mongoid-history/pull/237): Fix tracking subclasses with additional fields - [@getaroom](https://github.com/getaroom).
|
|
5
|
+
* [#239](https://github.com/mongoid/mongoid-history/pull/239): Optimize `modified_attributes_for_create` 6-7x - [@getaroom](https://github.com/getaroom).
|
|
6
|
+
* [#240](https://github.com/mongoid/mongoid-history/pull/240): `Mongoid::History.disable` and `disable_tracking` now restore the original state - [@getaroom](https://github.com/getaroom).
|
|
7
|
+
* [#240](https://github.com/mongoid/mongoid-history/pull/240): Added `Mongoid::History.enable`, `Mongoid::History.enable!`, `Mongoid::History.disable!`, `enable_tracking`, `enable_tracking!`, and `disable_tracking!` - [@getaroom](https://github.com/getaroom).
|
|
8
|
+
|
|
1
9
|
### 0.8.2 (2019/12/02)
|
|
2
10
|
|
|
3
11
|
* [#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).
|
data/Gemfile
CHANGED
data/README.md
CHANGED
|
@@ -149,11 +149,34 @@ Comment.disable_tracking do
|
|
|
149
149
|
comment.update_attributes(:title => "Test 3")
|
|
150
150
|
end
|
|
151
151
|
|
|
152
|
-
#
|
|
152
|
+
# disable tracking for comments by default
|
|
153
|
+
Comment.disable_tracking!
|
|
154
|
+
|
|
155
|
+
# enable tracking for comments within a block
|
|
156
|
+
Comment.enable_tracking do
|
|
157
|
+
comment.update_attributes(:title => "Test 3")
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# renable tracking for comments by default
|
|
161
|
+
Comment.enable_tracking!
|
|
162
|
+
|
|
163
|
+
# globally disable all history tracking within a block
|
|
153
164
|
Mongoid::History.disable do
|
|
154
165
|
comment.update_attributes(:title => "Test 3")
|
|
155
166
|
user.update_attributes(:name => "Eddie Van Halen")
|
|
156
167
|
end
|
|
168
|
+
|
|
169
|
+
# globally disable all history tracking by default
|
|
170
|
+
Mongoid::History.disable!
|
|
171
|
+
|
|
172
|
+
# globally enable all history tracking within a block
|
|
173
|
+
Mongoid::History.enable do
|
|
174
|
+
comment.update_attributes(:title => "Test 3")
|
|
175
|
+
user.update_attributes(:name => "Eddie Van Halen")
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
# globally renable all history tracking by default
|
|
179
|
+
Mongoid::History.enable!
|
|
157
180
|
```
|
|
158
181
|
|
|
159
182
|
You may want to track changes on all fields.
|
|
@@ -516,7 +539,7 @@ For more examples, check out [spec/integration/integration_spec.rb](spec/integra
|
|
|
516
539
|
|
|
517
540
|
You can have different trackers for different classes like so.
|
|
518
541
|
|
|
519
|
-
```
|
|
542
|
+
``` ruby
|
|
520
543
|
class First
|
|
521
544
|
include Mongoid::Document
|
|
522
545
|
include Mongoid::History::Trackable
|
data/lib/mongoid/history.rb
CHANGED
|
@@ -19,13 +19,25 @@ module Mongoid
|
|
|
19
19
|
attr_accessor :modifier_class_name
|
|
20
20
|
attr_accessor :current_user_method
|
|
21
21
|
|
|
22
|
-
def disable
|
|
22
|
+
def disable
|
|
23
|
+
original_flag = store[GLOBAL_TRACK_HISTORY_FLAG]
|
|
23
24
|
store[GLOBAL_TRACK_HISTORY_FLAG] = false
|
|
24
|
-
yield
|
|
25
|
+
yield if block_given?
|
|
25
26
|
ensure
|
|
27
|
+
store[GLOBAL_TRACK_HISTORY_FLAG] = original_flag if block_given?
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def enable
|
|
31
|
+
original_flag = store[GLOBAL_TRACK_HISTORY_FLAG]
|
|
26
32
|
store[GLOBAL_TRACK_HISTORY_FLAG] = true
|
|
33
|
+
yield if block_given?
|
|
34
|
+
ensure
|
|
35
|
+
store[GLOBAL_TRACK_HISTORY_FLAG] = original_flag if block_given?
|
|
27
36
|
end
|
|
28
37
|
|
|
38
|
+
alias disable! disable
|
|
39
|
+
alias enable! enable
|
|
40
|
+
|
|
29
41
|
def enabled?
|
|
30
42
|
store[GLOBAL_TRACK_HISTORY_FLAG] != false
|
|
31
43
|
end
|
|
@@ -4,14 +4,9 @@ module Mongoid
|
|
|
4
4
|
class Create < ::Mongoid::History::Attributes::Base
|
|
5
5
|
def attributes
|
|
6
6
|
@attributes = {}
|
|
7
|
-
|
|
7
|
+
changes.each do |k, v|
|
|
8
8
|
next unless trackable_class.tracked_field?(k, :create)
|
|
9
|
-
|
|
10
|
-
changes[k].class == Array ? changes[k].last : changes[k]
|
|
11
|
-
else
|
|
12
|
-
v
|
|
13
|
-
end
|
|
14
|
-
@attributes[k] = [nil, format_field(k, modified)]
|
|
9
|
+
@attributes[k] = format_field(k, v)
|
|
15
10
|
end
|
|
16
11
|
insert_embeds_one_changes
|
|
17
12
|
insert_embeds_many_changes
|
|
@@ -13,29 +13,28 @@ module Mongoid
|
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def prepared
|
|
16
|
-
@prepared
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
16
|
+
return @prepared if @prepared
|
|
17
|
+
@prepared = options.dup
|
|
18
|
+
prepare_skipped_fields
|
|
19
|
+
prepare_formatted_fields
|
|
20
|
+
parse_tracked_fields_and_relations
|
|
21
|
+
@prepared
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
private
|
|
25
25
|
|
|
26
26
|
def default_options
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
format: nil }
|
|
27
|
+
{ on: :all,
|
|
28
|
+
except: %i[created_at updated_at],
|
|
29
|
+
tracker_class_name: nil,
|
|
30
|
+
modifier_field: :modifier,
|
|
31
|
+
version_field: :version,
|
|
32
|
+
changes_method: :changes,
|
|
33
|
+
scope: scope,
|
|
34
|
+
track_create: true,
|
|
35
|
+
track_update: true,
|
|
36
|
+
track_destroy: true,
|
|
37
|
+
format: nil }
|
|
39
38
|
end
|
|
40
39
|
|
|
41
40
|
# Sets the :except attributes and relations in `options` to be an [ Array <String> ]
|
|
@@ -43,15 +42,15 @@ module Mongoid
|
|
|
43
42
|
# Removes the `nil` and duplicate entries from skipped attributes/relations list
|
|
44
43
|
def prepare_skipped_fields
|
|
45
44
|
# normalize :except fields to an array of database field strings
|
|
46
|
-
@
|
|
47
|
-
@
|
|
45
|
+
@prepared[:except] = Array(@prepared[:except])
|
|
46
|
+
@prepared[:except] = @prepared[:except].map { |field| trackable.database_field_name(field) }.compact.uniq
|
|
48
47
|
end
|
|
49
48
|
|
|
50
49
|
def prepare_formatted_fields
|
|
51
50
|
formats = {}
|
|
52
51
|
|
|
53
|
-
if
|
|
54
|
-
|
|
52
|
+
if @prepared[:format].class == Hash
|
|
53
|
+
@prepared[:format].each do |field, format|
|
|
55
54
|
next if field.nil?
|
|
56
55
|
|
|
57
56
|
field = trackable.database_field_name(field)
|
|
@@ -68,7 +67,7 @@ module Mongoid
|
|
|
68
67
|
end
|
|
69
68
|
end
|
|
70
69
|
|
|
71
|
-
|
|
70
|
+
@prepared[:format] = formats
|
|
72
71
|
end
|
|
73
72
|
|
|
74
73
|
def parse_tracked_fields_and_relations
|
|
@@ -76,25 +75,25 @@ module Mongoid
|
|
|
76
75
|
# when `posts: [:id, :title]`, then it will convert it to `[[:posts, [:id, :title]]]`
|
|
77
76
|
# when `:foo`, then `[:foo]`
|
|
78
77
|
# when `[:foo, { posts: [:id, :title] }]`, then return as is
|
|
79
|
-
@
|
|
78
|
+
@prepared[:on] = Array(@prepared[:on])
|
|
80
79
|
|
|
81
|
-
@
|
|
80
|
+
@prepared[:on] = @prepared[:on].map { |opt| opt == :all ? :fields : opt }
|
|
82
81
|
|
|
83
|
-
if
|
|
84
|
-
@
|
|
85
|
-
@
|
|
82
|
+
if @prepared[:on].include?(:fields)
|
|
83
|
+
@prepared[:on] = @prepared[:on].reject { |opt| opt == :fields }
|
|
84
|
+
@prepared[:on] = @prepared[:on] | trackable.fields.keys.map(&:to_sym) - reserved_fields.map(&:to_sym)
|
|
86
85
|
end
|
|
87
86
|
|
|
88
|
-
if
|
|
89
|
-
@
|
|
90
|
-
@
|
|
87
|
+
if @prepared[:on].include?(:embedded_relations)
|
|
88
|
+
@prepared[:on] = @prepared[:on].reject { |opt| opt == :embedded_relations }
|
|
89
|
+
@prepared[:on] = @prepared[:on] | trackable.embedded_relations.keys
|
|
91
90
|
end
|
|
92
91
|
|
|
93
|
-
@
|
|
94
|
-
@
|
|
95
|
-
@
|
|
92
|
+
@prepared[:fields] = []
|
|
93
|
+
@prepared[:dynamic] = []
|
|
94
|
+
@prepared[:relations] = { embeds_one: {}, embeds_many: {} }
|
|
96
95
|
|
|
97
|
-
|
|
96
|
+
@prepared[:on].each do |option|
|
|
98
97
|
if option.is_a?(Hash)
|
|
99
98
|
option.each { |k, v| split_and_categorize(k => v) }
|
|
100
99
|
else
|
|
@@ -145,7 +144,7 @@ module Mongoid
|
|
|
145
144
|
# @param [ String ] field The database field name of field or relation to track
|
|
146
145
|
# @param [ nil | Array <String | Symbol> ] field_options The tracked fields for embedded relations
|
|
147
146
|
def categorize_tracked_option(field, field_options = nil)
|
|
148
|
-
return if
|
|
147
|
+
return if @prepared[:except].include?(field)
|
|
149
148
|
return if reserved_fields.include?(field)
|
|
150
149
|
|
|
151
150
|
field_options = Array(field_options)
|
|
@@ -155,23 +154,23 @@ module Mongoid
|
|
|
155
154
|
elsif trackable.embeds_many?(field)
|
|
156
155
|
track_relation(field, :embeds_many, field_options)
|
|
157
156
|
elsif trackable.fields.keys.include?(field)
|
|
158
|
-
@
|
|
157
|
+
@prepared[:fields] << field
|
|
159
158
|
else
|
|
160
|
-
@
|
|
159
|
+
@prepared[:dynamic] << field
|
|
161
160
|
end
|
|
162
161
|
end
|
|
163
162
|
|
|
164
163
|
def track_relation(field, kind, field_options)
|
|
165
164
|
relation_class = trackable.relation_class_of(field)
|
|
166
|
-
@
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
165
|
+
@prepared[:relations][kind][field] = if field_options.blank?
|
|
166
|
+
relation_class.fields.keys
|
|
167
|
+
else
|
|
168
|
+
%w[_id] | field_options.map { |opt| relation_class.database_field_name(opt) }
|
|
169
|
+
end
|
|
171
170
|
end
|
|
172
171
|
|
|
173
172
|
def reserved_fields
|
|
174
|
-
@reserved_fields ||= ['_id', '_type',
|
|
173
|
+
@reserved_fields ||= ['_id', '_type', @prepared[:version_field].to_s, "#{@prepared[:modifier_field]}_id"]
|
|
175
174
|
end
|
|
176
175
|
end
|
|
177
176
|
end
|
|
@@ -25,9 +25,9 @@ module Mongoid
|
|
|
25
25
|
delegate :track_history?, to: 'self.class'
|
|
26
26
|
|
|
27
27
|
callback_options = history_options.options.slice(:if, :unless)
|
|
28
|
-
around_update :track_update, callback_options if history_options.options[:track_update]
|
|
29
|
-
around_create :track_create, callback_options if history_options.options[:track_create]
|
|
30
|
-
around_destroy :track_destroy, callback_options if history_options.options[:track_destroy]
|
|
28
|
+
around_update :track_update, **callback_options if history_options.options[:track_update]
|
|
29
|
+
around_create :track_create, **callback_options if history_options.options[:track_create]
|
|
30
|
+
around_destroy :track_destroy, **callback_options if history_options.options[:track_destroy]
|
|
31
31
|
|
|
32
32
|
unless respond_to? :mongoid_history_options
|
|
33
33
|
class_attribute :mongoid_history_options, instance_accessor: false
|
|
@@ -52,13 +52,25 @@ module Mongoid
|
|
|
52
52
|
Mongoid::Compatibility::Version.mongoid3? || (self < Mongoid::Attributes::Dynamic).present?
|
|
53
53
|
end
|
|
54
54
|
|
|
55
|
-
def disable_tracking
|
|
55
|
+
def disable_tracking
|
|
56
|
+
original_flag = Mongoid::History.store[track_history_flag]
|
|
56
57
|
Mongoid::History.store[track_history_flag] = false
|
|
57
|
-
yield
|
|
58
|
+
yield if block_given?
|
|
58
59
|
ensure
|
|
60
|
+
Mongoid::History.store[track_history_flag] = original_flag if block_given?
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def enable_tracking
|
|
64
|
+
original_flag = Mongoid::History.store[track_history_flag]
|
|
59
65
|
Mongoid::History.store[track_history_flag] = true
|
|
66
|
+
yield if block_given?
|
|
67
|
+
ensure
|
|
68
|
+
Mongoid::History.store[track_history_flag] = original_flag if block_given?
|
|
60
69
|
end
|
|
61
70
|
|
|
71
|
+
alias disable_tracking! disable_tracking
|
|
72
|
+
alias enable_tracking! enable_tracking
|
|
73
|
+
|
|
62
74
|
def track_history_flag
|
|
63
75
|
"mongoid_history_#{name.underscore}_trackable_enabled".to_sym
|
|
64
76
|
end
|
|
@@ -559,7 +571,11 @@ module Mongoid
|
|
|
559
571
|
@tracked_fields = nil
|
|
560
572
|
@tracked_embeds_one = nil
|
|
561
573
|
@tracked_embeds_many = nil
|
|
562
|
-
|
|
574
|
+
end
|
|
575
|
+
|
|
576
|
+
def inherited(subclass)
|
|
577
|
+
super
|
|
578
|
+
subclass.mongoid_history_options = Mongoid::History::Options.new(subclass, mongoid_history_options.options)
|
|
563
579
|
end
|
|
564
580
|
end
|
|
565
581
|
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
$LOAD_PATH.push File.expand_path('../../lib', __FILE__)
|
|
2
|
+
|
|
3
|
+
require 'mongoid'
|
|
4
|
+
require 'mongoid/history'
|
|
5
|
+
|
|
6
|
+
require 'benchmark/ips'
|
|
7
|
+
require './perf/gc_suite'
|
|
8
|
+
|
|
9
|
+
Mongoid.connect_to('mongoid_history_perf_test')
|
|
10
|
+
Mongo::Logger.logger.level = ::Logger::FATAL
|
|
11
|
+
Mongoid.purge!
|
|
12
|
+
|
|
13
|
+
Attributes = Mongoid::History::Attributes
|
|
14
|
+
|
|
15
|
+
module ZeroPointEight
|
|
16
|
+
class Create < Attributes::Create
|
|
17
|
+
def attributes
|
|
18
|
+
@attributes = {}
|
|
19
|
+
trackable.attributes.each do |k, v|
|
|
20
|
+
next unless trackable_class.tracked_field?(k, :create)
|
|
21
|
+
modified = if changes[k]
|
|
22
|
+
changes[k].class == Array ? changes[k].last : changes[k]
|
|
23
|
+
else
|
|
24
|
+
v
|
|
25
|
+
end
|
|
26
|
+
@attributes[k] = [nil, format_field(k, modified)]
|
|
27
|
+
end
|
|
28
|
+
insert_embeds_one_changes
|
|
29
|
+
insert_embeds_many_changes
|
|
30
|
+
@attributes
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
class Person
|
|
36
|
+
include Mongoid::Document
|
|
37
|
+
include Mongoid::History::Trackable
|
|
38
|
+
|
|
39
|
+
field :first_name, type: String
|
|
40
|
+
field :last_name, type: String
|
|
41
|
+
field :birth_date, type: Date
|
|
42
|
+
field :title, type: String
|
|
43
|
+
|
|
44
|
+
track_history on: %i[first_name last_name birth_date]
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
new_person = Person.new(first_name: 'Eliot', last_name: 'Horowitz', birth_date: '1981-05-01', title: 'CTO')
|
|
48
|
+
|
|
49
|
+
Benchmark.ips do |bm|
|
|
50
|
+
bm.config(suite: GCSuite.new)
|
|
51
|
+
|
|
52
|
+
bm.report('HEAD') do
|
|
53
|
+
Attributes::Create.new(new_person).attributes
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
bm.report('v0.8.2') do
|
|
57
|
+
ZeroPointEight::Create.new(new_person).attributes
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
bm.report('v0.5.0') do
|
|
61
|
+
new_person.attributes.each_with_object({}) { |(k, v), h| h[k] = [nil, v] }.select { |k, _| new_person.class.tracked_field?(k, :create) }
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
bm.compare!
|
|
65
|
+
end
|
data/perf/gc_suite.rb
ADDED
|
@@ -7,12 +7,16 @@ describe Mongoid::History::Tracker do
|
|
|
7
7
|
include Mongoid::Timestamps
|
|
8
8
|
include Mongoid::History::Trackable
|
|
9
9
|
|
|
10
|
+
track_history
|
|
11
|
+
|
|
10
12
|
field :body
|
|
11
13
|
|
|
12
|
-
|
|
14
|
+
# force preparation of options
|
|
15
|
+
history_trackable_options
|
|
13
16
|
end
|
|
14
17
|
|
|
15
18
|
class Prompt < Element
|
|
19
|
+
field :head
|
|
16
20
|
end
|
|
17
21
|
|
|
18
22
|
class User
|
|
@@ -31,11 +35,13 @@ describe Mongoid::History::Tracker do
|
|
|
31
35
|
it 'tracks subclass create and update' do
|
|
32
36
|
prompt = Prompt.new(modifier: user)
|
|
33
37
|
expect { prompt.save! }.to change(Tracker, :count).by(1)
|
|
34
|
-
expect { prompt.update_attributes!(body: 'one') }.to change(Tracker, :count).by(1)
|
|
38
|
+
expect { prompt.update_attributes!(body: 'one', head: 'two') }.to change(Tracker, :count).by(1)
|
|
35
39
|
prompt.undo! user
|
|
36
40
|
expect(prompt.body).to be_blank
|
|
41
|
+
expect(prompt.head).to be_blank
|
|
37
42
|
prompt.redo! user, 2
|
|
38
43
|
expect(prompt.body).to eq('one')
|
|
44
|
+
expect(prompt.head).to eq('two')
|
|
39
45
|
expect { prompt.destroy }.to change(Tracker, :count).by(1)
|
|
40
46
|
end
|
|
41
47
|
end
|
data/spec/unit/options_spec.rb
CHANGED
|
@@ -84,6 +84,12 @@ describe Mongoid::History::Options do
|
|
|
84
84
|
end
|
|
85
85
|
|
|
86
86
|
describe '#parse' do
|
|
87
|
+
it 'does not mutate the original options' do
|
|
88
|
+
original_options = service.options.dup
|
|
89
|
+
service.prepared
|
|
90
|
+
expect(service.options).to eq original_options
|
|
91
|
+
end
|
|
92
|
+
|
|
87
93
|
describe '#default_options' do
|
|
88
94
|
let(:expected_options) do
|
|
89
95
|
{
|
data/spec/unit/trackable_spec.rb
CHANGED
|
@@ -270,6 +270,11 @@ describe Mongoid::History::Trackable do
|
|
|
270
270
|
|
|
271
271
|
describe '#track_history?' do
|
|
272
272
|
shared_examples_for 'history tracking' do
|
|
273
|
+
after do
|
|
274
|
+
Mongoid::History.store[Mongoid::History::GLOBAL_TRACK_HISTORY_FLAG] = true
|
|
275
|
+
Mongoid::History.store[MyModel.track_history_flag] = true
|
|
276
|
+
end
|
|
277
|
+
|
|
273
278
|
context 'when tracking is globally enabled' do
|
|
274
279
|
it 'should be enabled on the current thread' do
|
|
275
280
|
expect(Mongoid::History.enabled?).to eq(true)
|
|
@@ -283,7 +288,40 @@ describe Mongoid::History::Trackable do
|
|
|
283
288
|
end
|
|
284
289
|
end
|
|
285
290
|
|
|
286
|
-
it 'should be
|
|
291
|
+
it 'should be enabled within enable_tracking' do
|
|
292
|
+
MyModel.disable_tracking do
|
|
293
|
+
MyModel.enable_tracking do
|
|
294
|
+
expect(Mongoid::History.enabled?).to eq(true)
|
|
295
|
+
expect(MyModel.new.track_history?).to eq(true)
|
|
296
|
+
end
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
it 'should still be disabled after completing a nested disable_tracking' do
|
|
301
|
+
MyModel.disable_tracking do
|
|
302
|
+
MyModel.disable_tracking {}
|
|
303
|
+
expect(Mongoid::History.enabled?).to eq(true)
|
|
304
|
+
expect(MyModel.new.track_history?).to eq(false)
|
|
305
|
+
end
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
it 'should still be enabled after completing a nested enable_tracking' do
|
|
309
|
+
MyModel.enable_tracking do
|
|
310
|
+
MyModel.enable_tracking {}
|
|
311
|
+
expect(Mongoid::History.enabled?).to eq(true)
|
|
312
|
+
expect(MyModel.new.track_history?).to eq(true)
|
|
313
|
+
end
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
it 'should restore the original state after completing enable_tracking' do
|
|
317
|
+
MyModel.disable_tracking do
|
|
318
|
+
MyModel.enable_tracking {}
|
|
319
|
+
expect(Mongoid::History.enabled?).to eq(true)
|
|
320
|
+
expect(MyModel.new.track_history?).to eq(false)
|
|
321
|
+
end
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
it 'should be rescued if an exception occurs in disable_tracking' do
|
|
287
325
|
begin
|
|
288
326
|
MyModel.disable_tracking do
|
|
289
327
|
raise 'exception'
|
|
@@ -294,6 +332,33 @@ describe Mongoid::History::Trackable do
|
|
|
294
332
|
expect(MyModel.new.track_history?).to eq(true)
|
|
295
333
|
end
|
|
296
334
|
|
|
335
|
+
it 'should be rescued if an exception occurs in enable_tracking' do
|
|
336
|
+
MyModel.disable_tracking do
|
|
337
|
+
begin
|
|
338
|
+
MyModel.enable_tracking do
|
|
339
|
+
raise 'exception'
|
|
340
|
+
end
|
|
341
|
+
rescue
|
|
342
|
+
end
|
|
343
|
+
expect(Mongoid::History.enabled?).to eq(true)
|
|
344
|
+
expect(MyModel.new.track_history?).to eq(false)
|
|
345
|
+
end
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
it 'should stay disabled if disable_tracking called without a block' do
|
|
349
|
+
MyModel.disable_tracking!
|
|
350
|
+
expect(Mongoid::History.enabled?).to eq(true)
|
|
351
|
+
expect(MyModel.new.track_history?).to eq(false)
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
it 'should stay enabled if enable_tracking called without a block' do
|
|
355
|
+
MyModel.disable_tracking do
|
|
356
|
+
MyModel.enable_tracking!
|
|
357
|
+
expect(Mongoid::History.enabled?).to eq(true)
|
|
358
|
+
expect(MyModel.new.track_history?).to eq(true)
|
|
359
|
+
end
|
|
360
|
+
end
|
|
361
|
+
|
|
297
362
|
context 'with multiple classes' do
|
|
298
363
|
before :each do
|
|
299
364
|
class MyModel2
|
|
@@ -317,7 +382,7 @@ describe Mongoid::History::Trackable do
|
|
|
317
382
|
end
|
|
318
383
|
end
|
|
319
384
|
|
|
320
|
-
context 'when
|
|
385
|
+
context 'when changing global tracking' do
|
|
321
386
|
it 'should be disabled by the global disablement' do
|
|
322
387
|
Mongoid::History.disable do
|
|
323
388
|
expect(Mongoid::History.enabled?).to eq(false)
|
|
@@ -325,6 +390,41 @@ describe Mongoid::History::Trackable do
|
|
|
325
390
|
end
|
|
326
391
|
end
|
|
327
392
|
|
|
393
|
+
it 'should be enabled by the global enablement' do
|
|
394
|
+
Mongoid::History.disable do
|
|
395
|
+
Mongoid::History.enable do
|
|
396
|
+
expect(Mongoid::History.enabled?).to eq(true)
|
|
397
|
+
expect(MyModel.new.track_history?).to eq(true)
|
|
398
|
+
end
|
|
399
|
+
end
|
|
400
|
+
end
|
|
401
|
+
|
|
402
|
+
it 'should restore the original state after completing enable' do
|
|
403
|
+
Mongoid::History.disable do
|
|
404
|
+
Mongoid::History.enable {}
|
|
405
|
+
expect(Mongoid::History.enabled?).to eq(false)
|
|
406
|
+
expect(MyModel.new.track_history?).to eq(false)
|
|
407
|
+
end
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
it 'should still be disabled after completing a nested disable' do
|
|
411
|
+
Mongoid::History.disable do
|
|
412
|
+
Mongoid::History.disable {}
|
|
413
|
+
expect(Mongoid::History.enabled?).to eq(false)
|
|
414
|
+
expect(MyModel.new.track_history?).to eq(false)
|
|
415
|
+
end
|
|
416
|
+
end
|
|
417
|
+
|
|
418
|
+
it 'should still be enabled after completing a nested enable' do
|
|
419
|
+
Mongoid::History.disable do
|
|
420
|
+
Mongoid::History.enable do
|
|
421
|
+
Mongoid::History.enable {}
|
|
422
|
+
expect(Mongoid::History.enabled?).to eq(true)
|
|
423
|
+
expect(MyModel.new.track_history?).to eq(true)
|
|
424
|
+
end
|
|
425
|
+
end
|
|
426
|
+
end
|
|
427
|
+
|
|
328
428
|
it 'should be disabled within disable_tracking' do
|
|
329
429
|
Mongoid::History.disable do
|
|
330
430
|
MyModel.disable_tracking do
|
|
@@ -334,7 +434,7 @@ describe Mongoid::History::Trackable do
|
|
|
334
434
|
end
|
|
335
435
|
end
|
|
336
436
|
|
|
337
|
-
it 'should be rescued if an exception occurs' do
|
|
437
|
+
it 'should be rescued if an exception occurs in disable' do
|
|
338
438
|
Mongoid::History.disable do
|
|
339
439
|
begin
|
|
340
440
|
MyModel.disable_tracking do
|
|
@@ -347,6 +447,33 @@ describe Mongoid::History::Trackable do
|
|
|
347
447
|
end
|
|
348
448
|
end
|
|
349
449
|
|
|
450
|
+
it 'should be rescued if an exception occurs in enable' do
|
|
451
|
+
Mongoid::History.disable do
|
|
452
|
+
begin
|
|
453
|
+
Mongoid::History.enable do
|
|
454
|
+
raise 'exception'
|
|
455
|
+
end
|
|
456
|
+
rescue
|
|
457
|
+
end
|
|
458
|
+
expect(Mongoid::History.enabled?).to eq(false)
|
|
459
|
+
expect(MyModel.new.track_history?).to eq(false)
|
|
460
|
+
end
|
|
461
|
+
end
|
|
462
|
+
|
|
463
|
+
it 'should stay disabled if disable called without a block' do
|
|
464
|
+
Mongoid::History.disable!
|
|
465
|
+
expect(Mongoid::History.enabled?).to eq(false)
|
|
466
|
+
expect(MyModel.new.track_history?).to eq(false)
|
|
467
|
+
end
|
|
468
|
+
|
|
469
|
+
it 'should stay enabled if enable called without a block' do
|
|
470
|
+
Mongoid::History.disable do
|
|
471
|
+
Mongoid::History.enable!
|
|
472
|
+
expect(Mongoid::History.enabled?).to eq(true)
|
|
473
|
+
expect(MyModel.new.track_history?).to eq(true)
|
|
474
|
+
end
|
|
475
|
+
end
|
|
476
|
+
|
|
350
477
|
context 'with multiple classes' do
|
|
351
478
|
before :each do
|
|
352
479
|
class MyModel2
|
|
@@ -361,7 +488,7 @@ describe Mongoid::History::Trackable do
|
|
|
361
488
|
Object.send(:remove_const, :MyModel2)
|
|
362
489
|
end
|
|
363
490
|
|
|
364
|
-
it 'should be disabled
|
|
491
|
+
it 'should be disabled for all classes' do
|
|
365
492
|
Mongoid::History.disable do
|
|
366
493
|
MyModel.disable_tracking do
|
|
367
494
|
expect(Mongoid::History.enabled?).to eq(false)
|
|
@@ -412,7 +539,7 @@ describe Mongoid::History::Trackable do
|
|
|
412
539
|
track_history on: :key, changes_method: :my_changes, track_create: true
|
|
413
540
|
|
|
414
541
|
def my_changes
|
|
415
|
-
changes.merge('key' => "Save history-#{key}")
|
|
542
|
+
changes.merge('key' => ["Save history-#{key}", "Save history-#{key}"])
|
|
416
543
|
end
|
|
417
544
|
end
|
|
418
545
|
end
|
|
@@ -813,7 +940,7 @@ describe Mongoid::History::Trackable do
|
|
|
813
940
|
track_history on: :key, changes_method: :my_changes, track_create: true
|
|
814
941
|
|
|
815
942
|
def my_changes
|
|
816
|
-
changes.merge('key' => "Save history-#{key}")
|
|
943
|
+
changes.merge('key' => ["Save history-#{key}", "Save history-#{key}"])
|
|
817
944
|
end
|
|
818
945
|
end
|
|
819
946
|
|
|
@@ -836,4 +963,25 @@ describe Mongoid::History::Trackable do
|
|
|
836
963
|
m.save!
|
|
837
964
|
end
|
|
838
965
|
end
|
|
966
|
+
|
|
967
|
+
context "subclassing a #{described_class}" do
|
|
968
|
+
before :each do
|
|
969
|
+
MyModel.track_history(track_destroy: false)
|
|
970
|
+
|
|
971
|
+
class MySubclassModel < MyModel
|
|
972
|
+
end
|
|
973
|
+
end
|
|
974
|
+
|
|
975
|
+
after :each do
|
|
976
|
+
Object.send(:remove_const, :MySubclassModel)
|
|
977
|
+
end
|
|
978
|
+
|
|
979
|
+
describe '.inherited' do
|
|
980
|
+
it 'creates new history options for the subclass' do
|
|
981
|
+
options = MySubclassModel.mongoid_history_options
|
|
982
|
+
expect(options.trackable).to eq MySubclassModel
|
|
983
|
+
expect(options.options).to eq MyModel.mongoid_history_options.options
|
|
984
|
+
end
|
|
985
|
+
end
|
|
986
|
+
end
|
|
839
987
|
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.3
|
|
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: 2020-06-17 00:00:00.000000000 Z
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
16
16
|
name: easy_diff
|
|
@@ -112,6 +112,8 @@ files:
|
|
|
112
112
|
- lib/mongoid/history/tracker.rb
|
|
113
113
|
- lib/mongoid/history/version.rb
|
|
114
114
|
- mongoid-history.gemspec
|
|
115
|
+
- perf/benchmark_modified_attributes_for_create.rb
|
|
116
|
+
- perf/gc_suite.rb
|
|
115
117
|
- spec/integration/embedded_in_polymorphic_spec.rb
|
|
116
118
|
- spec/integration/integration_spec.rb
|
|
117
119
|
- spec/integration/multi_relation_spec.rb
|
|
@@ -158,7 +160,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
158
160
|
- !ruby/object:Gem::Version
|
|
159
161
|
version: '0'
|
|
160
162
|
requirements: []
|
|
161
|
-
rubygems_version: 3.
|
|
163
|
+
rubygems_version: 3.1.3
|
|
162
164
|
signing_key:
|
|
163
165
|
specification_version: 4
|
|
164
166
|
summary: Track and audit, undo and redo changes on Mongoid documents.
|