paper_trail 1.6.2 → 1.6.3
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.md +86 -1
- data/lib/paper_trail/has_paper_trail.rb +22 -22
- data/lib/paper_trail/version_number.rb +1 -1
- data/test/paper_trail_model_test.rb +11 -0
- metadata +24 -24
data/README.md
CHANGED
@@ -29,6 +29,76 @@ PaperTrail lets you track changes to your models' data. It's good for auditing
|
|
29
29
|
Works on Rails 3 and Rails 2.3. Probably works on Rails 2.2 and 2.1.
|
30
30
|
|
31
31
|
|
32
|
+
## API Summary
|
33
|
+
|
34
|
+
When you declare `has_paper_trail` in your model, you get these methods:
|
35
|
+
|
36
|
+
class Widget < ActiveRecord::Base
|
37
|
+
has_paper_trail # you can pass various options here
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns this widget's versions.
|
41
|
+
widget.versions
|
42
|
+
|
43
|
+
# Return the version this widget was reified from, or nil if it is live.
|
44
|
+
widget.version
|
45
|
+
|
46
|
+
# Returns true if this widget is the current, live one; or false if it is from a previous version.
|
47
|
+
widget.live?
|
48
|
+
|
49
|
+
# Returns who put the widget into its current state.
|
50
|
+
widget.originator
|
51
|
+
|
52
|
+
# Returns the widget (not a version) as it looked at the given timestamp.
|
53
|
+
widget.version_at(timestamp)
|
54
|
+
|
55
|
+
# Returns the widget (not a version) as it was most recently.
|
56
|
+
widget.previous_version
|
57
|
+
|
58
|
+
# Returns the widget (not a version) as it became next.
|
59
|
+
widget.next_version
|
60
|
+
|
61
|
+
# Turn PaperTrail off for all widgets.
|
62
|
+
Widget.paper_trail_off
|
63
|
+
|
64
|
+
# Turn PaperTrail on for all widgets.
|
65
|
+
Widget.paper_trail_on
|
66
|
+
|
67
|
+
And a `Version` instance has these methods:
|
68
|
+
|
69
|
+
# Returns the item restored from this version.
|
70
|
+
version.reify(options = {})
|
71
|
+
|
72
|
+
# Returns who put the item into the state stored in this version.
|
73
|
+
version.originator
|
74
|
+
|
75
|
+
# Returns who changed the item from the state it had in this version.
|
76
|
+
version.terminator
|
77
|
+
version.whodunnit
|
78
|
+
|
79
|
+
# Returns the next version.
|
80
|
+
version.next
|
81
|
+
|
82
|
+
# Returns the previous version.
|
83
|
+
version.previous
|
84
|
+
|
85
|
+
# Returns the index of this version in all the versions.
|
86
|
+
version.index
|
87
|
+
|
88
|
+
# Returns the event that caused this version (create|update|destroy).
|
89
|
+
version.event
|
90
|
+
|
91
|
+
In your controllers you can override these methods:
|
92
|
+
|
93
|
+
# Returns the user who is responsible for any changes that occur.
|
94
|
+
# Defaults to current_user.
|
95
|
+
user_for_paper_trail
|
96
|
+
|
97
|
+
# Returns any information about the controller or request that you want
|
98
|
+
# PaperTrail to store alongside any changes that occur.
|
99
|
+
info_for_paper_trail
|
100
|
+
|
101
|
+
|
32
102
|
## Basic Usage
|
33
103
|
|
34
104
|
PaperTrail is simple to use. Just add 15 characters to a model to get a paper trail of every `create`, `update`, and `destroy`.
|
@@ -289,7 +359,20 @@ But none of these will:
|
|
289
359
|
>> @book.author_ids = [@solzhenistyn.id, @dostoyevsky.id]
|
290
360
|
>> @book.authors = []
|
291
361
|
|
292
|
-
Having said that, you can
|
362
|
+
Having said that, you can apparently get all these working (I haven't tested it myself) with this [monkey patch](http://stackoverflow.com/questions/2381033/how-to-create-a-full-audit-log-in-rails-for-every-table/2381411#2381411):
|
363
|
+
|
364
|
+
# In config/initializers/core_extensions.rb or lib/core_extensions.rb
|
365
|
+
ActiveRecord::Associations::HasManyThroughAssociation.class_eval do
|
366
|
+
def delete_records(records)
|
367
|
+
klass = @reflection.through_reflection.klass
|
368
|
+
records.each do |associate|
|
369
|
+
klass.destroy_all(construct_join_attributes(associate))
|
370
|
+
end
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
374
|
+
The difference is the call to `destroy_all` instead of `delete_all` in [the original](http://github.com/rails/rails/blob/master/activerecord/lib/active_record/associations/has_many_through_association.rb#L76-81).
|
375
|
+
|
293
376
|
|
294
377
|
There may be a way to store authorship versions, probably using association callbacks, no matter how the collection is manipulated but I haven't found it yet. Let me know if you do.
|
295
378
|
|
@@ -454,6 +537,8 @@ Many thanks to:
|
|
454
537
|
* [Phan Le](http://github.com/revo)
|
455
538
|
* [jdrucza](http://github.com/jdrucza)
|
456
539
|
* [conickal](http://github.com/conickal)
|
540
|
+
* [Thibaud Guillaume-Gentil](http://github.com/thibaudgg)
|
541
|
+
* Danny Trelogan
|
457
542
|
|
458
543
|
|
459
544
|
## Inspirations
|
@@ -56,28 +56,6 @@ module PaperTrail
|
|
56
56
|
# Wrap the following methods in a module so we can include them only in the
|
57
57
|
# ActiveRecord models that declare `has_paper_trail`.
|
58
58
|
module InstanceMethods
|
59
|
-
def record_create
|
60
|
-
if switched_on?
|
61
|
-
versions.create merge_metadata(:event => 'create', :whodunnit => PaperTrail.whodunnit)
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
def record_update
|
66
|
-
if switched_on? && changed_and_we_care?
|
67
|
-
versions.build merge_metadata(:event => 'update',
|
68
|
-
:object => object_to_string(item_before_change),
|
69
|
-
:whodunnit => PaperTrail.whodunnit)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
def record_destroy
|
74
|
-
if switched_on?
|
75
|
-
versions.create merge_metadata(:event => 'destroy',
|
76
|
-
:object => object_to_string(item_before_change),
|
77
|
-
:whodunnit => PaperTrail.whodunnit)
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
59
|
# Returns true if this instance is the current, live one;
|
82
60
|
# returns false if this instance came from a previous version.
|
83
61
|
def live?
|
@@ -113,6 +91,28 @@ module PaperTrail
|
|
113
91
|
|
114
92
|
private
|
115
93
|
|
94
|
+
def record_create
|
95
|
+
if switched_on?
|
96
|
+
versions.create merge_metadata(:event => 'create', :whodunnit => PaperTrail.whodunnit)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def record_update
|
101
|
+
if switched_on? && changed_and_we_care?
|
102
|
+
versions.build merge_metadata(:event => 'update',
|
103
|
+
:object => object_to_string(item_before_change),
|
104
|
+
:whodunnit => PaperTrail.whodunnit)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def record_destroy
|
109
|
+
if switched_on? and not new_record?
|
110
|
+
versions.create merge_metadata(:event => 'destroy',
|
111
|
+
:object => object_to_string(item_before_change),
|
112
|
+
:whodunnit => PaperTrail.whodunnit)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
116
|
def merge_metadata(data)
|
117
117
|
# First we merge the model-level metadata in `meta`.
|
118
118
|
meta.each do |k,v|
|
@@ -769,6 +769,17 @@ class HasPaperTrailModelTest < Test::Unit::TestCase
|
|
769
769
|
end
|
770
770
|
|
771
771
|
|
772
|
+
context 'An unsaved record' do
|
773
|
+
setup do
|
774
|
+
@widget = Widget.new
|
775
|
+
@widget.destroy
|
776
|
+
end
|
777
|
+
should 'not have a version created on destroy' do
|
778
|
+
assert @widget.versions.empty?
|
779
|
+
end
|
780
|
+
end
|
781
|
+
|
782
|
+
|
772
783
|
private
|
773
784
|
|
774
785
|
# Updates `model`'s last version so it looks like the version was
|
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:
|
4
|
+
hash: 9
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 6
|
9
|
-
-
|
10
|
-
version: 1.6.
|
9
|
+
- 3
|
10
|
+
version: 1.6.3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Andy Stewart
|
@@ -20,9 +20,8 @@ default_executable:
|
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
22
|
name: bundler
|
23
|
-
type: :development
|
24
23
|
prerelease: false
|
25
|
-
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
26
25
|
none: false
|
27
26
|
requirements:
|
28
27
|
- - ~>
|
@@ -32,12 +31,12 @@ dependencies:
|
|
32
31
|
- 1
|
33
32
|
- 0
|
34
33
|
version: "1.0"
|
35
|
-
|
34
|
+
type: :development
|
35
|
+
version_requirements: *id001
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: rake
|
38
|
-
type: :development
|
39
38
|
prerelease: false
|
40
|
-
|
39
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
40
|
none: false
|
42
41
|
requirements:
|
43
42
|
- - "="
|
@@ -48,12 +47,12 @@ dependencies:
|
|
48
47
|
- 8
|
49
48
|
- 7
|
50
49
|
version: 0.8.7
|
51
|
-
|
50
|
+
type: :development
|
51
|
+
version_requirements: *id002
|
52
52
|
- !ruby/object:Gem::Dependency
|
53
53
|
name: shoulda
|
54
|
-
type: :development
|
55
54
|
prerelease: false
|
56
|
-
|
55
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
57
56
|
none: false
|
58
57
|
requirements:
|
59
58
|
- - "="
|
@@ -64,12 +63,12 @@ dependencies:
|
|
64
63
|
- 10
|
65
64
|
- 3
|
66
65
|
version: 2.10.3
|
67
|
-
|
66
|
+
type: :development
|
67
|
+
version_requirements: *id003
|
68
68
|
- !ruby/object:Gem::Dependency
|
69
69
|
name: activesupport
|
70
|
-
type: :development
|
71
70
|
prerelease: false
|
72
|
-
|
71
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
73
72
|
none: false
|
74
73
|
requirements:
|
75
74
|
- - ~>
|
@@ -79,12 +78,12 @@ dependencies:
|
|
79
78
|
- 2
|
80
79
|
- 3
|
81
80
|
version: "2.3"
|
82
|
-
|
81
|
+
type: :development
|
82
|
+
version_requirements: *id004
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: sqlite3-ruby
|
85
|
-
type: :development
|
86
85
|
prerelease: false
|
87
|
-
|
86
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
88
87
|
none: false
|
89
88
|
requirements:
|
90
89
|
- - ~>
|
@@ -94,12 +93,12 @@ dependencies:
|
|
94
93
|
- 1
|
95
94
|
- 2
|
96
95
|
version: "1.2"
|
97
|
-
|
96
|
+
type: :development
|
97
|
+
version_requirements: *id005
|
98
98
|
- !ruby/object:Gem::Dependency
|
99
99
|
name: activerecord
|
100
|
-
type: :runtime
|
101
100
|
prerelease: false
|
102
|
-
|
101
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
103
102
|
none: false
|
104
103
|
requirements:
|
105
104
|
- - ">="
|
@@ -109,12 +108,12 @@ dependencies:
|
|
109
108
|
- 2
|
110
109
|
- 3
|
111
110
|
version: "2.3"
|
112
|
-
|
111
|
+
type: :runtime
|
112
|
+
version_requirements: *id006
|
113
113
|
- !ruby/object:Gem::Dependency
|
114
114
|
name: actionpack
|
115
|
-
type: :runtime
|
116
115
|
prerelease: false
|
117
|
-
|
116
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
118
117
|
none: false
|
119
118
|
requirements:
|
120
119
|
- - ">="
|
@@ -124,7 +123,8 @@ dependencies:
|
|
124
123
|
- 2
|
125
124
|
- 3
|
126
125
|
version: "2.3"
|
127
|
-
|
126
|
+
type: :runtime
|
127
|
+
version_requirements: *id007
|
128
128
|
description: Track changes to your models' data. Good for auditing or versioning.
|
129
129
|
email: boss@airbladesoftware.com
|
130
130
|
executables: []
|