mongoid-history 0.0.9 → 0.1.0
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.
- data/README.rdoc +9 -2
- data/VERSION +1 -1
- data/lib/mongoid/history/trackable.rb +28 -6
- data/lib/mongoid/history/tracker.rb +18 -6
- data/mongoid-history.gemspec +3 -3
- data/spec/integration/integration_spec.rb +45 -3
- data/spec/trackable_spec.rb +6 -1
- metadata +4 -4
data/README.rdoc
CHANGED
|
@@ -42,6 +42,7 @@ Here is a quick example on how to use this plugin. For more details, please look
|
|
|
42
42
|
:modifier_field => :modifier, # Adds "referened_in :modifier" to track who made the change. Default is :modifier
|
|
43
43
|
:version_field => :version, # Adds "field :version, :type => Integer" to track current version. Default is :version
|
|
44
44
|
:track_create => false, # Do you want to track document creation? Default is false
|
|
45
|
+
:track_destroy => false, # Do you want to track document destruction? Default is false
|
|
45
46
|
end
|
|
46
47
|
|
|
47
48
|
class Comment
|
|
@@ -56,8 +57,8 @@ Here is a quick example on how to use this plugin. For more details, please look
|
|
|
56
57
|
embedded_in :post, :inverse_of => :comments
|
|
57
58
|
|
|
58
59
|
# Track title and body for all comments, scope it to post (the parent)
|
|
59
|
-
# Also track creation
|
|
60
|
-
track_history :on => [:title, :body], :scope => :post, :track_create => true
|
|
60
|
+
# Also track creation and destruction
|
|
61
|
+
track_history :on => [:title, :body], :scope => :post, :track_create => true, :track_destroy => true
|
|
61
62
|
end
|
|
62
63
|
|
|
63
64
|
# The modifier can be specified as well
|
|
@@ -96,6 +97,12 @@ Here is a quick example on how to use this plugin. For more details, please look
|
|
|
96
97
|
|
|
97
98
|
# redo last 3 versions
|
|
98
99
|
comment.redo! @user, :last => 3
|
|
100
|
+
|
|
101
|
+
# delete post
|
|
102
|
+
post.destroy
|
|
103
|
+
|
|
104
|
+
# undelete post
|
|
105
|
+
post.undo! @user
|
|
99
106
|
|
|
100
107
|
== Contributing to mongoid-history
|
|
101
108
|
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.0
|
|
1
|
+
0.1.0
|
|
@@ -11,7 +11,8 @@ module Mongoid::History
|
|
|
11
11
|
:modifier_field => :modifier,
|
|
12
12
|
:version_field => :version,
|
|
13
13
|
:scope => model_name,
|
|
14
|
-
:track_create => false
|
|
14
|
+
:track_create => false,
|
|
15
|
+
:track_destroy => false,
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
options = default_options.merge(options)
|
|
@@ -42,6 +43,7 @@ module Mongoid::History
|
|
|
42
43
|
|
|
43
44
|
before_update :track_update
|
|
44
45
|
before_create :track_create if options[:track_create]
|
|
46
|
+
after_destroy :track_destroy if options[:track_destroy]
|
|
45
47
|
|
|
46
48
|
Mongoid::History.trackable_classes ||= []
|
|
47
49
|
Mongoid::History.trackable_classes << self
|
|
@@ -146,7 +148,15 @@ module Mongoid::History
|
|
|
146
148
|
end
|
|
147
149
|
end
|
|
148
150
|
|
|
149
|
-
def
|
|
151
|
+
def modified_attributes_for_destroy
|
|
152
|
+
@modified_attributes_for_destroy ||= attributes.inject({}) do |h, pair|
|
|
153
|
+
k,v = pair
|
|
154
|
+
h[k] = [nil, v]
|
|
155
|
+
h
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def history_tracker_attributes(method)
|
|
150
160
|
return @history_tracker_attributes if @history_tracker_attributes
|
|
151
161
|
|
|
152
162
|
@history_tracker_attributes = {
|
|
@@ -155,7 +165,12 @@ module Mongoid::History
|
|
|
155
165
|
:modifier => send(history_trackable_options[:modifier_field])
|
|
156
166
|
}
|
|
157
167
|
|
|
158
|
-
original, modified = transform_changes(
|
|
168
|
+
original, modified = transform_changes(case method
|
|
169
|
+
when :destroy then modified_attributes_for_destroy
|
|
170
|
+
when :create then modified_attributes_for_create
|
|
171
|
+
else modified_attributes_for_update
|
|
172
|
+
end)
|
|
173
|
+
|
|
159
174
|
@history_tracker_attributes[:original] = original
|
|
160
175
|
@history_tracker_attributes[:modified] = modified
|
|
161
176
|
@history_tracker_attributes
|
|
@@ -165,7 +180,7 @@ module Mongoid::History
|
|
|
165
180
|
return unless should_track_update?
|
|
166
181
|
current_version = (self.send(history_trackable_options[:version_field]) || 0 ) + 1
|
|
167
182
|
self.send("#{history_trackable_options[:version_field]}=", current_version)
|
|
168
|
-
Mongoid::History.tracker_class.create!(history_tracker_attributes.merge(:version => current_version))
|
|
183
|
+
Mongoid::History.tracker_class.create!(history_tracker_attributes(:update).merge(:version => current_version, :action => "update"))
|
|
169
184
|
clear_memoization
|
|
170
185
|
end
|
|
171
186
|
|
|
@@ -173,7 +188,14 @@ module Mongoid::History
|
|
|
173
188
|
return unless track_history?
|
|
174
189
|
current_version = (self.send(history_trackable_options[:version_field]) || 0 ) + 1
|
|
175
190
|
self.send("#{history_trackable_options[:version_field]}=", current_version)
|
|
176
|
-
Mongoid::History.tracker_class.create!(history_tracker_attributes.merge(:version => current_version))
|
|
191
|
+
Mongoid::History.tracker_class.create!(history_tracker_attributes(:create).merge(:version => current_version, :action => "create"))
|
|
192
|
+
clear_memoization
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def track_destroy
|
|
196
|
+
return unless track_history?
|
|
197
|
+
current_version = (self.send(history_trackable_options[:version_field]) || 0 ) + 1
|
|
198
|
+
Mongoid::History.tracker_class.create!(history_tracker_attributes(:destroy).merge(:version => current_version, :action => "destroy"))
|
|
177
199
|
clear_memoization
|
|
178
200
|
end
|
|
179
201
|
|
|
@@ -205,4 +227,4 @@ module Mongoid::History
|
|
|
205
227
|
end
|
|
206
228
|
|
|
207
229
|
end
|
|
208
|
-
end
|
|
230
|
+
end
|
|
@@ -10,6 +10,7 @@ module Mongoid::History
|
|
|
10
10
|
field :modified, :type => Hash
|
|
11
11
|
field :original, :type => Hash
|
|
12
12
|
field :version, :type => Integer
|
|
13
|
+
field :action, :type => String
|
|
13
14
|
field :scope, :type => String
|
|
14
15
|
referenced_in :modifier, :class_name => Mongoid::History.modifer_class_name
|
|
15
16
|
|
|
@@ -21,11 +22,21 @@ module Mongoid::History
|
|
|
21
22
|
end
|
|
22
23
|
|
|
23
24
|
def undo!(modifier)
|
|
24
|
-
|
|
25
|
+
if action.to_sym == :destroy
|
|
26
|
+
class_name = association_chain[0]["name"]
|
|
27
|
+
restored = class_name.constantize.new(modified)
|
|
28
|
+
restored.save!
|
|
29
|
+
else
|
|
30
|
+
trackable.update_attributes!(undo_attr(modifier))
|
|
31
|
+
end
|
|
25
32
|
end
|
|
26
33
|
|
|
27
34
|
def redo!(modifier)
|
|
28
|
-
|
|
35
|
+
if action.to_sym == :destroy
|
|
36
|
+
trackable.destroy
|
|
37
|
+
else
|
|
38
|
+
trackable.update_attributes!(redo_attr(modifier))
|
|
39
|
+
end
|
|
29
40
|
end
|
|
30
41
|
|
|
31
42
|
def undo_attr(modifier)
|
|
@@ -57,15 +68,16 @@ module Mongoid::History
|
|
|
57
68
|
end
|
|
58
69
|
|
|
59
70
|
def affected
|
|
60
|
-
@affected ||= (modified.keys | original.keys).inject({}){ |h,k| h[k] =
|
|
71
|
+
@affected ||= (modified.keys | original.keys).inject({}){ |h,k| h[k] =
|
|
72
|
+
trackable ? trackable.attributes[k] : modified[k]; h}
|
|
61
73
|
end
|
|
62
74
|
|
|
63
75
|
private
|
|
64
76
|
def trackable_parents_and_trackable
|
|
65
|
-
@trackable_parents_and_trackable ||=
|
|
77
|
+
@trackable_parents_and_trackable ||= traverse_association_chain
|
|
66
78
|
end
|
|
67
79
|
|
|
68
|
-
def
|
|
80
|
+
def traverse_association_chain
|
|
69
81
|
chain = association_chain.dup
|
|
70
82
|
doc = nil
|
|
71
83
|
documents = []
|
|
@@ -80,4 +92,4 @@ private
|
|
|
80
92
|
end
|
|
81
93
|
|
|
82
94
|
end
|
|
83
|
-
end
|
|
95
|
+
end
|
data/mongoid-history.gemspec
CHANGED
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
|
|
6
6
|
Gem::Specification.new do |s|
|
|
7
7
|
s.name = %q{mongoid-history}
|
|
8
|
-
s.version = "0.0
|
|
8
|
+
s.version = "0.1.0"
|
|
9
9
|
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
|
11
11
|
s.authors = ["Aaron Qian", "Justin Grimes"]
|
|
12
|
-
s.date = %q{2011-
|
|
12
|
+
s.date = %q{2011-05-13}
|
|
13
13
|
s.description = %q{In frustration of Mongoid::Versioning, I created this plugin for tracking historical changes for any document, including embedded ones. It achieves this by storing all history tracks in a single collection that you define. (See Usage for more details) 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.
|
|
14
14
|
|
|
15
15
|
This plugin 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.}
|
|
@@ -40,7 +40,7 @@ Gem::Specification.new do |s|
|
|
|
40
40
|
s.homepage = %q{http://github.com/aq1018/mongoid-history}
|
|
41
41
|
s.licenses = ["MIT"]
|
|
42
42
|
s.require_paths = ["lib"]
|
|
43
|
-
s.rubygems_version = %q{1.5.
|
|
43
|
+
s.rubygems_version = %q{1.5.3}
|
|
44
44
|
s.summary = %q{history tracking, auditing, undo, redo for mongoid}
|
|
45
45
|
s.test_files = [
|
|
46
46
|
"spec/integration/integration_spec.rb",
|
|
@@ -16,7 +16,7 @@ describe Mongoid::History do
|
|
|
16
16
|
field :rating
|
|
17
17
|
|
|
18
18
|
embeds_many :comments
|
|
19
|
-
track_history :on => [:title, :body]
|
|
19
|
+
track_history :on => [:title, :body], :track_destroy => true
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
class Comment
|
|
@@ -37,7 +37,7 @@ describe Mongoid::History do
|
|
|
37
37
|
|
|
38
38
|
field :email
|
|
39
39
|
field :name
|
|
40
|
-
track_history
|
|
40
|
+
track_history :except => [:email]
|
|
41
41
|
end
|
|
42
42
|
end
|
|
43
43
|
|
|
@@ -62,7 +62,6 @@ describe Mongoid::History do
|
|
|
62
62
|
@comment.history_tracks.first.original.should == {}
|
|
63
63
|
end
|
|
64
64
|
|
|
65
|
-
|
|
66
65
|
it "should assign modifier" do
|
|
67
66
|
@comment.history_tracks.first.modifier.should == @user
|
|
68
67
|
end
|
|
@@ -74,12 +73,35 @@ describe Mongoid::History do
|
|
|
74
73
|
it "should assign scope" do
|
|
75
74
|
@comment.history_tracks.first.scope == "Post"
|
|
76
75
|
end
|
|
76
|
+
|
|
77
|
+
it "should assign method" do
|
|
78
|
+
@comment.history_tracks.first.action == "create"
|
|
79
|
+
end
|
|
77
80
|
|
|
78
81
|
it "should assign association_chain" do
|
|
79
82
|
@comment.history_tracks.first.association_chain = [{:id => @post.id, :name => "Post"}, {:id => @comment.id, :name => "Comment"}]
|
|
80
83
|
end
|
|
81
84
|
end
|
|
82
85
|
|
|
86
|
+
describe "on destruction" do
|
|
87
|
+
it "should have two history track records in post" do
|
|
88
|
+
lambda {
|
|
89
|
+
@post.destroy
|
|
90
|
+
}.should change(HistoryTracker, :count).by(1)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it "should assign destroy on track record" do
|
|
94
|
+
@post.destroy
|
|
95
|
+
@post.history_tracks.last.action == "destroy"
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it "should return affected attributes from track record" do
|
|
99
|
+
@post.destroy
|
|
100
|
+
@post.history_tracks.last.affected["title"] == "Test"
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
end
|
|
104
|
+
|
|
83
105
|
describe "on update non-embedded" do
|
|
84
106
|
it "should create a history track if changed attributes match tracked attributes" do
|
|
85
107
|
lambda {
|
|
@@ -99,6 +121,11 @@ describe Mongoid::History do
|
|
|
99
121
|
"title" => "Another Test"
|
|
100
122
|
}
|
|
101
123
|
end
|
|
124
|
+
|
|
125
|
+
it "should assign method field" do
|
|
126
|
+
@post.update_attributes(:title => "Another Test")
|
|
127
|
+
@post.history_tracks.first.action.should == "update"
|
|
128
|
+
end
|
|
102
129
|
|
|
103
130
|
it "should assign original fields" do
|
|
104
131
|
@post.update_attributes(:title => "Another Test")
|
|
@@ -221,6 +248,12 @@ describe Mongoid::History do
|
|
|
221
248
|
@post.reload
|
|
222
249
|
@post.title.should == "Test"
|
|
223
250
|
end
|
|
251
|
+
|
|
252
|
+
it "should undo destruction" do
|
|
253
|
+
@post.destroy
|
|
254
|
+
@post.history_tracks.where(:version => 1).first.undo!(@user)
|
|
255
|
+
Post.find(@post.id).title.should == "Test"
|
|
256
|
+
end
|
|
224
257
|
|
|
225
258
|
it "should create a new history track after undo" do
|
|
226
259
|
@post.update_attributes(:title => "Test2")
|
|
@@ -245,6 +278,15 @@ describe Mongoid::History do
|
|
|
245
278
|
|
|
246
279
|
@post.title.should == @post2.title
|
|
247
280
|
end
|
|
281
|
+
|
|
282
|
+
it "should be destroyed after undo and redo" do
|
|
283
|
+
@post.destroy
|
|
284
|
+
@track = @post.history_tracks.where(:version => 1).first
|
|
285
|
+
@track.undo!(@user)
|
|
286
|
+
@track.redo!(@user)
|
|
287
|
+
Post.where(:_id => @post.id).first == nil
|
|
288
|
+
end
|
|
289
|
+
|
|
248
290
|
end
|
|
249
291
|
|
|
250
292
|
describe "embedded" do
|
data/spec/trackable_spec.rb
CHANGED
|
@@ -43,7 +43,8 @@ describe Mongoid::History::Trackable do
|
|
|
43
43
|
:version_field => :version,
|
|
44
44
|
:scope => :my_model,
|
|
45
45
|
:except => ["created_at", "updated_at", "version", "modifier_id", "_id", "id"],
|
|
46
|
-
:track_create => false
|
|
46
|
+
:track_create => false,
|
|
47
|
+
:track_destroy => false,
|
|
47
48
|
}
|
|
48
49
|
end
|
|
49
50
|
|
|
@@ -64,6 +65,10 @@ describe Mongoid::History::Trackable do
|
|
|
64
65
|
MyModel.new.private_methods.collect(&:to_sym).should include(:track_create)
|
|
65
66
|
end
|
|
66
67
|
|
|
68
|
+
it "should define callback function #track_destroy" do
|
|
69
|
+
MyModel.new.private_methods.collect(&:to_sym).should include(:track_destroy)
|
|
70
|
+
end
|
|
71
|
+
|
|
67
72
|
it "should define #history_trackable_options" do
|
|
68
73
|
MyModel.history_trackable_options.should == @expected_option
|
|
69
74
|
end
|
metadata
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: mongoid-history
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease:
|
|
5
|
-
version: 0.0
|
|
5
|
+
version: 0.1.0
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
8
8
|
- Aaron Qian
|
|
@@ -11,7 +11,7 @@ autorequire:
|
|
|
11
11
|
bindir: bin
|
|
12
12
|
cert_chain: []
|
|
13
13
|
|
|
14
|
-
date: 2011-
|
|
14
|
+
date: 2011-05-13 00:00:00 -07:00
|
|
15
15
|
default_executable:
|
|
16
16
|
dependencies:
|
|
17
17
|
- !ruby/object:Gem::Dependency
|
|
@@ -170,7 +170,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
170
170
|
requirements:
|
|
171
171
|
- - ">="
|
|
172
172
|
- !ruby/object:Gem::Version
|
|
173
|
-
hash:
|
|
173
|
+
hash: -1260875336228097140
|
|
174
174
|
segments:
|
|
175
175
|
- 0
|
|
176
176
|
version: "0"
|
|
@@ -183,7 +183,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
183
183
|
requirements: []
|
|
184
184
|
|
|
185
185
|
rubyforge_project:
|
|
186
|
-
rubygems_version: 1.5.
|
|
186
|
+
rubygems_version: 1.5.3
|
|
187
187
|
signing_key:
|
|
188
188
|
specification_version: 3
|
|
189
189
|
summary: history tracking, auditing, undo, redo for mongoid
|