mongoid-history 0.8.0 → 0.8.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +5 -5
  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 -101
  9. data/CHANGELOG.md +173 -144
  10. data/CONTRIBUTING.md +117 -118
  11. data/Dangerfile +1 -1
  12. data/Gemfile +49 -37
  13. data/LICENSE.txt +20 -20
  14. data/README.md +609 -595
  15. data/RELEASING.md +66 -67
  16. data/Rakefile +24 -24
  17. data/UPGRADING.md +53 -34
  18. data/lib/mongoid/history/attributes/base.rb +72 -72
  19. data/lib/mongoid/history/attributes/create.rb +45 -50
  20. data/lib/mongoid/history/attributes/destroy.rb +34 -34
  21. data/lib/mongoid/history/attributes/update.rb +104 -45
  22. data/lib/mongoid/history/options.rb +177 -179
  23. data/lib/mongoid/history/trackable.rb +588 -521
  24. data/lib/mongoid/history/tracker.rb +247 -244
  25. data/lib/mongoid/history/version.rb +5 -5
  26. data/lib/mongoid/history.rb +77 -52
  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 -0
  30. data/perf/gc_suite.rb +21 -0
  31. data/spec/integration/embedded_in_polymorphic_spec.rb +112 -135
  32. data/spec/integration/integration_spec.rb +976 -942
  33. data/spec/integration/multi_relation_spec.rb +47 -53
  34. data/spec/integration/multiple_trackers_spec.rb +68 -71
  35. data/spec/integration/nested_embedded_documents_spec.rb +64 -84
  36. data/spec/integration/nested_embedded_documents_tracked_in_parent_spec.rb +124 -0
  37. data/spec/integration/nested_embedded_polymorphic_documents_spec.rb +115 -127
  38. data/spec/integration/subclasses_spec.rb +47 -29
  39. data/spec/integration/track_history_order_spec.rb +84 -52
  40. data/spec/integration/validation_failure_spec.rb +76 -63
  41. data/spec/spec_helper.rb +32 -25
  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 -13
  45. data/spec/unit/attributes/base_spec.rb +141 -150
  46. data/spec/unit/attributes/create_spec.rb +342 -315
  47. data/spec/unit/attributes/destroy_spec.rb +228 -218
  48. data/spec/unit/attributes/update_spec.rb +342 -321
  49. data/spec/unit/callback_options_spec.rb +165 -159
  50. data/spec/unit/embedded_methods_spec.rb +87 -69
  51. data/spec/unit/history_spec.rb +58 -35
  52. data/spec/unit/my_instance_methods_spec.rb +555 -485
  53. data/spec/unit/options_spec.rb +365 -327
  54. data/spec/unit/singleton_methods_spec.rb +406 -338
  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 -689
  58. data/spec/unit/tracker_spec.rb +190 -163
  59. metadata +13 -8
  60. data/.travis.yml +0 -35
data/RELEASING.md CHANGED
@@ -1,67 +1,66 @@
1
- Releasing Mongoid::History
2
- ========================
3
-
4
- There're no particular rules about when to release mongoid-history. Release bug fixes frequently, features not so frequently and breaking API changes rarely.
5
-
6
- ### Release
7
-
8
- Run tests, check that all tests succeed locally.
9
-
10
- ```
11
- bundle install
12
- bundle exec rake
13
- ```
14
-
15
- Check that the last build succeeded in [Travis CI](https://travis-ci.org/mongoid/mongoid-history) for all supported platforms.
16
-
17
- Increment the version, modify [lib/mongoid/history/version.rb](lib/mongoid/history/version.rb).
18
-
19
- * Increment the third number if the release has bug fixes and/or very minor features, only (eg. change `0.5.1` to `0.5.2`).
20
- * Increment the second number if the release contains major features or breaking API changes (eg. change `0.5.1` to `0.4.0`).
21
-
22
- Change "Next Release" in [CHANGELOG.md](CHANGELOG.md) to the new version.
23
-
24
- ```
25
- ### 0.4.0 (2014-01-27)
26
- ```
27
-
28
- Remove the line with "Your contribution here.", since there will be no more contributions to this release.
29
-
30
- Commit your changes.
31
-
32
- ```
33
- git add CHANGELOG.md lib/mongoid/history/version.rb
34
- git commit -m "Preparing for release, 0.4.0."
35
- git push origin master
36
- ```
37
-
38
- Release.
39
-
40
- ```
41
- $ rake release
42
-
43
- mongoid-history 0.4.0 built to pkg/mongoid-history-0.4.0.gem.
44
- Tagged v0.4.0.
45
- Pushed git commits and tags.
46
- Pushed mongoid-history 0.4.0 to rubygems.org.
47
- ```
48
-
49
- ### Prepare for the Next Version
50
-
51
- Add the next release to [CHANGELOG.md](CHANGELOG.md).
52
-
53
- ```
54
- ### 0.4.1 (Next)
55
-
56
- * Your contribution here.
57
- ```
58
-
59
- Increment the minor version, modify [lib/mongoid/history/version.rb](lib/mongoid/history/version.rb).
60
-
61
- Commit your changes.
62
-
63
- ```
64
- git add CHANGELOG.md lib/mongoid/history/version.rb
65
- git commit -m "Preparing for next release, 0.4.1."
66
- git push origin master
67
- ```
1
+ # Releasing Mongoid::History
2
+
3
+ There are no particular rules about when to release Mongoid History.
4
+ Release bug fixes frequently, features not so frequently and breaking API changes rarely.
5
+
6
+ ### Release Procedure
7
+
8
+ Run tests, check that all tests succeed locally.
9
+
10
+ ```
11
+ bundle install
12
+ bundle exec rake
13
+ ```
14
+
15
+ Check that the last build succeeded in [Travis CI](https://travis-ci.org/mongoid/mongoid-history)
16
+ for all supported platforms.
17
+
18
+ Increment the version, modify [lib/mongoid/history/version.rb](lib/mongoid/history/version.rb).
19
+ Mongoid History versions should follow [Semantic Versioning (SemVer)](https://semver.org/).
20
+
21
+ Change "Next Release" in [CHANGELOG.md](CHANGELOG.md) to the new version.
22
+
23
+ ```
24
+ ### 0.4.0 (2014-01-27)
25
+ ```
26
+
27
+ Remove the line with "Your contribution here.", since there will be no more contributions to this release.
28
+
29
+ Commit your changes.
30
+
31
+ ```
32
+ git add CHANGELOG.md lib/mongoid/history/version.rb
33
+ git commit -m "Preparing for release, 0.4.0."
34
+ git push origin master
35
+ ```
36
+
37
+ Release.
38
+
39
+ ```
40
+ $ rake release
41
+
42
+ mongoid-history 0.4.0 built to pkg/mongoid-history-0.4.0.gem.
43
+ Tagged v0.4.0.
44
+ Pushed git commits and tags.
45
+ Pushed mongoid-history 0.4.0 to rubygems.org.
46
+ ```
47
+
48
+ ### Prepare for the Next Version
49
+
50
+ Add the next release to [CHANGELOG.md](CHANGELOG.md).
51
+
52
+ ```
53
+ ### 0.4.1 (Next)
54
+
55
+ * Your contribution here.
56
+ ```
57
+
58
+ Increment the minor version, modify [lib/mongoid/history/version.rb](lib/mongoid/history/version.rb).
59
+
60
+ Commit your changes.
61
+
62
+ ```
63
+ git add CHANGELOG.md lib/mongoid/history/version.rb
64
+ git commit -m "Preparing for next release, 0.4.1."
65
+ git push origin master
66
+ ```
data/Rakefile CHANGED
@@ -1,24 +1,24 @@
1
- require 'bundler'
2
- begin
3
- Bundler.setup(:default, :development)
4
- rescue Bundler::BundlerError => e
5
- $stderr.puts e.message
6
- $stderr.puts 'Run `bundle install` to install missing gems'
7
- exit e.status_code
8
- end
9
-
10
- Bundler::GemHelper.install_tasks
11
-
12
- require 'rspec/core'
13
- require 'rspec/core/rake_task'
14
- RSpec::Core::RakeTask.new(:spec) do |spec|
15
- spec.pattern = FileList['spec/**/*_spec.rb']
16
- end
17
-
18
- require 'rubocop/rake_task'
19
- RuboCop::RakeTask.new(:rubocop)
20
-
21
- task default: %i[rubocop spec]
22
-
23
- require 'yard'
24
- YARD::Rake::YardocTask.new
1
+ require 'bundler'
2
+ begin
3
+ Bundler.setup(:default, :development)
4
+ rescue Bundler::BundlerError => e
5
+ $stderr.puts e.message
6
+ $stderr.puts 'Run `bundle install` to install missing gems'
7
+ exit e.status_code
8
+ end
9
+
10
+ Bundler::GemHelper.install_tasks
11
+
12
+ require 'rspec/core'
13
+ require 'rspec/core/rake_task'
14
+ RSpec::Core::RakeTask.new(:spec) do |spec|
15
+ spec.pattern = FileList['spec/**/*_spec.rb']
16
+ end
17
+
18
+ require 'rubocop/rake_task'
19
+ RuboCop::RakeTask.new(:rubocop)
20
+
21
+ task default: %i[rubocop spec]
22
+
23
+ require 'yard'
24
+ YARD::Rake::YardocTask.new
data/UPGRADING.md CHANGED
@@ -1,34 +1,53 @@
1
- ## Upgrading Mongoid History
2
-
3
- ### Upgrading to 0.8.0
4
-
5
- #### History is now tracked on create and destroy by default
6
-
7
- By default, Mongoid History will now track all actions (create, update, and destroy.)
8
- Previously, only update actions were tracked by default.
9
-
10
- To preserve the old behavior, please modify your call to `track_history` as follows:
11
-
12
- ```ruby
13
- track_history ...
14
- track_create: false,
15
- track_destroy: false
16
- ```
17
-
18
- See [#207](https://github.com/mongoid/mongoid-history/pull/207) for more information.
19
-
20
- ### Upgrading to 0.7.0
21
-
22
- #### Remove history track when create, update or destroy raises an error
23
-
24
- When an error is raised in a call to create, update or destroy a tracked model, any history track
25
- created before the call will now be deleted. In the past this was a problem for associations marked
26
- `dependent: :restrict`.
27
-
28
- See [#202](https://github.com/mongoid/mongoid-history/pull/202) for more information.
29
-
30
- # Main Changes / Upgrading Notes
31
-
32
- See [#189](https://github.com/mongoid/mongoid-history/pull/189) for more information.
33
-
34
- * Currently, the `:all` option behaves identically to `:fields`. Future versions will track all fields and relations of trackable class when using `:all`.
1
+ ## Upgrading Mongoid History
2
+
3
+ ### Upgrading to 0.8.0
4
+
5
+ #### History is now tracked on create and destroy by default
6
+
7
+ By default, Mongoid History will now track all actions (create, update, and destroy.)
8
+ Previously, only update actions were tracked by default.
9
+
10
+ To preserve the old behavior, please modify your call to `track_history` as follows:
11
+
12
+ ```ruby
13
+ track_history ...
14
+ track_create: false,
15
+ track_destroy: false
16
+ ```
17
+
18
+ See [#207](https://github.com/mongoid/mongoid-history/pull/207) for more information.
19
+
20
+ ### Upgrading to 0.7.0
21
+
22
+ #### Remove history track when create, update or destroy raises an error
23
+
24
+ When an error is raised in a call to create, update or destroy a tracked model, any history track
25
+ created before the call will now be deleted. In the past this was a problem for associations marked
26
+ `dependent: :restrict`.
27
+
28
+ See [#202](https://github.com/mongoid/mongoid-history/pull/202) for more information.
29
+
30
+ # Main Changes / Upgrading Notes
31
+
32
+ See [#189](https://github.com/mongoid/mongoid-history/pull/189) for more information.
33
+
34
+ * Currently, the `:all` option behaves identically to `:fields`. Future versions will track all fields and relations of trackable class when using `:all`.
35
+
36
+ ### Upgrading to 0.4.1
37
+
38
+ #### Migrate Userstamp
39
+
40
+ `Mongoid::History` no longer supports the userstamp natively. To track the User in the application who created the HistoryTracker, add the [Mongoid::Userstamp gem](https://github.com/tbpro/mongoid_userstamp) to your HistoryTracker class.
41
+
42
+ ```ruby
43
+ class MyHistoryTracker
44
+ include Mongoid::History::Tracker
45
+ include Mongoid::Userstamp
46
+ end
47
+ ```
48
+
49
+ Rename the field.
50
+
51
+ ```ruby
52
+ MyHistoryTracker.all.rename(modifier_id: :created_by)
53
+ ```
@@ -1,72 +1,72 @@
1
- module Mongoid
2
- module History
3
- module Attributes
4
- class Base
5
- attr_reader :trackable
6
-
7
- def initialize(trackable)
8
- @trackable = trackable
9
- end
10
-
11
- private
12
-
13
- def trackable_class
14
- @trackable_class ||= trackable.class
15
- end
16
-
17
- def aliased_fields
18
- @aliased_fields ||= trackable_class.aliased_fields
19
- end
20
-
21
- def changes_method
22
- trackable_class.history_trackable_options[:changes_method]
23
- end
24
-
25
- def changes
26
- trackable.send(changes_method)
27
- end
28
-
29
- def format_field(field, value)
30
- format_value(value, trackable_class.field_format(field))
31
- end
32
-
33
- def format_embeds_one_relation(rel, obj)
34
- rel = trackable_class.database_field_name(rel)
35
- relation_class = trackable_class.embeds_one_class(rel)
36
- permitted_attrs = trackable_class.tracked_embeds_one_attributes(rel)
37
- formats = trackable_class.field_format(rel)
38
- format_relation(relation_class, obj, permitted_attrs, formats)
39
- end
40
-
41
- def format_embeds_many_relation(rel, obj)
42
- rel = trackable_class.database_field_name(rel)
43
- relation_class = trackable_class.embeds_many_class(rel)
44
- permitted_attrs = trackable_class.tracked_embeds_many_attributes(rel)
45
- formats = trackable_class.field_format(rel)
46
- format_relation(relation_class, obj, permitted_attrs, formats)
47
- end
48
-
49
- def format_relation(relation_class, obj, permitted_attrs, formats)
50
- obj.inject({}) do |m, field_value|
51
- field = relation_class.database_field_name(field_value.first)
52
- next m unless permitted_attrs.include?(field)
53
-
54
- value = field_value.last
55
- value = format_value(field_value.last, formats[field]) if formats.class == Hash
56
- m.merge(field => value)
57
- end
58
- end
59
-
60
- def format_value(value, format)
61
- if format.class == String
62
- format % value
63
- elsif format.respond_to?(:call)
64
- format.call(value)
65
- else
66
- value
67
- end
68
- end
69
- end
70
- end
71
- end
72
- end
1
+ module Mongoid
2
+ module History
3
+ module Attributes
4
+ class Base
5
+ attr_reader :trackable
6
+
7
+ def initialize(trackable)
8
+ @trackable = trackable
9
+ end
10
+
11
+ private
12
+
13
+ def trackable_class
14
+ @trackable_class ||= trackable.class
15
+ end
16
+
17
+ def aliased_fields
18
+ @aliased_fields ||= trackable_class.aliased_fields
19
+ end
20
+
21
+ def changes_method
22
+ trackable_class.history_trackable_options[:changes_method]
23
+ end
24
+
25
+ def changes
26
+ trackable.send(changes_method)
27
+ end
28
+
29
+ def format_field(field, value)
30
+ format_value(value, trackable_class.field_format(field))
31
+ end
32
+
33
+ def format_embeds_one_relation(rel, obj)
34
+ rel = trackable_class.database_field_name(rel)
35
+ relation_class = trackable_class.relation_class_of(rel)
36
+ permitted_attrs = trackable_class.tracked_embeds_one_attributes(rel)
37
+ formats = trackable_class.field_format(rel)
38
+ format_relation(relation_class, obj, permitted_attrs, formats)
39
+ end
40
+
41
+ def format_embeds_many_relation(rel, obj)
42
+ rel = trackable_class.database_field_name(rel)
43
+ relation_class = trackable_class.relation_class_of(rel)
44
+ permitted_attrs = trackable_class.tracked_embeds_many_attributes(rel)
45
+ formats = trackable_class.field_format(rel)
46
+ format_relation(relation_class, obj, permitted_attrs, formats)
47
+ end
48
+
49
+ def format_relation(relation_class, obj, permitted_attrs, formats)
50
+ obj.inject({}) do |m, field_value|
51
+ field = relation_class.database_field_name(field_value.first)
52
+ next m unless permitted_attrs.include?(field)
53
+
54
+ value = field_value.last
55
+ value = format_value(field_value.last, formats[field]) if formats.class == Hash
56
+ m.merge(field => value)
57
+ end
58
+ end
59
+
60
+ def format_value(value, format)
61
+ if format.class == String
62
+ format % value
63
+ elsif format.respond_to?(:call)
64
+ format.call(value)
65
+ else
66
+ value
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -1,50 +1,45 @@
1
- module Mongoid
2
- module History
3
- module Attributes
4
- class Create < ::Mongoid::History::Attributes::Base
5
- def attributes
6
- @attributes = {}
7
- trackable.attributes.each do |k, v|
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)]
15
- end
16
- insert_embeds_one_changes
17
- insert_embeds_many_changes
18
- @attributes
19
- end
20
-
21
- private
22
-
23
- def insert_embeds_one_changes
24
- trackable_class.tracked_embeds_one.each do |rel|
25
- rel_class = trackable_class.embeds_one_class(rel)
26
- paranoia_field = Mongoid::History.trackable_class_settings(rel_class)[:paranoia_field]
27
- paranoia_field = rel_class.aliased_fields.key(paranoia_field) || paranoia_field
28
- rel = aliased_fields.key(rel) || rel
29
- obj = trackable.send(rel)
30
- next if !obj || (obj.respond_to?(paranoia_field) && obj.public_send(paranoia_field).present?)
31
- @attributes[rel] = [nil, format_embeds_one_relation(rel, obj.attributes)]
32
- end
33
- end
34
-
35
- def insert_embeds_many_changes
36
- trackable_class.tracked_embeds_many.each do |rel|
37
- rel_class = trackable_class.embeds_many_class(rel)
38
- paranoia_field = Mongoid::History.trackable_class_settings(rel_class)[:paranoia_field]
39
- paranoia_field = rel_class.aliased_fields.key(paranoia_field) || paranoia_field
40
- rel = aliased_fields.key(rel) || rel
41
- @attributes[rel] = [nil,
42
- trackable.send(rel)
43
- .reject { |obj| obj.respond_to?(paranoia_field) && obj.public_send(paranoia_field).present? }
44
- .map { |obj| format_embeds_many_relation(rel, obj.attributes) }]
45
- end
46
- end
47
- end
48
- end
49
- end
50
- end
1
+ module Mongoid
2
+ module History
3
+ module Attributes
4
+ class Create < ::Mongoid::History::Attributes::Base
5
+ def attributes
6
+ @attributes = {}
7
+ changes.each do |k, v|
8
+ next unless trackable_class.tracked_field?(k, :create)
9
+ @attributes[k] = format_field(k, v)
10
+ end
11
+ insert_embeds_one_changes
12
+ insert_embeds_many_changes
13
+ @attributes
14
+ end
15
+
16
+ private
17
+
18
+ def insert_embeds_one_changes
19
+ trackable_class.tracked_embeds_one.each do |rel|
20
+ rel_class = trackable_class.relation_class_of(rel)
21
+ paranoia_field = Mongoid::History.trackable_class_settings(rel_class)[:paranoia_field]
22
+ paranoia_field = rel_class.aliased_fields.key(paranoia_field) || paranoia_field
23
+ rel = aliased_fields.key(rel) || rel
24
+ obj = trackable.send(rel)
25
+ next if !obj || (obj.respond_to?(paranoia_field) && obj.public_send(paranoia_field).present?)
26
+ @attributes[rel] = [nil, format_embeds_one_relation(rel, obj.attributes)]
27
+ end
28
+ end
29
+
30
+ def insert_embeds_many_changes
31
+ trackable_class.tracked_embeds_many.each do |rel|
32
+ rel_class = trackable_class.relation_class_of(rel)
33
+ paranoia_field = Mongoid::History.trackable_class_settings(rel_class)[:paranoia_field]
34
+ paranoia_field = rel_class.aliased_fields.key(paranoia_field) || paranoia_field
35
+ rel = aliased_fields.key(rel) || rel
36
+ @attributes[rel] = [nil,
37
+ trackable.send(rel)
38
+ .reject { |obj| obj.respond_to?(paranoia_field) && obj.public_send(paranoia_field).present? }
39
+ .map { |obj| format_embeds_many_relation(rel, obj.attributes) }]
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -1,34 +1,34 @@
1
- module Mongoid
2
- module History
3
- module Attributes
4
- class Destroy < ::Mongoid::History::Attributes::Base
5
- def attributes
6
- @attributes = {}
7
- trackable.attributes.each { |k, v| @attributes[k] = [format_field(k, v), nil] if trackable_class.tracked_field?(k, :destroy) }
8
- insert_embeds_one_changes
9
- insert_embeds_many_changes
10
- @attributes
11
- end
12
-
13
- private
14
-
15
- def insert_embeds_one_changes
16
- trackable_class.tracked_embeds_one
17
- .map { |rel| aliased_fields.key(rel) || rel }
18
- .each do |rel|
19
- obj = trackable.send(rel)
20
- @attributes[rel] = [format_embeds_one_relation(rel, obj.attributes), nil] if obj
21
- end
22
- end
23
-
24
- def insert_embeds_many_changes
25
- trackable_class.tracked_embeds_many
26
- .map { |rel| aliased_fields.key(rel) || rel }
27
- .each do |rel|
28
- @attributes[rel] = [trackable.send(rel).map { |obj| format_embeds_many_relation(rel, obj.attributes) }, nil]
29
- end
30
- end
31
- end
32
- end
33
- end
34
- end
1
+ module Mongoid
2
+ module History
3
+ module Attributes
4
+ class Destroy < ::Mongoid::History::Attributes::Base
5
+ def attributes
6
+ @attributes = {}
7
+ trackable.attributes.each { |k, v| @attributes[k] = [format_field(k, v), nil] if trackable_class.tracked_field?(k, :destroy) }
8
+ insert_embeds_one_changes
9
+ insert_embeds_many_changes
10
+ @attributes
11
+ end
12
+
13
+ private
14
+
15
+ def insert_embeds_one_changes
16
+ trackable_class.tracked_embeds_one
17
+ .map { |rel| aliased_fields.key(rel) || rel }
18
+ .each do |rel|
19
+ obj = trackable.send(rel)
20
+ @attributes[rel] = [format_embeds_one_relation(rel, obj.attributes), nil] if obj
21
+ end
22
+ end
23
+
24
+ def insert_embeds_many_changes
25
+ trackable_class.tracked_embeds_many
26
+ .map { |rel| aliased_fields.key(rel) || rel }
27
+ .each do |rel|
28
+ @attributes[rel] = [trackable.send(rel).map { |obj| format_embeds_many_relation(rel, obj.attributes) }, nil]
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end