paper_trail 1.5.1 → 1.5.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -25,7 +25,7 @@ PaperTrail lets you track changes to your models' data. It's good for auditing
25
25
 
26
26
  ## Rails Version
27
27
 
28
- Known to work on Rails 2.3. Probably works on Rails 2.2 and 2.1.
28
+ Reported to work on Rails 3 (though I haven't yet tried myself). Known to work on Rails 2.3. Probably works on Rails 2.2 and 2.1.
29
29
 
30
30
 
31
31
  ## Basic Usage
@@ -192,6 +192,25 @@ In a migration or in `script/console` you can set who is responsible like this:
192
192
  >> widget.update_attributes :name => 'Wibble'
193
193
  >> widget.versions.last.whodunnit # Andy Stewart
194
194
 
195
+ N.B. A `version`'s `whodunnit` records who changed the object causing the `version` to be stored. Because a `version` stores the object as it looked before the change (see the table above), `whodunnit` returns who stopped the object looking like this -- not who made it look like this. Hence `whodunnit` is aliased as `terminator`.
196
+
197
+ To find out who made a `version`'s object look that way, use `version.originator`. And to find out who made a "live" object look like it does, use `originator` on the object.
198
+
199
+ >> widget = Widget.find 153 # assume widget has 0 versions
200
+ >> PaperTrail.whodunnit = 'Alice'
201
+ >> widget.update_attributes :name => 'Yankee'
202
+ >> widget.originator # 'Alice'
203
+ >> PaperTrail.whodunnit = 'Bob'
204
+ >> widget.update_attributes :name => 'Zulu'
205
+ >> widget.originator # 'Bob'
206
+ >> first_version, last_version = widget.versions.first, widget.versions.last
207
+ >> first_version.whodunnit # 'Alice'
208
+ >> first_version.originator # nil
209
+ >> first_version.terminator # 'Alice'
210
+ >> last_version.whodunnit # 'Bob'
211
+ >> last_version.originator # 'Alice'
212
+ >> last_version.terminator # 'Bob'
213
+
195
214
 
196
215
  ## Storing metadata
197
216
 
@@ -220,6 +239,26 @@ You can also store any information you like from your controller. Just override
220
239
  Remember to add those extra columns to your `versions` table ;)
221
240
 
222
241
 
242
+ ## Diffing Versions
243
+
244
+ When you're storing every version of an object, as PaperTrail lets you do, you're almost certainly going to want to diff those versions against each other. However I haven't built a diff method into PaperTrail because I think diffing is best left to dedicated libraries, and also it's hard to come up with a diff method to suit all the use cases.
245
+
246
+ You might be surprised that PaperTrail doesn't use diffs internally anyway. When I designed PaperTrail I wanted simplicity and robustness so I decided to make each version of an object self-contained. A version stores all of its object's data, not a diff from the previous version.
247
+
248
+ So instead here are some specialised diffing libraries which you can use on top of PaperTrail.
249
+
250
+ For diffing two strings:
251
+
252
+ * [htmldiff](http://github.com/myobie/htmldiff): expects but doesn't require HTML input and produces HTML output. Works very well but slows down significantly on large (e.g. 5,000 word) inputs.
253
+ * [differ](http://github.com/pvande/differ): expects plain text input and produces plain text/coloured/HTML/any output. Can do character-wise, word-wise, line-wise, or arbitrary-boundary-string-wise diffs. Works very well on non-HTML input.
254
+ * [diff-lcs](http://github.com/halostatue/ruwiki/tree/master/diff-lcs/trunk): old-school, line-wise diffs.
255
+
256
+ For diffing two ActiveRecord objects:
257
+
258
+ * [Jeremy Weiskotten's PaperTrail fork](http://github.com/jeremyw/paper_trail/blob/master/lib/paper_trail/has_paper_trail.rb#L151-156): uses ActiveSupport's diff to return an array of hashes of the changes.
259
+ * [activerecord-diff](http://github.com/tim/activerecord-diff): rather like ActiveRecord::Dirty but also allows you to specify which columns to compare.
260
+
261
+
223
262
  ## Turning PaperTrail Off/On
224
263
 
225
264
  Sometimes you don't want to store changes. Perhaps you are only interested in changes made by your users and don't need to store changes you make yourself in, say, a migration -- or when testing your application.
@@ -265,6 +304,15 @@ And then use it in your tests like this:
265
304
  end
266
305
 
267
306
 
307
+ ## Deleting Old Versions
308
+
309
+ Over time your `versions` table will grow to an unwieldy size. Because each version is self-contained (see the Diffing section above for more) you can simply delete any records you don't want any more. For example:
310
+
311
+ sql> delete from versions where created_at < 2010-06-01;
312
+
313
+ >> Version.delete_all ["created_at < ?", 1.week.ago]
314
+
315
+
268
316
  ## Installation
269
317
 
270
318
  1. Install PaperTrail as a gem via your `config/environment.rb`:
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.5.1
1
+ 1.5.2
@@ -78,6 +78,11 @@ module PaperTrail
78
78
  end
79
79
  end
80
80
 
81
+ # Returns who put the object into its current state.
82
+ def originator
83
+ versions.last.try :whodunnit
84
+ end
85
+
81
86
  # Returns the object (not a Version) as it was at the given timestamp.
82
87
  def version_at(timestamp)
83
88
  # Short-circuit if the current state is applicable.
@@ -87,13 +92,13 @@ module PaperTrail
87
92
  # change.
88
93
  version = versions.first :conditions => ['created_at > ?', timestamp],
89
94
  :order => 'created_at ASC'
90
- version.reify if version
95
+ version.try :reify
91
96
  end
92
97
 
93
98
  # Returns the object (not a Version) as it was most recently.
94
99
  def previous_version
95
100
  last_version = version ? version.previous : versions.last
96
- last_version.reify if last_version
101
+ last_version.try :reify
97
102
  end
98
103
 
99
104
  # Returns the object (not a Version) as it became next.
@@ -40,6 +40,17 @@ class Version < ActiveRecord::Base
40
40
  end
41
41
  end
42
42
 
43
+ # Returns who put the item into the state stored in this version.
44
+ def originator
45
+ previous.try :whodunnit
46
+ end
47
+
48
+ # Returns who changed the item from the state it had in this version.
49
+ # This is an alias for `whodunnit`.
50
+ def terminator
51
+ whodunnit
52
+ end
53
+
43
54
  def next
44
55
  Version.first :conditions => ["id > ? AND item_type = ? AND item_id = ?", id, item_type, item_id],
45
56
  :order => 'id ASC'
@@ -54,5 +65,5 @@ class Version < ActiveRecord::Base
54
65
  Version.all(:conditions => ["item_type = ? AND item_id = ?", item_type, item_id],
55
66
  :order => 'id ASC').index(self)
56
67
  end
57
-
68
+
58
69
  end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{paper_trail}
8
- s.version = "1.5.1"
8
+ s.version = "1.5.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Andy Stewart"]
12
- s.date = %q{2010-06-22}
12
+ s.date = %q{2010-06-28}
13
13
  s.email = %q{boss@airbladesoftware.com}
14
14
  s.extra_rdoc_files = [
15
15
  "README.md"
@@ -310,29 +310,49 @@ class HasPaperTrailModelTest < Test::Unit::TestCase
310
310
 
311
311
  context 'A papertrail with somebody making changes' do
312
312
  setup do
313
- PaperTrail.whodunnit = 'Colonel Mustard'
314
313
  @widget = Widget.new :name => 'Fidget'
315
314
  end
316
315
 
317
316
  context 'when a record is created' do
318
- setup { @widget.save }
317
+ setup do
318
+ PaperTrail.whodunnit = 'Alice'
319
+ @widget.save
320
+ @version = @widget.versions.last # only 1 version
321
+ end
319
322
 
320
323
  should 'track who made the change' do
321
- assert_equal 'Colonel Mustard', @widget.versions.last.whodunnit
324
+ assert_equal 'Alice', @version.whodunnit
325
+ assert_nil @version.originator
326
+ assert_equal 'Alice', @version.terminator
327
+ assert_equal 'Alice', @widget.originator
322
328
  end
323
329
 
324
330
  context 'when a record is updated' do
325
- setup { @widget.update_attributes :name => 'Rivet' }
331
+ setup do
332
+ PaperTrail.whodunnit = 'Bob'
333
+ @widget.update_attributes :name => 'Rivet'
334
+ @version = @widget.versions.last
335
+ end
326
336
 
327
337
  should 'track who made the change' do
328
- assert_equal 'Colonel Mustard', @widget.versions.last.whodunnit
338
+ assert_equal 'Bob', @version.whodunnit
339
+ assert_equal 'Alice', @version.originator
340
+ assert_equal 'Bob', @version.terminator
341
+ assert_equal 'Bob', @widget.originator
329
342
  end
330
343
 
331
344
  context 'when a record is destroyed' do
332
- setup { @widget.destroy }
345
+ setup do
346
+ PaperTrail.whodunnit = 'Charlie'
347
+ @widget.destroy
348
+ @version = @widget.versions.last
349
+ end
333
350
 
334
351
  should 'track who made the change' do
335
- assert_equal 'Colonel Mustard', @widget.versions.last.whodunnit
352
+ assert_equal 'Charlie', @version.whodunnit
353
+ assert_equal 'Bob', @version.originator
354
+ assert_equal 'Charlie', @version.terminator
355
+ assert_equal 'Charlie', @widget.originator
336
356
  end
337
357
  end
338
358
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: paper_trail
3
3
  version: !ruby/object:Gem::Version
4
- hash: 1
4
+ hash: 7
5
5
  prerelease: false
6
6
  segments:
7
7
  - 1
8
8
  - 5
9
- - 1
10
- version: 1.5.1
9
+ - 2
10
+ version: 1.5.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Andy Stewart
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-06-22 00:00:00 +01:00
18
+ date: 2010-06-28 00:00:00 +01:00
19
19
  default_executable:
20
20
  dependencies: []
21
21