mongoid-history 0.0.9 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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.9
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 history_tracker_attributes
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((new_record? ? modified_attributes_for_create : modified_attributes_for_update))
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
- trackable.update_attributes!(undo_attr(modifier))
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
- trackable.update_attributes!(redo_attr(modifier))
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] = trackable.attributes[k]; h}
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 ||= triverse_association_chain
77
+ @trackable_parents_and_trackable ||= traverse_association_chain
66
78
  end
67
79
 
68
- def triverse_association_chain
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
@@ -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.9"
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-04-05}
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.2}
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 :except => [:email]
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
@@ -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.9
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-04-05 00:00:00 -07:00
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: 2391533013898856093
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.2
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