mongoid-history 0.6.0 → 0.6.1

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
  SHA1:
3
- metadata.gz: 1fd1d2a3abaccb54ecc0c83da09b16dbaa7d8210
4
- data.tar.gz: 1126ed19a46d4542a059c2434665436043787424
3
+ metadata.gz: d92239564a7df075b3a55eb68c9f7f22666e24ef
4
+ data.tar.gz: 13f5bb15f7102d5b0957b569cb880af4249a0c75
5
5
  SHA512:
6
- metadata.gz: d83f26cbfe246d76d2659414b7a7feb48b1a27007cafec7bf1c4d957568b688375ce09302f0ed3a15329d31e87a4e15147212c70f3fa4796d6de783e17edfd0d
7
- data.tar.gz: 27fce1d91542b620f197f213185b570f057508a929f05abc8b2647cfeeeef543e536850e3127d9b29e567f032bc94a2d587a72c9d8f91facec0254632540b49e
6
+ metadata.gz: e9b09271720419ebbd843f78954d182430e4a3e5f020cc6b835993154c08fa55e6c8627beaef64f8813632ce15118186057d39771ddb863cf40f28a68c6ce7d3
7
+ data.tar.gz: 8d337e3008f6468a42b01c0babafa649685237f686e255bd620d380bf8d91bf77d56888445ca20b043ee6f2e7398d4821709fb877bafe11765948fc38ee6ddad
@@ -64,6 +64,7 @@ Style/Documentation:
64
64
  - 'spec/unit/singleton_methods_spec.rb'
65
65
  - 'spec/unit/trackable_spec.rb'
66
66
  - 'spec/unit/tracker_spec.rb'
67
+ - 'spec/unit/attributes/base_spec.rb'
67
68
  - 'spec/unit/attributes/create_spec.rb'
68
69
  - 'spec/unit/attributes/destroy_spec.rb'
69
70
  - 'spec/unit/attributes/update_spec.rb'
@@ -85,3 +86,7 @@ Style/MultilineBlockChain:
85
86
  Exclude:
86
87
  - 'lib/mongoid/history/trackable.rb'
87
88
  - 'lib/mongoid/history/tracker.rb'
89
+
90
+ Style/ClassLength:
91
+ Exclude:
92
+ - 'lib/mongoid/history/options.rb'
@@ -1,57 +1,57 @@
1
- 0.6.0 (2016/09/13)
2
- ------------------
1
+ ### 0.6.1 (2017/01/04)
3
2
 
4
- * [#2](https://github.com/mongoid/mongoid-history/pull/2): Froked into the [mongoid](https://github.com/mongoid) organization - [@dblock](https://github.com/dblock).
5
- * [#1](https://github.com/mongoid/mongoid-history/pull/1): Added Danger, PR linter - [@dblock](https://github.com/dblock).
6
- * [#166](https://github.com/aq1018/mongoid-history/pull/166): Hash fields should default to an empty Hash - [@johnnyshields](https://github.com/johnnyshields).
7
- * [#162](https://github.com/aq1018/mongoid-history/pull/162): Do not consider embedded relations as dynamic fields - [@JagdeepSingh](https://github.com/JagdeepSingh).
8
- * [#144](https://github.com/aq1018/mongoid-history/pull/158): Can modify history tracker insertion on object creation - [@sivagollapalli](https://github.com/sivagollapalli).
9
- * [#155](https://github.com/aq1018/mongoid-history/pull/155): Add support to whitelist the attributes for tracked embeds_one and embeds_many relations - [@JagdeepSingh](https://github.com/JagdeepSingh).
10
- * [#154](https://github.com/aq1018/mongoid-history/pull/154): Prevent soft-deleted embedded documents from tracking - [@JagdeepSingh](https://github.com/JagdeepSingh).
11
- * [#151](https://github.com/aq1018/mongoid-history/pull/151): Added ability to customize tracker class for each trackable; multiple trackers across the app are now possible - [@JagdeepSingh](https://github.com/JagdeepSingh).
12
- * [#151](https://github.com/aq1018/mongoid-history/pull/151): Added automatic support for `request_store` gem as drop-in replacement for `Thread.current` - [@JagdeepSingh](https://github.com/JagdeepSingh).
13
- * [#150](https://github.com/aq1018/mongoid-history/pull/150): Added support for keeping embedded objects audit history in parent itself - [@JagdeepSingh](https://github.com/JagdeepSingh).
3
+ * [#182](https://github.com/mongoid/mongoid-history/pull/182): No-op on repeated calls to destroy - [@msaffitz](https://github.com/msaffitz).
4
+ * [#170](https://github.com/mongoid/mongoid-history/pull/170): Parent repo is now [mongoid/mongoid-history](https://github.com/mongoid/mongoid-history) - [@dblock](https://github.com/dblock).
5
+ * [#171](https://github.com/mongoid/mongoid-history/pull/171): Add field formatting - [@jnfeinstein](https://github.com/jnfeinstein).
6
+ * [#172](https://github.com/mongoid/mongoid-history/pull/172): Add config helper to track all embedded relations - [@jnfeinstein](https://github.com/jnfeinstein).
7
+ * [#173](https://github.com/mongoid/mongoid-history/pull/173): Compatible with mongoid 6 - [@sivagollapalli](https://github.com/sivagollapalli).
14
8
 
15
- 0.5.0 (2015/09/18)
16
- ------------------
9
+ ### 0.6.0 (2016/09/13)
17
10
 
18
- * [#143](https://github.com/aq1018/mongoid-history/pull/143): Added support for Mongoid 5 - [@dblock](https://github.com/dblock).
19
- * [#133](https://github.com/aq1018/mongoid-history/pull/133): Added dynamic attributes tracking (Mongoid::Attributes::Dynamic) - [@minisai](https://github.com/minisai).
20
- * [#142](https://github.com/aq1018/mongoid-history/pull/142): Allow non-database fields to be specified in conjunction with a custom changes method - [@kayakyakr](https://github.com/kayakyakr).
11
+ * [#2](https://github.com/dblock/mongoid-history/pull/2): Forked into the [mongoid](https://github.com/mongoid) organization - [@dblock](https://github.com/dblock).
12
+ * [#1](https://github.com/dblock/mongoid-history/pull/1): Added Danger, PR linter - [@dblock](https://github.com/dblock).
13
+ * [#166](https://github.com/mongoid/mongoid-history/pull/166): Hash fields should default to an empty Hash - [@johnnyshields](https://github.com/johnnyshields).
14
+ * [#162](https://github.com/mongoid/mongoid-history/pull/162): Do not consider embedded relations as dynamic fields - [@JagdeepSingh](https://github.com/JagdeepSingh).
15
+ * [#144](https://github.com/mongoid/mongoid-history/pull/158): Can modify history tracker insertion on object creation - [@sivagollapalli](https://github.com/sivagollapalli).
16
+ * [#155](https://github.com/mongoid/mongoid-history/pull/155): Add support to whitelist the attributes for tracked embeds_one and embeds_many relations - [@JagdeepSingh](https://github.com/JagdeepSingh).
17
+ * [#154](https://github.com/mongoid/mongoid-history/pull/154): Prevent soft-deleted embedded documents from tracking - [@JagdeepSingh](https://github.com/JagdeepSingh).
18
+ * [#151](https://github.com/mongoid/mongoid-history/pull/151): Added ability to customize tracker class for each trackable; multiple trackers across the app are now possible - [@JagdeepSingh](https://github.com/JagdeepSingh).
19
+ * [#151](https://github.com/mongoid/mongoid-history/pull/151): Added automatic support for `request_store` gem as drop-in replacement for `Thread.current` - [@JagdeepSingh](https://github.com/JagdeepSingh).
20
+ * [#150](https://github.com/mongoid/mongoid-history/pull/150): Added support for keeping embedded objects audit history in parent itself - [@JagdeepSingh](https://github.com/JagdeepSingh).
21
21
 
22
- 0.4.7 (2015/04/06)
23
- ------------------
22
+ ### 0.5.0 (2015/09/18)
24
23
 
25
- * [#124](https://github.com/aq1018/mongoid-history/pull/124): You can require both `mongoid-history` and `mongoid/history` - [@dblock](https://github.com/dblock).
24
+ * [#143](https://github.com/mongoid/mongoid-history/pull/143): Added support for Mongoid 5 - [@dblock](https://github.com/dblock).
25
+ * [#133](https://github.com/mongoid/mongoid-history/pull/133): Added dynamic attributes tracking (Mongoid::Attributes::Dynamic) - [@minisai](https://github.com/minisai).
26
+ * [#142](https://github.com/mongoid/mongoid-history/pull/142): Allow non-database fields to be specified in conjunction with a custom changes method - [@kayakyakr](https://github.com/kayakyakr).
26
27
 
27
- 0.4.5 (2015/02/09)
28
- ------------------
28
+ ### 0.4.7 (2015/04/06)
29
29
 
30
- * [#131](https://github.com/aq1018/mongoid-history/pull/131): Added `undo` method, that helps to get specific version of an object without saving changes - [@alexkravets](https://github.com/alexkravets).
31
- * [#127](https://github.com/aq1018/mongoid-history/pull/127): Fixed gem naming per [rubygems](http://guides.rubygems.org/name-your-gem/) specs, now you can `require 'mongoid/history'` - [@nofxx](https://github.com/nofxx).
32
- * [#129](https://github.com/aq1018/mongoid-history/pull/129): Support multiple levels of embedded polimorphic documents - [@BrunoChauvet](https://github.com/BrunoChauvet).
33
- * [#123](https://github.com/aq1018/mongoid-history/pull/123): Used a method compatible with mongoid-observers to determinine the version of Mongoid - [@zeitnot](https://github.com/zeitnot).
30
+ * [#124](https://github.com/mongoid/mongoid-history/pull/124): You can require both `mongoid-history` and `mongoid/history` - [@dblock](https://github.com/dblock).
34
31
 
35
- 0.4.4 (2014/7/29)
36
- -----------------
32
+ ### 0.4.5 (2015/02/09)
37
33
 
38
- * [#111](https://github.com/aq1018/mongoid-history/pull/111): Fixed compatibility of `undo!` and `redo!` methods with Rails 3.x - [@mrjlynch](https://github.com/mrjlynch).
34
+ * [#131](https://github.com/mongoid/mongoid-history/pull/131): Added `undo` method, that helps to get specific version of an object without saving changes - [@alexkravets](https://github.com/alexkravets).
35
+ * [#127](https://github.com/mongoid/mongoid-history/pull/127): Fixed gem naming per [rubygems](http://guides.rubygems.org/name-your-gem/) specs, now you can `require 'mongoid/history'` - [@nofxx](https://github.com/nofxx).
36
+ * [#129](https://github.com/mongoid/mongoid-history/pull/129): Support multiple levels of embedded polimorphic documents - [@BrunoChauvet](https://github.com/BrunoChauvet).
37
+ * [#123](https://github.com/mongoid/mongoid-history/pull/123): Used a method compatible with mongoid-observers to determinine the version of Mongoid - [@zeitnot](https://github.com/zeitnot).
39
38
 
40
- 0.4.3 (2014/07/10)
41
- ------------------
39
+ ### 0.4.4 (2014/7/29)
42
40
 
43
- * [#110](https://github.com/aq1018/mongoid-history/pull/110): Fixed scope reference on history tracks criteria - [@adbeelitamar](https://github.com/adbeelitamar).
41
+ * [#111](https://github.com/mongoid/mongoid-history/pull/111): Fixed compatibility of `undo!` and `redo!` methods with Rails 3.x - [@mrjlynch](https://github.com/mrjlynch).
44
42
 
45
- 0.4.2 (2014/07/01)
46
- ------------------
43
+ ### 0.4.3 (2014/07/10)
47
44
 
48
- * [#106](https://github.com/aq1018/mongoid-history/pull/106): Added support for polymorphic relationship `scope` - [@adbeelitamar](https://github.com/adbeelitamar).
49
- * [#106](https://github.com/aq1018/mongoid-history/pull/106): Enabled specifying an array of relationships in `scope` - [@adbeelitamar](https://github.com/adbeelitamar).
50
- * [#83](https://github.com/aq1018/mongoid-history/pull/83): Added support for Mongoid 4.x, which removed `attr_accessible` in favor of protected attributes - [@dblock](https://github.com/dblock).
51
- * [#103](https://github.com/aq1018/mongoid-history/pull/103): Fixed compatibility with models using `default_scope` - [@mrjlynch](https://github.com/mrjlynch).
45
+ * [#110](https://github.com/mongoid/mongoid-history/pull/110): Fixed scope reference on history tracks criteria - [@adbeelitamar](https://github.com/adbeelitamar).
52
46
 
53
- 0.4.1 (2014/01/11)
54
- ------------------
47
+ ### 0.4.2 (2014/07/01)
48
+
49
+ * [#106](https://github.com/mongoid/mongoid-history/pull/106): Added support for polymorphic relationship `scope` - [@adbeelitamar](https://github.com/adbeelitamar).
50
+ * [#106](https://github.com/mongoid/mongoid-history/pull/106): Enabled specifying an array of relationships in `scope` - [@adbeelitamar](https://github.com/adbeelitamar).
51
+ * [#83](https://github.com/mongoid/mongoid-history/pull/83): Added support for Mongoid 4.x, which removed `attr_accessible` in favor of protected attributes - [@dblock](https://github.com/dblock).
52
+ * [#103](https://github.com/mongoid/mongoid-history/pull/103): Fixed compatibility with models using `default_scope` - [@mrjlynch](https://github.com/mrjlynch).
53
+
54
+ ### 0.4.1 (2014/01/11)
55
55
 
56
56
  * Fixed compatibility with Mongoid 4.x - [@dblock](https://github.com/dblock).
57
57
  * `Mongoid::History::Sweeper` has been removed, in accorance with Mongoid 4.x (see [#3108](https://github.com/mongoid/mongoid/issues/3108)) and Rails 4.x observer deprecation - [@dblock](https://github.com/dblock).
@@ -62,8 +62,7 @@
62
62
  * Replace Jeweler with Gem-Release - [@johnnyshields](https://github.com/johnnyshields).
63
63
  * Track version as a Ruby file - [@johnnyshields](https://github.com/johnnyshields).
64
64
 
65
- 0.4.0 (2013/06/12)
66
- ------------------
65
+ ### 0.4.0 (2013/06/12)
67
66
 
68
67
  * Added `Mongoid::History.disable` and `Mongoid::History.enabled?` methods for global tracking disablement - [@johnnyshields](https://github.com/johnnyshields).
69
68
  * Added `:changes_method` that optionally overrides which method to call to collect changes - [@joelnordel](https://github.com/joelnordell).
@@ -74,67 +73,58 @@
74
73
  * Added `#tracked_changes` and `#tracked_edits` methods to `Tracker` class for nicer change summaries - [@johnnyshields](https://github.com/johnnyshields) and [@tstepp](https://github.com/tstepp).
75
74
  * Refactored and exposed `#trackable_parent_class` in `Tracker`, which returns the class of the trackable regardless of whether the trackable itself has been destroyed - [@johnnyshields](https://github.com/johnnyshields).
76
75
  * Added class-level `#tracked_field?` and `#tracked_fields` methods; refactor logic to determine whether a field is tracked - [@johnnyshields](https://github.com/johnnyshields).
77
- * Fixed bug in Trackable#track_update where `return` condition at beginning of method caused a short-circuit where memoization would not be cleared properly. - [@johnnyshields](https://github.com/johnnyshields).
76
+ * Fixed bug in Trackable#track_update where `return` condition at beginning of method caused a short-circuit where memoization would not be cleared properly - [@johnnyshields](https://github.com/johnnyshields).
78
77
  * Tests: Added spec for nested embedded documents - [@matekb](https://github.com/matekb).
79
78
  * Tests: Test run time cut in half (~2.5s versus ~5s) by using `#let` helper and removing class initialization before each test - [@johnnyshields](https://github.com/johnnyshields).
80
79
  * Tests: Remove `database_cleaner` gem in favor of `Mongoid.purge!` - [@johnnyshields](https://github.com/johnnyshields).
81
80
  * Tests: Remove dependency on non-committed file `mongoid.yml` and hardcode collection to `mongoid_history_test` - [@johnnyshields](https://github.com/johnnyshields).
82
81
 
83
- 0.3.3 (2013/04/01)
84
- ------------------
82
+ ### 0.3.3 (2013/04/01)
85
83
 
86
- * [#42](https://github.com/aq1018/mongoid-history/issues/42): Fix: corrected creation of association chain when using nested embedded documents - [@matekb](https://github.com/matekb).
87
- * [#56](https://github.com/aq1018/mongoid-history/issues/56): Fix: now possible to undo setting (creating) attributes that was previously unset - [@matekb](https://github.com/matekb).
88
- * [#49](https://github.com/aq1018/mongoid-history/issues/49): Fix: now correctly undo/redo localized fields - [@edejong](https://github.com/edejong).
84
+ * [#42](https://github.com/mongoid/mongoid-history/issues/42): Fix: corrected creation of association chain when using nested embedded documents - [@matekb](https://github.com/matekb).
85
+ * [#56](https://github.com/mongoid/mongoid-history/issues/56): Fix: now possible to undo setting (creating) attributes that was previously unset - [@matekb](https://github.com/matekb).
86
+ * [#49](https://github.com/mongoid/mongoid-history/issues/49): Fix: now correctly undo/redo localized fields - [@edejong](https://github.com/edejong).
89
87
 
90
88
 
91
- 0.3.2 (2013/01/24)
92
- ------------------
89
+ ### 0.3.2 (2013/01/24)
93
90
 
94
- * [#54](https://github.com/aq1018/mongoid-history/pull/54): Used an index instead of the `$elemMatch` selector in `history_tracks` - [@vecio](https://github.com/vecio).
95
- * [#11](https://github.com/aq1018/mongoid-history/issues/11): Added `:modifier_field_inverse_of` on `track_history` that defines the `:inverse_of` relationship of the modifier class - [@matekb](https://github.com/matekb), [@dblock](https://github.com/dblock).
91
+ * [#54](https://github.com/mongoid/mongoid-history/pull/54): Used an index instead of the `$elemMatch` selector in `history_tracks` - [@vecio](https://github.com/vecio).
92
+ * [#11](https://github.com/mongoid/mongoid-history/issues/11): Added `:modifier_field_inverse_of` on `track_history` that defines the `:inverse_of` relationship of the modifier class - [@matekb](https://github.com/matekb), [@dblock](https://github.com/dblock).
96
93
 
97
- 0.3.1 (2012/11/16)
98
- ------------------
94
+ ### 0.3.1 (2012/11/16)
99
95
 
100
- * [#45](https://github.com/aq1018/mongoid-history/pull/45): Fix: intermittent hash ordering issue with `history_tracks` - [@getaroom](https://github.com/getaroom).
101
- * [#50](https://github.com/aq1018/mongoid-history/pull/50): Fix: tracking of array changes, undo and redo of field changes on non-embedded objects - [@dblock](https://github.com/dblock).
96
+ * [#45](https://github.com/mongoid/mongoid-history/pull/45): Fix: intermittent hash ordering issue with `history_tracks` - [@getaroom](https://github.com/getaroom).
97
+ * [#50](https://github.com/mongoid/mongoid-history/pull/50): Fix: tracking of array changes, undo and redo of field changes on non-embedded objects - [@dblock](https://github.com/dblock).
102
98
 
103
- 0.3.0 (2012/08/21)
104
- ------------------
99
+ ### 0.3.0 (2012/08/21)
105
100
 
106
- * [#41](https://github.com/aq1018/mongoid-history/pull/41): Mongoid 3.x support - [@zambot](https://github.com/zambot).
101
+ * [#41](https://github.com/mongoid/mongoid-history/pull/41): Mongoid 3.x support - [@zambot](https://github.com/zambot).
107
102
 
108
- 0.2.4 (2012/08/21)
109
- ------------------
103
+ ### 0.2.4 (2012/08/21)
110
104
 
111
- * [#38](https://github.com/aq1018/mongoid-history/pull/38): Fix: allow sub-models to be tracked by using `collection_name` as the scope - [@acant](https://github.com/acant).
112
- * [#35](https://github.com/aq1018/mongoid-history/pull/35): Fix: sweeper references record of change, not the record changed - [@dblock](https://github.com/dblock).
105
+ * [#38](https://github.com/mongoid/mongoid-history/pull/38): Fix: allow sub-models to be tracked by using `collection_name` as the scope - [@acant](https://github.com/acant).
106
+ * [#35](https://github.com/mongoid/mongoid-history/pull/35): Fix: sweeper references record of change, not the record changed - [@dblock](https://github.com/dblock).
113
107
 
114
- 0.2.3 (2012/04/20)
115
- ------------------
108
+ ### 0.2.3 (2012/04/20)
116
109
 
117
- * [#23](https://github.com/aq1018/mongoid-history/pull/34): Updated `Trackable::association_hash` to write through parent - [@tcopple](https://github.com/tcopple).
110
+ * [#23](https://github.com/mongoid/mongoid-history/pull/34): Updated `Trackable::association_hash` to write through parent - [@tcopple](https://github.com/tcopple).
118
111
  * Fix: `Trackable::association_hash` nil meta value call - [@tcopple](https://github.com/tcopple).
119
- * [#27](https://github.com/aq1018/mongoid-history/pull/27): Added support for re-creation of destroyed embedded documents - [@erlingwl](https://github.com/erlingwl).
112
+ * [#27](https://github.com/mongoid/mongoid-history/pull/27): Added support for re-creation of destroyed embedded documents - [@erlingwl](https://github.com/erlingwl).
120
113
 
121
- 0.1.7 (2011/12/09)
122
- ------------------
114
+ ### 0.1.7 (2011/12/09)
123
115
 
124
116
  * Fix: tracking `false` values - [@gottfrois](https://github.com/gottfrois).
125
117
  * Used a mongoid observer and controller `around_filter` to pick up modifying user from controller - [@bensymonds](https://github.com/bensymonds).
126
118
  * More flexible dependency on mongoid - [@sarcilav](https://github.com/sarcilav).
127
119
  * Fix: tracking broken in a multithreaded environment - [@dblock](https://github.com/dblock).
128
120
 
129
- 0.1.0 (2011/05/13)
130
- ------------------
121
+ ### 0.1.0 (2011/05/13)
131
122
 
132
123
  * Added support for `destroy` - [@dblock](https://github.com/dblock).
133
124
  * Added undo and redo - [@aq1018](https://github.com/aq1018).
134
125
  * Added support for temporarily disabling history tracking - [@aq1018](https://github.com/aq1018).
135
126
  * Record modifier for undo and redo actions - [@aq1018](https://github.com/aq1018).
136
127
 
137
- 0.0.1 (2011/03/04)
138
- ------------------
128
+ ### 0.0.1 (2011/03/04)
139
129
 
140
130
  * Intial public release - [@aq1018](https://github.com/aq1018).
data/Gemfile CHANGED
@@ -2,11 +2,11 @@ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
4
 
5
- case version = ENV['MONGOID_VERSION'] || '~> 6.0.0.rc0'
5
+ case version = ENV['MONGOID_VERSION'] || '~> 6.0.0'
6
6
  when 'HEAD'
7
7
  gem 'mongoid', github: 'mongodb/mongoid'
8
8
  when /6/
9
- gem 'mongoid', '~> 6.0.0.rc0'
9
+ gem 'mongoid', '~> 6.0.0'
10
10
  when /5/
11
11
  gem 'mongoid', '~> 5.0'
12
12
  gem 'mongoid-observers', '~> 0.2.0'
@@ -20,7 +20,7 @@ else
20
20
  end
21
21
 
22
22
  group :development, :test do
23
- gem 'rake'
23
+ gem 'rake', '< 11.0'
24
24
  gem 'bundler'
25
25
  end
26
26
 
data/README.md CHANGED
@@ -14,7 +14,7 @@ This gem also implements multi-user undo, which allows users to undo any history
14
14
  Install
15
15
  -------
16
16
 
17
- This gem supports Mongoid 3, 4 and 5 on Ruby 1.9.3 or newer. Add it to your `Gemfile` or run `gem install mongoid-history`.
17
+ This gem supports Mongoid 3, 4, 5 on Ruby 1.9.3 or newer and Mongoid 6 on Ruby 2.2.2+. Add it to your `Gemfile` or run `gem install mongoid-history`.
18
18
 
19
19
  ```ruby
20
20
  gem 'mongoid-history'
@@ -156,6 +156,35 @@ Mongoid::History.disable do
156
156
  end
157
157
  ```
158
158
 
159
+ You may want to track changes on all fields.
160
+
161
+ ```ruby
162
+ class Post
163
+ include Mongoid::Document
164
+ include Mongoid::History::Trackable
165
+
166
+ field :title
167
+ field :body
168
+ field :rating
169
+
170
+ track_history :on => [:fields] # all fields will be tracked
171
+ end
172
+ ```
173
+
174
+ You can also track changes on all embedded relations.
175
+
176
+ ```ruby
177
+ class Post
178
+ include Mongoid::Document
179
+ include Mongoid::History::Trackable
180
+
181
+ embeds_many :comments
182
+ embeds_one :content
183
+
184
+ track_history :on => [:embedded_relations] # all embedded relations will be tracked
185
+ end
186
+ ```
187
+
159
188
  **Include embedded objects attributes in parent audit**
160
189
 
161
190
  Modify above `Post` and `Comment` classes as below:
@@ -279,6 +308,41 @@ end
279
308
 
280
309
  This will skip the `page` documents with `removed_at` set to a non-blank value from nested tracking
281
310
 
311
+ **Formatting fields**
312
+
313
+ You can opt to use a proc or string interpolation to alter attributes being stored on a history record.
314
+
315
+ ```ruby
316
+ class Post
317
+ include Mongoid::Document
318
+ include Mongoid::History::Trackable
319
+
320
+ field :title
321
+ track_history on: :title,
322
+ format: { title: ->(t){ t[0..3] } }
323
+ ```
324
+
325
+ This also works for fields on an embedded relations.
326
+
327
+ ```ruby
328
+ class Book
329
+ include Mongoid::Document
330
+ include Mongoid::History::Trackable
331
+
332
+ embeds_many :pages
333
+ track_history on: :pages,
334
+ format: { pages: { number: 'pg. %d' } }
335
+ end
336
+
337
+ class Page
338
+ include Mongoid::Document
339
+ include Mongoid::History::Trackable
340
+
341
+ field :number, type: Integer
342
+ embedded_in :book
343
+ end
344
+ ```
345
+
282
346
  **Displaying history trackers as an audit trail**
283
347
 
284
348
  In your Controller:
@@ -341,7 +405,7 @@ Since October 2013 (mongoid-history version 0.4.1 and onwards), Mongoid::History
341
405
  instructions above then run the following command:
342
406
 
343
407
  ```
344
- MyHistoryTracker.all.each{|ht| ht.rename(:modifier_id, :created_by)
408
+ MyHistoryTracker.all.rename(modifier_id: :created_by)
345
409
  ```
346
410
 
347
411
  **Setting Modifier Class Name**
@@ -25,6 +25,47 @@ module Mongoid
25
25
  def changes
26
26
  trackable.send(changes_method)
27
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
28
69
  end
29
70
  end
30
71
  end
@@ -11,7 +11,7 @@ module Mongoid
11
11
  else
12
12
  v
13
13
  end
14
- @attributes[k] = [nil, modified]
14
+ @attributes[k] = [nil, format_field(k, modified)]
15
15
  end
16
16
  insert_embeds_one_changes
17
17
  insert_embeds_many_changes
@@ -25,11 +25,10 @@ module Mongoid
25
25
  rel_class = trackable_class.embeds_one_class(rel)
26
26
  paranoia_field = Mongoid::History.trackable_class_settings(rel_class)[:paranoia_field]
27
27
  paranoia_field = rel_class.aliased_fields.key(paranoia_field) || paranoia_field
28
- permitted_attrs = trackable_class.tracked_embeds_one_attributes(rel)
29
28
  rel = aliased_fields.key(rel) || rel
30
29
  obj = trackable.send(rel)
31
30
  next if !obj || (obj.respond_to?(paranoia_field) && obj.public_send(paranoia_field).present?)
32
- @attributes[rel] = [nil, obj.attributes.slice(*permitted_attrs)]
31
+ @attributes[rel] = [nil, format_embeds_one_relation(rel, obj.attributes)]
33
32
  end
34
33
  end
35
34
 
@@ -38,12 +37,11 @@ module Mongoid
38
37
  rel_class = trackable_class.embeds_many_class(rel)
39
38
  paranoia_field = Mongoid::History.trackable_class_settings(rel_class)[:paranoia_field]
40
39
  paranoia_field = rel_class.aliased_fields.key(paranoia_field) || paranoia_field
41
- permitted_attrs = trackable_class.tracked_embeds_many_attributes(rel)
42
40
  rel = aliased_fields.key(rel) || rel
43
41
  @attributes[rel] = [nil,
44
42
  trackable.send(rel)
45
43
  .reject { |obj| obj.respond_to?(paranoia_field) && obj.public_send(paranoia_field).present? }
46
- .map { |obj| obj.attributes.slice(*permitted_attrs) }]
44
+ .map { |obj| format_embeds_many_relation(rel, obj.attributes) }]
47
45
  end
48
46
  end
49
47
  end
@@ -4,7 +4,7 @@ module Mongoid
4
4
  class Destroy < ::Mongoid::History::Attributes::Base
5
5
  def attributes
6
6
  @attributes = {}
7
- trackable.attributes.each { |k, v| @attributes[k] = [v, nil] if trackable_class.tracked_field?(k, :destroy) }
7
+ trackable.attributes.each { |k, v| @attributes[k] = [format_field(k, v), nil] if trackable_class.tracked_field?(k, :destroy) }
8
8
  insert_embeds_one_changes
9
9
  insert_embeds_many_changes
10
10
  @attributes
@@ -16,9 +16,8 @@ module Mongoid
16
16
  trackable_class.tracked_embeds_one
17
17
  .map { |rel| aliased_fields.key(rel) || rel }
18
18
  .each do |rel|
19
- permitted_attrs = trackable_class.tracked_embeds_one_attributes(rel)
20
19
  obj = trackable.send(rel)
21
- @attributes[rel] = [obj.attributes.slice(*permitted_attrs), nil] if obj
20
+ @attributes[rel] = [format_embeds_one_relation(rel, obj.attributes), nil] if obj
22
21
  end
23
22
  end
24
23
 
@@ -26,8 +25,7 @@ module Mongoid
26
25
  trackable_class.tracked_embeds_many
27
26
  .map { |rel| aliased_fields.key(rel) || rel }
28
27
  .each do |rel|
29
- permitted_attrs = trackable_class.tracked_embeds_many_attributes(rel)
30
- @attributes[rel] = [trackable.send(rel).map { |obj| obj.attributes.slice(*permitted_attrs) }, nil]
28
+ @attributes[rel] = [trackable.send(rel).map { |obj| format_embeds_many_relation(rel, obj.attributes) }, nil]
31
29
  end
32
30
  end
33
31
  end
@@ -10,7 +10,7 @@ module Mongoid
10
10
  elsif trackable_class.tracked_embeds_many?(k)
11
11
  insert_embeds_many_changes(k, v)
12
12
  elsif trackable_class.tracked?(k, :update)
13
- @attributes[k] = v
13
+ @attributes[k] = format_field(k, v)
14
14
  end
15
15
  end
16
16
  @attributes
@@ -20,22 +20,22 @@ module Mongoid
20
20
 
21
21
  def insert_embeds_one_changes(relation, value)
22
22
  relation = trackable_class.database_field_name(relation)
23
- permitted_attrs = trackable_class.tracked_embeds_one_attributes(relation)
24
23
  relation_class = trackable_class.embeds_one_class(relation)
25
24
  paranoia_field = Mongoid::History.trackable_class_settings(relation_class)[:paranoia_field]
26
25
  @attributes[relation] = []
27
- @attributes[relation][0] = value[0][paranoia_field].present? ? {} : value[0].slice(*permitted_attrs)
28
- @attributes[relation][1] = value[1][paranoia_field].present? ? {} : value[1].slice(*permitted_attrs)
26
+ @attributes[relation][0] = value[0][paranoia_field].present? ? {} : format_embeds_one_relation(relation, value[0])
27
+ @attributes[relation][1] = value[1][paranoia_field].present? ? {} : format_embeds_one_relation(relation, value[1])
29
28
  end
30
29
 
31
30
  def insert_embeds_many_changes(relation, value)
32
31
  relation = trackable_class.database_field_name(relation)
33
- permitted_attrs = trackable_class.tracked_embeds_many_attributes(relation)
34
32
  relation_class = trackable_class.embeds_many_class(relation)
35
33
  paranoia_field = Mongoid::History.trackable_class_settings(relation_class)[:paranoia_field]
36
34
  @attributes[relation] = []
37
- @attributes[relation][0] = value[0].reject { |rel| rel[paranoia_field].present? }.map { |v_attrs| v_attrs.slice(*permitted_attrs) }
38
- @attributes[relation][1] = value[1].reject { |rel| rel[paranoia_field].present? }.map { |v_attrs| v_attrs.slice(*permitted_attrs) }
35
+ @attributes[relation][0] = value[0].reject { |rel| rel[paranoia_field].present? }
36
+ .map { |v_attrs| format_embeds_many_relation(relation, v_attrs) }
37
+ @attributes[relation][1] = value[1].reject { |rel| rel[paranoia_field].present? }
38
+ .map { |v_attrs| format_embeds_many_relation(relation, v_attrs) }
39
39
  end
40
40
  end
41
41
  end
@@ -14,6 +14,7 @@ module Mongoid
14
14
  def parse(options = {})
15
15
  @options = default_options.merge(options)
16
16
  prepare_skipped_fields
17
+ prepare_formatted_fields
17
18
  parse_tracked_fields_and_relations
18
19
  @options
19
20
  end
@@ -31,7 +32,8 @@ module Mongoid
31
32
  scope: scope,
32
33
  track_create: false,
33
34
  track_update: true,
34
- track_destroy: false }
35
+ track_destroy: false,
36
+ format: nil }
35
37
  end
36
38
 
37
39
  # Sets the :except attributes and relations in `options` to be an [ Array <String> ]
@@ -43,6 +45,30 @@ module Mongoid
43
45
  @options[:except] = options[:except].map { |field| trackable.database_field_name(field) }.compact.uniq
44
46
  end
45
47
 
48
+ def prepare_formatted_fields
49
+ formats = {}
50
+
51
+ if options[:format].class == Hash
52
+ options[:format].each do |field, format|
53
+ next if field.nil?
54
+
55
+ field = trackable.database_field_name(field)
56
+
57
+ if format.class == Hash && trackable.embeds_many?(field)
58
+ relation_class = trackable.embeds_many_class(field)
59
+ formats[field] = format.inject({}) { |a, e| a.merge(relation_class.database_field_name(e.first) => e.last) }
60
+ elsif format.class == Hash && trackable.embeds_one?(field)
61
+ relation_class = trackable.embeds_one_class(field)
62
+ formats[field] = format.inject({}) { |a, e| a.merge(relation_class.database_field_name(e.first) => e.last) }
63
+ else
64
+ formats[field] = format
65
+ end
66
+ end
67
+ end
68
+
69
+ options[:format] = formats
70
+ end
71
+
46
72
  def parse_tracked_fields_and_relations
47
73
  # case `options[:on]`
48
74
  # when `posts: [:id, :title]`, then it will convert it to `[[:posts, [:id, :title]]]`
@@ -64,6 +90,11 @@ module Mongoid
64
90
  @options[:on] = options[:on] | trackable.fields.keys.map(&:to_sym) - reserved_fields.map(&:to_sym)
65
91
  end
66
92
 
93
+ if options[:on].include?(:embedded_relations)
94
+ @options[:on] = options[:on].reject { |opt| opt == :embedded_relations }
95
+ @options[:on] = options[:on] | trackable.embedded_relations.keys
96
+ end
97
+
67
98
  @options[:fields] = []
68
99
  @options[:dynamic] = []
69
100
  @options[:relations] = { embeds_one: {}, embeds_many: {} }
@@ -241,7 +241,7 @@ module Mongoid
241
241
  end
242
242
 
243
243
  def track_destroy
244
- track_history_for_action(:destroy)
244
+ track_history_for_action(:destroy) unless destroyed?
245
245
  end
246
246
 
247
247
  def clear_trackable_memoization
@@ -387,6 +387,10 @@ module Mongoid
387
387
  !embedded_relations.map { |_, v| v.key }.include?(database_field_name(field))
388
388
  end
389
389
 
390
+ def field_format(field)
391
+ field_formats[database_field_name(field)]
392
+ end
393
+
390
394
  # Retrieves the list of tracked fields for a given action.
391
395
  #
392
396
  # @param [ String | Symbol ] action The action name (:create, :update, or :destroy)
@@ -413,6 +417,10 @@ module Mongoid
413
417
  @reserved_tracked_fields ||= ['_id', history_trackable_options[:version_field].to_s, "#{history_trackable_options[:modifier_field]}_id"]
414
418
  end
415
419
 
420
+ def field_formats
421
+ @field_formats ||= history_trackable_options[:format]
422
+ end
423
+
416
424
  # Whether or not the relation should be tracked.
417
425
  #
418
426
  # @param [ String | Symbol ] relation The name of the relation
@@ -485,6 +493,7 @@ module Mongoid
485
493
  @tracked_fields = nil
486
494
  @tracked_embeds_one = nil
487
495
  @tracked_embeds_many = nil
496
+ @obfuscated_fields = nil
488
497
  end
489
498
  end
490
499
  end
@@ -1,5 +1,5 @@
1
1
  module Mongoid
2
2
  module History
3
- VERSION = '0.6.0'
3
+ VERSION = '0.6.1'
4
4
  end
5
5
  end
@@ -8,7 +8,7 @@ Gem::Specification.new do |s|
8
8
  s.summary = 'Track and audit, undo and redo changes on Mongoid documents.'
9
9
  s.description = 'This library tracks historical changes for any document, including embedded ones. It achieves this by storing all history tracks in a single collection that you define. Embedded documents are referenced by storing an association path, which is an array of document_name and document_id fields starting from the top most parent document and down to the embedded document that should track history. Mongoid-history implements multi-user undo, which allows users to undo any history change in any order. Undoing a document also creates a new history track. This is great for auditing and preventing vandalism, but it is probably not suitable for use cases such as a wiki.'
10
10
  s.email = ['aq1018@gmail.com', 'justin.mgrimes@gmail.com', 'dblock@dblock.org']
11
- s.homepage = 'http://github.com/aq1018/mongoid-history'
11
+ s.homepage = 'http://github.com/mongoid/mongoid-history'
12
12
  s.license = 'MIT'
13
13
 
14
14
  s.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
@@ -136,6 +136,13 @@ describe Mongoid::History do
136
136
  post.destroy
137
137
  expect(post.history_tracks.last.affected['title']).to eq('Test')
138
138
  end
139
+
140
+ it 'should no-op on repeated calls to destroy' do
141
+ post.destroy
142
+ expect do
143
+ post.destroy
144
+ end.not_to change(Tracker, :count)
145
+ end
139
146
  end
140
147
 
141
148
  describe 'on update non-embedded' do
@@ -13,6 +13,18 @@ describe Mongoid::History::Attributes::Base do
13
13
  end
14
14
  end
15
15
 
16
+ before :all do
17
+ class ModelTwo
18
+ include Mongoid::Document
19
+ field :foo
20
+ field :goo
21
+ end
22
+ end
23
+
24
+ after :all do
25
+ Object.send(:remove_const, :ModelTwo)
26
+ end
27
+
16
28
  let(:obj_one) { model_one.new }
17
29
  let(:base) { described_class.new(obj_one) }
18
30
  subject { base }
@@ -51,4 +63,88 @@ describe Mongoid::History::Attributes::Base do
51
63
  subject { base.send(:changes) }
52
64
  it { is_expected.to eq('foo' => ['Foo', 'Foo-new']) }
53
65
  end
66
+
67
+ describe '#format_field' do
68
+ before(:each) do
69
+ model_one.instance_variable_set(:@history_trackable_options, nil)
70
+ end
71
+
72
+ subject { base.send(:format_field, :bar, 'foo') }
73
+
74
+ context 'when formatted via string' do
75
+ before do
76
+ model_one.track_history format: { bar: '*%s*' }
77
+ end
78
+
79
+ it { is_expected.to eq '*foo*' }
80
+ end
81
+
82
+ context 'when formatted via proc' do
83
+ before do
84
+ model_one.track_history format: { bar: ->(v) { v * 2 } }
85
+ end
86
+
87
+ it { is_expected.to eq 'foofoo' }
88
+ end
89
+
90
+ context 'when not formatted' do
91
+ before do
92
+ model_one.track_history
93
+ end
94
+
95
+ it { is_expected.to eq 'foo' }
96
+ end
97
+ end
98
+
99
+ shared_examples 'formats embedded relation' do |relation_type|
100
+ let(:model_two) { ModelTwo.new(foo: :bar, goo: :baz) }
101
+
102
+ before :each do
103
+ model_one.instance_variable_set(:@history_trackable_options, nil)
104
+ model_one.send(relation_type, :model_two)
105
+ end
106
+
107
+ subject { base.send("format_#{relation_type}_relation", :model_two, model_two.attributes) }
108
+
109
+ context 'with permitted attributes' do
110
+ before do
111
+ model_one.track_history on: { model_two: %i(foo) }
112
+ end
113
+
114
+ it 'should select only permitted attributes' do
115
+ is_expected.to include('foo' => :bar)
116
+ is_expected.to_not include('goo')
117
+ end
118
+ end
119
+
120
+ context 'with attributes formatted via string' do
121
+ before do
122
+ model_one.track_history on: { model_two: %i(foo) }, format: { model_two: { foo: '&%s&' } }
123
+ end
124
+
125
+ it 'should select obfuscate permitted attributes' do
126
+ is_expected.to include('foo' => '&bar&')
127
+ is_expected.to_not include('goo')
128
+ end
129
+ end
130
+
131
+ context 'with attributes formatted via proc' do
132
+ before do
133
+ model_one.track_history on: { model_two: %i(foo) }, format: { model_two: { foo: ->(v) { v.to_s * 2 } } }
134
+ end
135
+
136
+ it 'should select obfuscate permitted attributes' do
137
+ is_expected.to include('foo' => 'barbar')
138
+ is_expected.to_not include('goo')
139
+ end
140
+ end
141
+ end
142
+
143
+ describe '#format_embeds_one_relation' do
144
+ include_examples 'formats embedded relation', :embeds_one
145
+ end
146
+
147
+ describe '#format_embeds_many_relation' do
148
+ include_examples 'formats embedded relation', :embeds_many
149
+ end
54
150
  end
@@ -69,7 +69,8 @@ describe Mongoid::History::Options do
69
69
  scope: :model_one,
70
70
  track_create: false,
71
71
  track_update: true,
72
- track_destroy: false }
72
+ track_destroy: false,
73
+ format: nil }
73
74
  end
74
75
  it { expect(service.send(:default_options)).to eq expected_options }
75
76
  end
@@ -104,6 +105,26 @@ describe Mongoid::History::Options do
104
105
  end
105
106
  end
106
107
 
108
+ describe '#prepare_formatted_fields' do
109
+ let(:options) { { format: value } }
110
+ subject { service.parse(options) }
111
+
112
+ context 'with non-hash' do
113
+ let(:value) { :foo }
114
+ it { expect(subject[:format]).to eq({}) }
115
+ end
116
+
117
+ context 'with a field format' do
118
+ let(:value) { { foo: '&&&' } }
119
+ it { expect(subject[:format]).to include 'foo' => '&&&' }
120
+ end
121
+
122
+ context 'with nested format' do
123
+ let(:value) { { emb_one: { f_em_foo: '***' } } }
124
+ it { expect(subject[:format]).to include 'emb_one' => { 'f_em_foo' => '***' } }
125
+ end
126
+ end
127
+
107
128
  describe '#parse_tracked_fields_and_relations' do
108
129
  context 'when options not passed' do
109
130
  let(:expected_options) do
@@ -119,7 +140,8 @@ describe Mongoid::History::Options do
119
140
  track_destroy: false,
120
141
  fields: %w(foo b),
121
142
  dynamic: [],
122
- relations: { embeds_one: {}, embeds_many: {} } }
143
+ relations: { embeds_one: {}, embeds_many: {} },
144
+ format: {} }
123
145
  end
124
146
  it { expect(service.parse).to eq expected_options }
125
147
  end
@@ -232,6 +254,16 @@ describe Mongoid::History::Options do
232
254
  let(:options) { { on: :my_field } }
233
255
  it { expect(subject[:dynamic]).to eq %w(my_field) }
234
256
  end
257
+
258
+ context 'with relations' do
259
+ let(:options) { { on: :embedded_relations } }
260
+ it do
261
+ expect(subject[:relations]).to eq(embeds_many: { 'emb_threes' => %w(_id f_em_foo fmb),
262
+ 'emfs' => %w(_id f_em_baz) },
263
+ embeds_one: { 'emb_one' => %w(_id f_em_foo fmb),
264
+ 'emtw' => %w(_id f_em_baz) })
265
+ end
266
+ end
235
267
  end
236
268
  end
237
269
 
@@ -46,7 +46,8 @@ describe Mongoid::History::Trackable do
46
46
  track_destroy: false,
47
47
  fields: %w(foo),
48
48
  relations: { embeds_one: {}, embeds_many: {} },
49
- dynamic: [] }
49
+ dynamic: [],
50
+ format: {} }
50
51
  end
51
52
  let(:regular_fields) { ['foo'] }
52
53
  let(:reserved_fields) { %w(_id version modifier_id) }
@@ -151,6 +152,38 @@ describe Mongoid::History::Trackable do
151
152
  end
152
153
  end
153
154
 
155
+ describe '#field_format' do
156
+ before :all do
157
+ ModelOne = Class.new do
158
+ include Mongoid::Document
159
+ include Mongoid::History::Trackable
160
+ field :foo
161
+ end
162
+ end
163
+
164
+ let(:format) { '***' }
165
+
166
+ before do
167
+ ModelOne.track_history format: { foo: format }
168
+ end
169
+
170
+ context 'when field is formatted' do
171
+ it 'should return the format' do
172
+ expect(ModelOne.field_format(:foo)).to be format
173
+ end
174
+ end
175
+
176
+ context 'when field is not formatted' do
177
+ it 'should return nil' do
178
+ expect(ModelOne.field_format(:bar)).to be_nil
179
+ end
180
+ end
181
+
182
+ after :all do
183
+ Object.send(:remove_const, :ModelOne)
184
+ end
185
+ end
186
+
154
187
  context 'sub-model' do
155
188
  before :each do
156
189
  class MySubModel < MyModel
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.6.0
4
+ version: 0.6.1
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: 2016-09-13 00:00:00.000000000 Z
13
+ date: 2017-01-04 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: easy_diff
@@ -132,7 +132,7 @@ files:
132
132
  - spec/unit/store/request_store_spec.rb
133
133
  - spec/unit/trackable_spec.rb
134
134
  - spec/unit/tracker_spec.rb
135
- homepage: http://github.com/aq1018/mongoid-history
135
+ homepage: http://github.com/mongoid/mongoid-history
136
136
  licenses:
137
137
  - MIT
138
138
  metadata: {}