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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 84ee622b782d764b3a15ea31bfac94cbedf3fa023d8ae0302022562d6a5a6ec2
4
- data.tar.gz: abf09c6ed9db7126b9d7754f42a0f1b00317919ad6744f0486b4d970601eb3f4
3
+ metadata.gz: 7f7558f1c6033e5350cdeb3732e385d483c7abfa71ffc7f89acfbba22befff97
4
+ data.tar.gz: 71c5f5ab67e1bd040e14b040211b1acc5532449f048919c83adcb4e875f7eac4
5
5
  SHA512:
6
- metadata.gz: 484eb94fae5bba8b787ffda61403e65c95684f9e3a77c03daa56952e056c440d639d58d3a381760e7996ec1bec1415fe409f6688fab38ed24d6e0315f53c9369
7
- data.tar.gz: f66b6abc4dcf17696bafea67faddbcd0b97f194e8b8b36c48f32461a31987b9867a6dbf204a8604a391654ebace4c94c76b4b745ac2511b74db8df26f886d54a
6
+ metadata.gz: f528411205ca81444296803927b54c1bd1ef570611b2b4a9bb79f6e4165fb038c5b13ad5fb79c8adde96c62eaefa1142bf5f4c6b5f44d72a80743f38a0aa5d48
7
+ data.tar.gz: 4149122d3f6c474f5f0105772fa64a9fe237d299005e97ad021e887f42687d1a81ede778c589070231319704b9c71e2f99a5e660d04c2581a078178e965b0425
@@ -1,6 +1,6 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2019-06-09 13:41:12 +0200 using RuboCop version 0.60.0.
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: **/*.gemfile, **/Gemfile, **/gems.rb
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: 125
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, ExcludedMethods.
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: 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
-
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
@@ -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
@@ -29,6 +29,7 @@ group :development, :test do
29
29
  end
30
30
 
31
31
  group :test do
32
+ gem 'benchmark-ips', require: false
32
33
  gem 'coveralls'
33
34
  gem 'gem-release'
34
35
  gem 'mongoid-danger', '~> 0.1.0', require: false
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
- # globally disable all history tracking
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
@@ -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(&_block)
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
- trackable.attributes.each do |k, v|
7
+ changes.each do |k, v|
8
8
  next unless trackable_class.tracked_field?(k, :create)
9
- modified = if changes[k]
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 ||= begin
17
- prepare_skipped_fields
18
- prepare_formatted_fields
19
- parse_tracked_fields_and_relations
20
- options
21
- end
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
- @default_options ||=
28
- { on: :all,
29
- except: %i[created_at updated_at],
30
- tracker_class_name: nil,
31
- modifier_field: :modifier,
32
- version_field: :version,
33
- changes_method: :changes,
34
- scope: scope,
35
- track_create: true,
36
- track_update: true,
37
- track_destroy: true,
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
- @options[:except] = Array(options[:except])
47
- @options[:except] = options[:except].map { |field| trackable.database_field_name(field) }.compact.uniq
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 options[:format].class == Hash
54
- options[:format].each do |field, format|
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
- options[:format] = formats
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
- @options[:on] = Array(options[:on])
78
+ @prepared[:on] = Array(@prepared[:on])
80
79
 
81
- @options[:on] = options[:on].map { |opt| opt == :all ? :fields : opt }
80
+ @prepared[:on] = @prepared[:on].map { |opt| opt == :all ? :fields : opt }
82
81
 
83
- if options[:on].include?(:fields)
84
- @options[:on] = options[:on].reject { |opt| opt == :fields }
85
- @options[:on] = options[:on] | trackable.fields.keys.map(&:to_sym) - reserved_fields.map(&:to_sym)
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 options[:on].include?(:embedded_relations)
89
- @options[:on] = options[:on].reject { |opt| opt == :embedded_relations }
90
- @options[:on] = options[:on] | trackable.embedded_relations.keys
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
- @options[:fields] = []
94
- @options[:dynamic] = []
95
- @options[:relations] = { embeds_one: {}, embeds_many: {} }
92
+ @prepared[:fields] = []
93
+ @prepared[:dynamic] = []
94
+ @prepared[:relations] = { embeds_one: {}, embeds_many: {} }
96
95
 
97
- options[:on].each do |option|
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 options[:except].include?(field)
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
- @options[:fields] << field
157
+ @prepared[:fields] << field
159
158
  else
160
- @options[:dynamic] << field
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
- @options[:relations][kind][field] = if field_options.blank?
167
- relation_class.fields.keys
168
- else
169
- %w[_id] | field_options.map { |opt| relation_class.database_field_name(opt) }
170
- end
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', options[:version_field].to_s, "#{options[:modifier_field]}_id"]
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(&_block)
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
- @obfuscated_fields = nil
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
@@ -1,5 +1,5 @@
1
1
  module Mongoid
2
2
  module History
3
- VERSION = '0.8.2'.freeze
3
+ VERSION = '0.8.3'.freeze
4
4
  end
5
5
  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
@@ -0,0 +1,21 @@
1
+ class GCSuite
2
+ def warming(*)
3
+ run_gc
4
+ end
5
+
6
+ def running(*)
7
+ run_gc
8
+ end
9
+
10
+ def warmup_stats(*); end
11
+
12
+ def add_report(*); end
13
+
14
+ private
15
+
16
+ def run_gc
17
+ GC.enable
18
+ GC.start
19
+ GC.disable
20
+ end
21
+ end
@@ -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
- track_history on: [:body]
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
@@ -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
  {
@@ -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 rescued if an exception occurs' do
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 tracking is globally disabled' do
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 only for the class that calls disable_tracking' do
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.2
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: 2019-12-02 00:00:00.000000000 Z
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.0.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.