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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/.coveralls.yml +1 -1
  3. data/.document +5 -5
  4. data/.github/workflows/test.yml +72 -0
  5. data/.gitignore +46 -46
  6. data/.rspec +2 -2
  7. data/.rubocop.yml +6 -6
  8. data/.rubocop_todo.yml +99 -99
  9. data/CHANGELOG.md +173 -163
  10. data/CONTRIBUTING.md +117 -118
  11. data/Dangerfile +1 -1
  12. data/Gemfile +49 -40
  13. data/LICENSE.txt +20 -20
  14. data/README.md +609 -608
  15. data/RELEASING.md +66 -67
  16. data/Rakefile +24 -24
  17. data/UPGRADING.md +53 -53
  18. data/lib/mongoid/history/attributes/base.rb +72 -72
  19. data/lib/mongoid/history/attributes/create.rb +45 -45
  20. data/lib/mongoid/history/attributes/destroy.rb +34 -34
  21. data/lib/mongoid/history/attributes/update.rb +104 -104
  22. data/lib/mongoid/history/options.rb +177 -177
  23. data/lib/mongoid/history/trackable.rb +588 -583
  24. data/lib/mongoid/history/tracker.rb +247 -247
  25. data/lib/mongoid/history/version.rb +5 -5
  26. data/lib/mongoid/history.rb +77 -77
  27. data/lib/mongoid-history.rb +1 -1
  28. data/mongoid-history.gemspec +25 -25
  29. data/perf/benchmark_modified_attributes_for_create.rb +65 -65
  30. data/perf/gc_suite.rb +21 -21
  31. data/spec/integration/embedded_in_polymorphic_spec.rb +112 -112
  32. data/spec/integration/integration_spec.rb +976 -976
  33. data/spec/integration/multi_relation_spec.rb +47 -47
  34. data/spec/integration/multiple_trackers_spec.rb +68 -68
  35. data/spec/integration/nested_embedded_documents_spec.rb +64 -64
  36. data/spec/integration/nested_embedded_documents_tracked_in_parent_spec.rb +124 -124
  37. data/spec/integration/nested_embedded_polymorphic_documents_spec.rb +115 -115
  38. data/spec/integration/subclasses_spec.rb +47 -47
  39. data/spec/integration/track_history_order_spec.rb +84 -84
  40. data/spec/integration/validation_failure_spec.rb +76 -76
  41. data/spec/spec_helper.rb +32 -30
  42. data/spec/support/error_helpers.rb +7 -0
  43. data/spec/support/mongoid.rb +11 -11
  44. data/spec/support/mongoid_history.rb +12 -12
  45. data/spec/unit/attributes/base_spec.rb +141 -141
  46. data/spec/unit/attributes/create_spec.rb +342 -342
  47. data/spec/unit/attributes/destroy_spec.rb +228 -228
  48. data/spec/unit/attributes/update_spec.rb +342 -342
  49. data/spec/unit/callback_options_spec.rb +165 -165
  50. data/spec/unit/embedded_methods_spec.rb +87 -87
  51. data/spec/unit/history_spec.rb +58 -58
  52. data/spec/unit/my_instance_methods_spec.rb +555 -555
  53. data/spec/unit/options_spec.rb +365 -365
  54. data/spec/unit/singleton_methods_spec.rb +406 -406
  55. data/spec/unit/store/default_store_spec.rb +11 -11
  56. data/spec/unit/store/request_store_spec.rb +13 -13
  57. data/spec/unit/trackable_spec.rb +1057 -987
  58. data/spec/unit/tracker_spec.rb +190 -190
  59. metadata +9 -7
  60. data/.travis.yml +0 -36
@@ -1,247 +1,247 @@
1
- module Mongoid
2
- module History
3
- module Tracker
4
- extend ActiveSupport::Concern
5
-
6
- included do
7
- include Mongoid::Document
8
- include Mongoid::Timestamps
9
- attr_writer :trackable
10
-
11
- field :association_chain, type: Array, default: []
12
- field :modified, type: Hash, default: {}
13
- field :original, type: Hash, default: {}
14
- field :version, type: Integer
15
- field :action, type: String
16
- field :scope, type: String
17
- modifier_options = {
18
- class_name: Mongoid::History.modifier_class_name
19
- }
20
- modifier_options[:optional] = true if Mongoid::Compatibility::Version.mongoid6_or_newer?
21
- belongs_to :modifier, modifier_options
22
-
23
- index(scope: 1)
24
- index(association_chain: 1)
25
-
26
- Mongoid::History.tracker_class_name ||= name.tableize.singularize.to_sym
27
- end
28
-
29
- def undo!(modifier = nil)
30
- if action.to_sym == :destroy
31
- re_create
32
- elsif action.to_sym == :create
33
- re_destroy
34
- elsif Mongoid::Compatibility::Version.mongoid3?
35
- trackable.update_attributes!(undo_attr(modifier), without_protection: true)
36
- else
37
- trackable.update_attributes!(undo_attr(modifier))
38
- end
39
- end
40
-
41
- def redo!(modifier = nil)
42
- if action.to_sym == :destroy
43
- re_destroy
44
- elsif action.to_sym == :create
45
- re_create
46
- elsif Mongoid::Compatibility::Version.mongoid3?
47
- trackable.update_attributes!(redo_attr(modifier), without_protection: true)
48
- else
49
- trackable.update_attributes!(redo_attr(modifier))
50
- end
51
- end
52
-
53
- def undo_attr(modifier)
54
- undo_hash = affected.easy_unmerge(modified)
55
- undo_hash.easy_merge!(original)
56
- modifier_field = trackable.history_trackable_options[:modifier_field]
57
- undo_hash[modifier_field] = modifier if modifier_field
58
- (modified.keys - undo_hash.keys).each do |k|
59
- undo_hash[k] = nil
60
- end
61
- localize_keys(undo_hash)
62
- end
63
-
64
- def redo_attr(modifier)
65
- redo_hash = affected.easy_unmerge(original)
66
- redo_hash.easy_merge!(modified)
67
- modifier_field = trackable.history_trackable_options[:modifier_field]
68
- redo_hash[modifier_field] = modifier if modifier_field
69
- localize_keys(redo_hash)
70
- end
71
-
72
- def trackable_root
73
- @trackable_root ||= trackable_parents_and_trackable.first
74
- end
75
-
76
- def trackable
77
- @trackable ||= trackable_parents_and_trackable.last
78
- end
79
-
80
- def trackable_parents
81
- @trackable_parents ||= trackable_parents_and_trackable[0, -1]
82
- end
83
-
84
- def trackable_parent
85
- @trackable_parent ||= trackable_parents_and_trackable[-2]
86
- end
87
-
88
- # Outputs a :from, :to hash for each affected field. Intentionally excludes fields
89
- # which are not tracked, even if there are tracked values for such fields
90
- # present in the database.
91
- #
92
- # @return [ HashWithIndifferentAccess ] a change set in the format:
93
- # { field_1: {to: new_val}, field_2: {from: old_val, to: new_val} }
94
- def tracked_changes
95
- @tracked_changes ||= (modified.keys | original.keys).inject(HashWithIndifferentAccess.new) do |h, k|
96
- h[k] = { from: original[k], to: modified[k] }.delete_if { |_, vv| vv.nil? }
97
- h
98
- end.delete_if { |k, v| v.blank? || !trackable_parent_class.tracked?(k) }
99
- end
100
-
101
- # Outputs summary of edit actions performed: :add, :modify, :remove, or :array.
102
- # Does deep comparison of arrays. Useful for creating human-readable representations
103
- # of the history tracker. Considers changing a value to 'blank' to be a removal.
104
- #
105
- # @return [ HashWithIndifferentAccess ] a change set in the format:
106
- # { add: { field_1: new_val, ... },
107
- # modify: { field_2: {from: old_val, to: new_val}, ... },
108
- # remove: { field_3: old_val },
109
- # array: { field_4: {add: ['foo', 'bar'], remove: ['baz']} } }
110
- def tracked_edits
111
- return @tracked_edits if @tracked_edits
112
- @tracked_edits = HashWithIndifferentAccess.new
113
-
114
- tracked_changes.each do |k, v|
115
- next if v[:from].blank? && v[:to].blank?
116
-
117
- if trackable_parent_class.tracked_embeds_many?(k)
118
- prepare_tracked_edits_for_embeds_many(k, v)
119
- elsif v[:from].blank?
120
- @tracked_edits[:add] ||= {}
121
- @tracked_edits[:add][k] = v[:to]
122
- elsif v[:to].blank?
123
- @tracked_edits[:remove] ||= {}
124
- @tracked_edits[:remove][k] = v[:from]
125
- elsif v[:from].is_a?(Array) && v[:to].is_a?(Array)
126
- @tracked_edits[:array] ||= {}
127
- old_values = v[:from] - v[:to]
128
- new_values = v[:to] - v[:from]
129
- @tracked_edits[:array][k] = { add: new_values, remove: old_values }.delete_if { |_, vv| vv.blank? }
130
- else
131
- @tracked_edits[:modify] ||= {}
132
- @tracked_edits[:modify][k] = v
133
- end
134
- end
135
- @tracked_edits
136
- end
137
-
138
- # Similar to #tracked_changes, but contains only a single value for each
139
- # affected field:
140
- # - :create and :update return the modified values
141
- # - :destroy returns original values
142
- # Included for legacy compatibility.
143
- #
144
- # @deprecated
145
- #
146
- # @return [ HashWithIndifferentAccess ] a change set in the format:
147
- # { field_1: value, field_2: value }
148
- def affected
149
- target = action.to_sym == :destroy ? :from : :to
150
- @affected ||= tracked_changes.inject(HashWithIndifferentAccess.new) do |h, (k, v)|
151
- h[k] = v[target]
152
- h
153
- end
154
- end
155
-
156
- # Returns the class of the trackable, irrespective of whether the trackable object
157
- # has been destroyed.
158
- #
159
- # @return [ Class ] the class of the trackable
160
- def trackable_parent_class
161
- association_chain.first['name'].constantize
162
- end
163
-
164
- private
165
-
166
- def re_create
167
- association_chain.length > 1 ? create_on_parent : create_standalone
168
- end
169
-
170
- def re_destroy
171
- trackable.destroy
172
- end
173
-
174
- def create_standalone
175
- restored = trackable_parent_class.new(localize_keys(original))
176
- restored.id = original['_id']
177
- restored.save!
178
- end
179
-
180
- def create_on_parent
181
- name = association_chain.last['name']
182
-
183
- if trackable_parent.class.embeds_one?(name)
184
- trackable_parent._create_relation(name, localize_keys(original))
185
- elsif trackable_parent.class.embeds_many?(name)
186
- trackable_parent._get_relation(name).create!(localize_keys(original))
187
- else
188
- raise 'This should never happen. Please report bug!'
189
- end
190
- end
191
-
192
- def trackable_parents_and_trackable
193
- @trackable_parents_and_trackable ||= traverse_association_chain
194
- end
195
-
196
- def traverse_association_chain
197
- chain = association_chain.dup
198
- doc = nil
199
- documents = []
200
- loop do
201
- node = chain.shift
202
- name = node['name']
203
- doc = if doc.nil?
204
- # root association. First element of the association chain
205
- # unscoped is added to remove any default_scope defined in model
206
- klass = name.classify.constantize
207
- klass.unscoped.where(_id: node['id']).first
208
- elsif doc.class.embeds_one?(name)
209
- doc._get_relation(name)
210
- elsif doc.class.embeds_many?(name)
211
- doc._get_relation(name).unscoped.where(_id: node['id']).first
212
- else
213
- relation_klass = doc.class.relation_class_of(name) if doc
214
- relation_klass ||= 'nil'
215
- raise "Unexpected relation for field '#{name}': #{relation_klass}. This should never happen. Please report bug."
216
- end
217
- documents << doc
218
- break if chain.empty?
219
- end
220
- documents
221
- end
222
-
223
- def localize_keys(hash)
224
- klass = association_chain.first['name'].constantize
225
- if klass.respond_to?(:localized_fields)
226
- klass.localized_fields.keys.each do |name|
227
- hash["#{name}_translations"] = hash.delete(name) if hash[name].present?
228
- end
229
- end
230
- hash
231
- end
232
-
233
- def prepare_tracked_edits_for_embeds_many(key, value)
234
- @tracked_edits[:embeds_many] ||= {}
235
- value[:from] ||= []
236
- value[:to] ||= []
237
- modify_ids = value[:from].map { |vv| vv['_id'] }.compact & value[:to].map { |vv| vv['_id'] }.compact
238
- modify_values = modify_ids.map { |id| { from: value[:from].detect { |vv| vv['_id'] == id }, to: value[:to].detect { |vv| vv['_id'] == id } } }
239
- modify_values.delete_if { |vv| vv[:from] == vv[:to] }
240
- ignore_values = modify_values.map { |vv| [vv[:from], vv[:to]] }.flatten
241
- old_values = value[:from] - value[:to] - ignore_values
242
- new_values = value[:to] - value[:from] - ignore_values
243
- @tracked_edits[:embeds_many][key] = { add: new_values, remove: old_values, modify: modify_values }.delete_if { |_, vv| vv.blank? }
244
- end
245
- end
246
- end
247
- end
1
+ module Mongoid
2
+ module History
3
+ module Tracker
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ include Mongoid::Document
8
+ include Mongoid::Timestamps
9
+ attr_writer :trackable
10
+
11
+ field :association_chain, type: Array, default: []
12
+ field :modified, type: Hash, default: {}
13
+ field :original, type: Hash, default: {}
14
+ field :version, type: Integer
15
+ field :action, type: String
16
+ field :scope, type: String
17
+ modifier_options = {
18
+ class_name: Mongoid::History.modifier_class_name
19
+ }
20
+ modifier_options[:optional] = true if Mongoid::Compatibility::Version.mongoid6_or_newer?
21
+ belongs_to :modifier, modifier_options
22
+
23
+ index(scope: 1)
24
+ index(association_chain: 1)
25
+
26
+ Mongoid::History.tracker_class_name ||= name.tableize.singularize.to_sym
27
+ end
28
+
29
+ def undo!(modifier = nil)
30
+ if action.to_sym == :destroy
31
+ re_create
32
+ elsif action.to_sym == :create
33
+ re_destroy
34
+ elsif Mongoid::Compatibility::Version.mongoid3?
35
+ trackable.update_attributes!(undo_attr(modifier), without_protection: true)
36
+ else
37
+ trackable.update_attributes!(undo_attr(modifier))
38
+ end
39
+ end
40
+
41
+ def redo!(modifier = nil)
42
+ if action.to_sym == :destroy
43
+ re_destroy
44
+ elsif action.to_sym == :create
45
+ re_create
46
+ elsif Mongoid::Compatibility::Version.mongoid3?
47
+ trackable.update_attributes!(redo_attr(modifier), without_protection: true)
48
+ else
49
+ trackable.update_attributes!(redo_attr(modifier))
50
+ end
51
+ end
52
+
53
+ def undo_attr(modifier)
54
+ undo_hash = affected.easy_unmerge(modified)
55
+ undo_hash.easy_merge!(original)
56
+ modifier_field = trackable.history_trackable_options[:modifier_field]
57
+ undo_hash[modifier_field] = modifier if modifier_field
58
+ (modified.keys - undo_hash.keys).each do |k|
59
+ undo_hash[k] = nil
60
+ end
61
+ localize_keys(undo_hash)
62
+ end
63
+
64
+ def redo_attr(modifier)
65
+ redo_hash = affected.easy_unmerge(original)
66
+ redo_hash.easy_merge!(modified)
67
+ modifier_field = trackable.history_trackable_options[:modifier_field]
68
+ redo_hash[modifier_field] = modifier if modifier_field
69
+ localize_keys(redo_hash)
70
+ end
71
+
72
+ def trackable_root
73
+ @trackable_root ||= trackable_parents_and_trackable.first
74
+ end
75
+
76
+ def trackable
77
+ @trackable ||= trackable_parents_and_trackable.last
78
+ end
79
+
80
+ def trackable_parents
81
+ @trackable_parents ||= trackable_parents_and_trackable[0, -1]
82
+ end
83
+
84
+ def trackable_parent
85
+ @trackable_parent ||= trackable_parents_and_trackable[-2]
86
+ end
87
+
88
+ # Outputs a :from, :to hash for each affected field. Intentionally excludes fields
89
+ # which are not tracked, even if there are tracked values for such fields
90
+ # present in the database.
91
+ #
92
+ # @return [ HashWithIndifferentAccess ] a change set in the format:
93
+ # { field_1: {to: new_val}, field_2: {from: old_val, to: new_val} }
94
+ def tracked_changes
95
+ @tracked_changes ||= (modified.keys | original.keys).inject(HashWithIndifferentAccess.new) do |h, k|
96
+ h[k] = { from: original[k], to: modified[k] }.delete_if { |_, vv| vv.nil? }
97
+ h
98
+ end.delete_if { |k, v| v.blank? || !trackable_parent_class.tracked?(k) }
99
+ end
100
+
101
+ # Outputs summary of edit actions performed: :add, :modify, :remove, or :array.
102
+ # Does deep comparison of arrays. Useful for creating human-readable representations
103
+ # of the history tracker. Considers changing a value to 'blank' to be a removal.
104
+ #
105
+ # @return [ HashWithIndifferentAccess ] a change set in the format:
106
+ # { add: { field_1: new_val, ... },
107
+ # modify: { field_2: {from: old_val, to: new_val}, ... },
108
+ # remove: { field_3: old_val },
109
+ # array: { field_4: {add: ['foo', 'bar'], remove: ['baz']} } }
110
+ def tracked_edits
111
+ return @tracked_edits if @tracked_edits
112
+ @tracked_edits = HashWithIndifferentAccess.new
113
+
114
+ tracked_changes.each do |k, v|
115
+ next if v[:from].blank? && v[:to].blank?
116
+
117
+ if trackable_parent_class.tracked_embeds_many?(k)
118
+ prepare_tracked_edits_for_embeds_many(k, v)
119
+ elsif v[:from].blank?
120
+ @tracked_edits[:add] ||= {}
121
+ @tracked_edits[:add][k] = v[:to]
122
+ elsif v[:to].blank?
123
+ @tracked_edits[:remove] ||= {}
124
+ @tracked_edits[:remove][k] = v[:from]
125
+ elsif v[:from].is_a?(Array) && v[:to].is_a?(Array)
126
+ @tracked_edits[:array] ||= {}
127
+ old_values = v[:from] - v[:to]
128
+ new_values = v[:to] - v[:from]
129
+ @tracked_edits[:array][k] = { add: new_values, remove: old_values }.delete_if { |_, vv| vv.blank? }
130
+ else
131
+ @tracked_edits[:modify] ||= {}
132
+ @tracked_edits[:modify][k] = v
133
+ end
134
+ end
135
+ @tracked_edits
136
+ end
137
+
138
+ # Similar to #tracked_changes, but contains only a single value for each
139
+ # affected field:
140
+ # - :create and :update return the modified values
141
+ # - :destroy returns original values
142
+ # Included for legacy compatibility.
143
+ #
144
+ # @deprecated
145
+ #
146
+ # @return [ HashWithIndifferentAccess ] a change set in the format:
147
+ # { field_1: value, field_2: value }
148
+ def affected
149
+ target = action.to_sym == :destroy ? :from : :to
150
+ @affected ||= tracked_changes.inject(HashWithIndifferentAccess.new) do |h, (k, v)|
151
+ h[k] = v[target]
152
+ h
153
+ end
154
+ end
155
+
156
+ # Returns the class of the trackable, irrespective of whether the trackable object
157
+ # has been destroyed.
158
+ #
159
+ # @return [ Class ] the class of the trackable
160
+ def trackable_parent_class
161
+ association_chain.first['name'].constantize
162
+ end
163
+
164
+ private
165
+
166
+ def re_create
167
+ association_chain.length > 1 ? create_on_parent : create_standalone
168
+ end
169
+
170
+ def re_destroy
171
+ trackable.destroy
172
+ end
173
+
174
+ def create_standalone
175
+ restored = trackable_parent_class.new(localize_keys(original))
176
+ restored.id = original['_id']
177
+ restored.save!
178
+ end
179
+
180
+ def create_on_parent
181
+ name = association_chain.last['name']
182
+
183
+ if trackable_parent.class.embeds_one?(name)
184
+ trackable_parent._create_relation(name, localize_keys(original))
185
+ elsif trackable_parent.class.embeds_many?(name)
186
+ trackable_parent._get_relation(name).create!(localize_keys(original))
187
+ else
188
+ raise 'This should never happen. Please report bug!'
189
+ end
190
+ end
191
+
192
+ def trackable_parents_and_trackable
193
+ @trackable_parents_and_trackable ||= traverse_association_chain
194
+ end
195
+
196
+ def traverse_association_chain
197
+ chain = association_chain.dup
198
+ doc = nil
199
+ documents = []
200
+ loop do
201
+ node = chain.shift
202
+ name = node['name']
203
+ doc = if doc.nil?
204
+ # root association. First element of the association chain
205
+ # unscoped is added to remove any default_scope defined in model
206
+ klass = name.classify.constantize
207
+ klass.unscoped.where(_id: node['id']).first
208
+ elsif doc.class.embeds_one?(name)
209
+ doc._get_relation(name)
210
+ elsif doc.class.embeds_many?(name)
211
+ doc._get_relation(name).unscoped.where(_id: node['id']).first
212
+ else
213
+ relation_klass = doc.class.relation_class_of(name) if doc
214
+ relation_klass ||= 'nil'
215
+ raise "Unexpected relation for field '#{name}': #{relation_klass}. This should never happen. Please report bug."
216
+ end
217
+ documents << doc
218
+ break if chain.empty?
219
+ end
220
+ documents
221
+ end
222
+
223
+ def localize_keys(hash)
224
+ klass = association_chain.first['name'].constantize
225
+ if klass.respond_to?(:localized_fields)
226
+ klass.localized_fields.keys.each do |name|
227
+ hash["#{name}_translations"] = hash.delete(name) if hash[name].present?
228
+ end
229
+ end
230
+ hash
231
+ end
232
+
233
+ def prepare_tracked_edits_for_embeds_many(key, value)
234
+ @tracked_edits[:embeds_many] ||= {}
235
+ value[:from] ||= []
236
+ value[:to] ||= []
237
+ modify_ids = value[:from].map { |vv| vv['_id'] }.compact & value[:to].map { |vv| vv['_id'] }.compact
238
+ modify_values = modify_ids.map { |id| { from: value[:from].detect { |vv| vv['_id'] == id }, to: value[:to].detect { |vv| vv['_id'] == id } } }
239
+ modify_values.delete_if { |vv| vv[:from] == vv[:to] }
240
+ ignore_values = modify_values.map { |vv| [vv[:from], vv[:to]] }.flatten
241
+ old_values = value[:from] - value[:to] - ignore_values
242
+ new_values = value[:to] - value[:from] - ignore_values
243
+ @tracked_edits[:embeds_many][key] = { add: new_values, remove: old_values, modify: modify_values }.delete_if { |_, vv| vv.blank? }
244
+ end
245
+ end
246
+ end
247
+ end
@@ -1,5 +1,5 @@
1
- module Mongoid
2
- module History
3
- VERSION = '0.8.3'.freeze
4
- end
5
- end
1
+ module Mongoid
2
+ module History
3
+ VERSION = '0.8.5'.freeze
4
+ end
5
+ end
@@ -1,77 +1,77 @@
1
- require 'easy_diff'
2
- require 'mongoid/compatibility'
3
- require 'mongoid/history/attributes/base'
4
- require 'mongoid/history/attributes/create'
5
- require 'mongoid/history/attributes/update'
6
- require 'mongoid/history/attributes/destroy'
7
- require 'mongoid/history/options'
8
- require 'mongoid/history/version'
9
- require 'mongoid/history/tracker'
10
- require 'mongoid/history/trackable'
11
-
12
- module Mongoid
13
- module History
14
- GLOBAL_TRACK_HISTORY_FLAG = 'mongoid_history_trackable_enabled'.freeze
15
-
16
- class << self
17
- attr_accessor :tracker_class_name
18
- attr_accessor :trackable_settings
19
- attr_accessor :modifier_class_name
20
- attr_accessor :current_user_method
21
-
22
- def disable
23
- original_flag = store[GLOBAL_TRACK_HISTORY_FLAG]
24
- store[GLOBAL_TRACK_HISTORY_FLAG] = false
25
- yield if block_given?
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]
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?
36
- end
37
-
38
- alias disable! disable
39
- alias enable! enable
40
-
41
- def enabled?
42
- store[GLOBAL_TRACK_HISTORY_FLAG] != false
43
- end
44
-
45
- def store
46
- defined?(RequestStore) ? RequestStore.store : Thread.current
47
- end
48
-
49
- def default_settings
50
- @default_settings ||= { paranoia_field: 'deleted_at' }
51
- end
52
-
53
- def trackable_class_settings(trackable_class)
54
- trackable_settings[trackable_class.name.to_sym] || default_settings
55
- end
56
-
57
- def reset!
58
- Mongoid::History.modifier_class_name = 'User'
59
- Mongoid::History.trackable_settings = {}
60
- Mongoid::History.current_user_method ||= :current_user
61
-
62
- Mongoid.models.each do |model|
63
- next unless model.included_modules.include? Mongoid::History::Trackable
64
-
65
- model.singleton_class.class_eval do
66
- # Inverse of class_attribute
67
- %i[mongoid_history_options
68
- mongoid_history_options=
69
- mongoid_history_options?].each { |m| remove_possible_method(m) }
70
- end
71
- end
72
- end
73
- end
74
- end
75
- end
76
-
77
- Mongoid::History.reset!
1
+ require 'easy_diff'
2
+ require 'mongoid/compatibility'
3
+ require 'mongoid/history/attributes/base'
4
+ require 'mongoid/history/attributes/create'
5
+ require 'mongoid/history/attributes/update'
6
+ require 'mongoid/history/attributes/destroy'
7
+ require 'mongoid/history/options'
8
+ require 'mongoid/history/version'
9
+ require 'mongoid/history/tracker'
10
+ require 'mongoid/history/trackable'
11
+
12
+ module Mongoid
13
+ module History
14
+ GLOBAL_TRACK_HISTORY_FLAG = 'mongoid_history_trackable_enabled'.freeze
15
+
16
+ class << self
17
+ attr_accessor :tracker_class_name
18
+ attr_accessor :trackable_settings
19
+ attr_accessor :modifier_class_name
20
+ attr_accessor :current_user_method
21
+
22
+ def disable
23
+ original_flag = store[GLOBAL_TRACK_HISTORY_FLAG]
24
+ store[GLOBAL_TRACK_HISTORY_FLAG] = false
25
+ yield if block_given?
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]
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?
36
+ end
37
+
38
+ alias disable! disable
39
+ alias enable! enable
40
+
41
+ def enabled?
42
+ store[GLOBAL_TRACK_HISTORY_FLAG] != false
43
+ end
44
+
45
+ def store
46
+ defined?(RequestStore) ? RequestStore.store : Thread.current
47
+ end
48
+
49
+ def default_settings
50
+ @default_settings ||= { paranoia_field: 'deleted_at' }
51
+ end
52
+
53
+ def trackable_class_settings(trackable_class)
54
+ trackable_settings[trackable_class.name.to_sym] || default_settings
55
+ end
56
+
57
+ def reset!
58
+ Mongoid::History.modifier_class_name = 'User'
59
+ Mongoid::History.trackable_settings = {}
60
+ Mongoid::History.current_user_method ||= :current_user
61
+
62
+ Mongoid.models.each do |model|
63
+ next unless model.included_modules.include? Mongoid::History::Trackable
64
+
65
+ model.singleton_class.class_eval do
66
+ # Inverse of class_attribute
67
+ %i[mongoid_history_options
68
+ mongoid_history_options=
69
+ mongoid_history_options?].each { |m| remove_possible_method(m) }
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ Mongoid::History.reset!
@@ -1 +1 @@
1
- require 'mongoid/history'
1
+ require 'mongoid/history'