paper_trail 1.6.4 → 1.6.5
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 +1 -0
- data/lib/paper_trail/has_paper_trail.rb +24 -15
- data/lib/paper_trail/version.rb +27 -6
- data/lib/paper_trail/version_number.rb +1 -1
- data/paper_trail.gemspec +5 -2
- data/test/paper_trail_model_test.rb +9 -0
- data/test/schema.rb +1 -0
- metadata +56 -26
data/README.md
CHANGED
@@ -3,9 +3,6 @@ module PaperTrail
|
|
3
3
|
|
4
4
|
def self.included(base)
|
5
5
|
base.send :extend, ClassMethods
|
6
|
-
|
7
|
-
# The version this instance was reified from.
|
8
|
-
attr_accessor :version
|
9
6
|
end
|
10
7
|
|
11
8
|
|
@@ -24,6 +21,9 @@ module PaperTrail
|
|
24
21
|
# any more ActiveRecord models than we have to.
|
25
22
|
send :include, InstanceMethods
|
26
23
|
|
24
|
+
# The version this instance was reified from.
|
25
|
+
attr_accessor :version
|
26
|
+
|
27
27
|
cattr_accessor :ignore
|
28
28
|
self.ignore = (options[:ignore] || []).map &:to_s
|
29
29
|
|
@@ -71,14 +71,14 @@ module PaperTrail
|
|
71
71
|
def version_at(timestamp)
|
72
72
|
# Because a version stores how its object looked *before* the change,
|
73
73
|
# we need to look for the first version created *after* the timestamp.
|
74
|
-
version = versions.first
|
74
|
+
version = versions.after(timestamp).first
|
75
75
|
version ? version.reify : self
|
76
76
|
end
|
77
77
|
|
78
78
|
# Returns the object (not a Version) as it was most recently.
|
79
79
|
def previous_version
|
80
|
-
|
81
|
-
|
80
|
+
preceding_version = version ? version.previous : versions.last
|
81
|
+
preceding_version.try :reify
|
82
82
|
end
|
83
83
|
|
84
84
|
# Returns the object (not a Version) as it became next.
|
@@ -98,7 +98,7 @@ module PaperTrail
|
|
98
98
|
end
|
99
99
|
|
100
100
|
def record_update
|
101
|
-
if switched_on? &&
|
101
|
+
if switched_on? && changed_notably?
|
102
102
|
versions.build merge_metadata(:event => 'update',
|
103
103
|
:object => object_to_string(item_before_change),
|
104
104
|
:whodunnit => PaperTrail.whodunnit)
|
@@ -117,27 +117,36 @@ module PaperTrail
|
|
117
117
|
def merge_metadata(data)
|
118
118
|
# First we merge the model-level metadata in `meta`.
|
119
119
|
meta.each do |k,v|
|
120
|
-
data[k] =
|
120
|
+
data[k] =
|
121
|
+
if v.respond_to?(:call)
|
122
|
+
v.call(self)
|
123
|
+
elsif v.is_a?(Symbol) && respond_to?(v)
|
124
|
+
send(v)
|
125
|
+
else
|
126
|
+
v
|
127
|
+
end
|
121
128
|
end
|
122
129
|
# Second we merge any extra data from the controller (if available).
|
123
130
|
data.merge(PaperTrail.controller_info || {})
|
124
131
|
end
|
125
132
|
|
126
133
|
def item_before_change
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
previous.send :write_attribute, attr.to_sym, ary.first
|
134
|
+
self.clone.tap do |previous|
|
135
|
+
previous.id = id
|
136
|
+
changed_attributes.each { |attr, before| previous[attr] = before }
|
131
137
|
end
|
132
|
-
previous
|
133
138
|
end
|
134
139
|
|
135
140
|
def object_to_string(object)
|
136
141
|
object.attributes.to_yaml
|
137
142
|
end
|
138
143
|
|
139
|
-
def
|
140
|
-
|
144
|
+
def changed_notably?
|
145
|
+
notably_changed.any?
|
146
|
+
end
|
147
|
+
|
148
|
+
def notably_changed
|
149
|
+
changed - self.class.ignore
|
141
150
|
end
|
142
151
|
|
143
152
|
# Returns `true` if PaperTrail is globally enabled and active for this class,
|
data/lib/paper_trail/version.rb
CHANGED
@@ -2,6 +2,26 @@ class Version < ActiveRecord::Base
|
|
2
2
|
belongs_to :item, :polymorphic => true
|
3
3
|
validates_presence_of :event
|
4
4
|
|
5
|
+
named_scope :with_item_keys, lambda { |item_type, item_id| {
|
6
|
+
:conditions => { :item_type => item_type, :item_id => item_id }
|
7
|
+
} }
|
8
|
+
|
9
|
+
named_scope :subsequent, lambda { |version| {
|
10
|
+
:conditions => ["id > ?", version.is_a?(ActiveRecord::Base) ? version.id : version],
|
11
|
+
:order => "id ASC",
|
12
|
+
} }
|
13
|
+
|
14
|
+
named_scope :preceding, lambda { |version| {
|
15
|
+
:conditions => ["id < ?", version.is_a?(ActiveRecord::Base) ? version.id : version],
|
16
|
+
:order => "id DESC",
|
17
|
+
} }
|
18
|
+
|
19
|
+
named_scope :after, lambda { |timestamp| {
|
20
|
+
:conditions => ['created_at > ?', timestamp],
|
21
|
+
# TODO: is this :order necessary, considering its presence on the has_many :versions association?
|
22
|
+
:order => 'created_at ASC, id ASC'
|
23
|
+
} }
|
24
|
+
|
5
25
|
# Restore the item from this version.
|
6
26
|
#
|
7
27
|
# This will automatically restore all :has_one associations as they were "at the time",
|
@@ -69,19 +89,20 @@ class Version < ActiveRecord::Base
|
|
69
89
|
whodunnit
|
70
90
|
end
|
71
91
|
|
92
|
+
def sibling_versions
|
93
|
+
Version.with_item_keys(item_type, item_id)
|
94
|
+
end
|
95
|
+
|
72
96
|
def next
|
73
|
-
|
74
|
-
:order => 'id ASC'
|
97
|
+
sibling_versions.subsequent(self).first
|
75
98
|
end
|
76
99
|
|
77
100
|
def previous
|
78
|
-
|
79
|
-
:order => 'id DESC'
|
101
|
+
sibling_versions.preceding(self).first
|
80
102
|
end
|
81
103
|
|
82
104
|
def index
|
83
|
-
|
84
|
-
:order => 'id ASC').index(self)
|
105
|
+
sibling_versions.all(:select => :id, :order => "id ASC").map(&:id).index(self.id)
|
85
106
|
end
|
86
107
|
|
87
108
|
private
|
data/paper_trail.gemspec
CHANGED
@@ -21,7 +21,10 @@ Gem::Specification.new do |s|
|
|
21
21
|
s.add_development_dependency 'shoulda', '2.10.3'
|
22
22
|
s.add_development_dependency 'activesupport', '~> 2.3'
|
23
23
|
s.add_development_dependency 'sqlite3-ruby', '~> 1.2'
|
24
|
+
# Repeated here to make bundler happy
|
25
|
+
s.add_development_dependency 'activerecord', '~> 2.3'
|
26
|
+
s.add_development_dependency 'actionpack', '~> 2.3'
|
24
27
|
|
25
|
-
s.add_dependency 'activerecord', '
|
26
|
-
s.add_dependency 'actionpack', '
|
28
|
+
s.add_dependency 'activerecord', '~> 2.3'
|
29
|
+
s.add_dependency 'actionpack', '~> 2.3'
|
27
30
|
end
|
@@ -21,8 +21,13 @@ end
|
|
21
21
|
class Article < ActiveRecord::Base
|
22
22
|
has_paper_trail :ignore => [:title],
|
23
23
|
:meta => {:answer => 42,
|
24
|
+
:action => :action_data_provider_method,
|
24
25
|
:question => Proc.new { "31 + 11 = #{31 + 11}" },
|
25
26
|
:article_id => Proc.new { |article| article.id } }
|
27
|
+
|
28
|
+
def action_data_provider_method
|
29
|
+
self.object_id.to_s
|
30
|
+
end
|
26
31
|
end
|
27
32
|
|
28
33
|
class Book < ActiveRecord::Base
|
@@ -528,6 +533,10 @@ class HasPaperTrailModelTest < Test::Unit::TestCase
|
|
528
533
|
assert_equal @article.id, @article.versions.last.article_id
|
529
534
|
end
|
530
535
|
|
536
|
+
should 'store dynamic meta data based on a method of the item' do
|
537
|
+
assert_equal @article.action_data_provider_method, @article.versions.last.action
|
538
|
+
end
|
539
|
+
|
531
540
|
|
532
541
|
context 'and updated' do
|
533
542
|
setup { @article.update_attributes! :content => 'Better text.' }
|
data/test/schema.rb
CHANGED
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: 5
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 6
|
9
|
-
-
|
10
|
-
version: 1.6.
|
9
|
+
- 5
|
10
|
+
version: 1.6.5
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Andy Stewart
|
@@ -15,14 +15,13 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date:
|
18
|
+
date: 2011-02-08 00:00:00 +00:00
|
19
19
|
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,37 +93,68 @@ 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
|
+
- - ~>
|
106
105
|
- !ruby/object:Gem::Version
|
107
106
|
hash: 5
|
108
107
|
segments:
|
109
108
|
- 2
|
110
109
|
- 3
|
111
110
|
version: "2.3"
|
112
|
-
|
111
|
+
type: :development
|
112
|
+
version_requirements: *id006
|
113
113
|
- !ruby/object:Gem::Dependency
|
114
114
|
name: actionpack
|
115
|
+
prerelease: false
|
116
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
117
|
+
none: false
|
118
|
+
requirements:
|
119
|
+
- - ~>
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
hash: 5
|
122
|
+
segments:
|
123
|
+
- 2
|
124
|
+
- 3
|
125
|
+
version: "2.3"
|
126
|
+
type: :development
|
127
|
+
version_requirements: *id007
|
128
|
+
- !ruby/object:Gem::Dependency
|
129
|
+
name: activerecord
|
130
|
+
prerelease: false
|
131
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
132
|
+
none: false
|
133
|
+
requirements:
|
134
|
+
- - ~>
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
hash: 5
|
137
|
+
segments:
|
138
|
+
- 2
|
139
|
+
- 3
|
140
|
+
version: "2.3"
|
115
141
|
type: :runtime
|
142
|
+
version_requirements: *id008
|
143
|
+
- !ruby/object:Gem::Dependency
|
144
|
+
name: actionpack
|
116
145
|
prerelease: false
|
117
|
-
|
146
|
+
requirement: &id009 !ruby/object:Gem::Requirement
|
118
147
|
none: false
|
119
148
|
requirements:
|
120
|
-
- -
|
149
|
+
- - ~>
|
121
150
|
- !ruby/object:Gem::Version
|
122
151
|
hash: 5
|
123
152
|
segments:
|
124
153
|
- 2
|
125
154
|
- 3
|
126
155
|
version: "2.3"
|
127
|
-
|
156
|
+
type: :runtime
|
157
|
+
version_requirements: *id009
|
128
158
|
description: Track changes to your models' data. Good for auditing or versioning.
|
129
159
|
email: boss@airbladesoftware.com
|
130
160
|
executables: []
|