paper_trail 1.2.14 → 1.3.1
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/.gitignore +1 -0
- data/README.md +28 -2
- data/Rakefile +2 -1
- data/VERSION +1 -1
- data/generators/paper_trail/templates/create_versions.rb +0 -2
- data/lib/paper_trail.rb +0 -14
- data/lib/paper_trail/has_paper_trail.rb +11 -78
- data/lib/paper_trail/version.rb +1 -19
- data/paper_trail.gemspec +18 -16
- data/test/database.yml +13 -17
- data/test/paper_trail_controller_test.rb +1 -3
- data/test/paper_trail_model_test.rb +28 -9
- data/test/paper_trail_schema_test.rb +1 -0
- data/test/schema.rb +5 -0
- data/test/test_helper.rb +20 -24
- metadata +4 -7
- data/lib/paper_trail/config.rb +0 -10
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -6,7 +6,7 @@ PaperTrail lets you track changes to your models' data. It's good for auditing
|
|
6
6
|
## Features
|
7
7
|
|
8
8
|
* Stores every create, update and destroy.
|
9
|
-
* Does not store updates which don't change anything.
|
9
|
+
* Does not store updates which don't change anything (or which only change attributes you are ignoring).
|
10
10
|
* Allows you to get at every version, including the original, even once destroyed.
|
11
11
|
* Allows you to get at every version even if the schema has since changed.
|
12
12
|
* Automatically records who was responsible if your controller has a `current_user` method.
|
@@ -87,6 +87,25 @@ Here's a helpful table showing what PaperTrail stores:
|
|
87
87
|
PaperTrail stores the values in the Model Before column. Most other auditing/versioning plugins store the After column.
|
88
88
|
|
89
89
|
|
90
|
+
## Ignoring changes to certain attributes
|
91
|
+
|
92
|
+
You can ignore changes to certain attributes like this:
|
93
|
+
|
94
|
+
class Article < ActiveRecord::Base
|
95
|
+
has_paper_trail :ignore => [:title, :rating]
|
96
|
+
end
|
97
|
+
|
98
|
+
This means that changes to just the `title` or `rating` will not store another version of the article. It does not mean that the `title` and `rating` attributes will be ignored if some other change causes a new `Version` to be crated. For example:
|
99
|
+
|
100
|
+
>> a = Article.create
|
101
|
+
>> a.versions.length # 1
|
102
|
+
>> a.update_attributes :title => 'My Title', :rating => 3
|
103
|
+
>> a.versions.length # 1
|
104
|
+
>> a.update_attributes :content => 'Hello'
|
105
|
+
>> a.versions.length # 2
|
106
|
+
>> a.versions.last.reify.title # 'My Title'
|
107
|
+
|
108
|
+
|
90
109
|
## Reverting And Undeleting A Model
|
91
110
|
|
92
111
|
PaperTrail makes reverting to a previous version easy:
|
@@ -160,7 +179,7 @@ And on again like this:
|
|
160
179
|
|
161
180
|
## Testing
|
162
181
|
|
163
|
-
PaperTrail has a thorough suite of tests.
|
182
|
+
PaperTrail has a thorough suite of tests. Thanks to [Zachery Hostens](http://github.com/zacheryph) for making them able to run standalone, i.e. without needing PaperTrail to be sitting in a Rails app.
|
164
183
|
|
165
184
|
|
166
185
|
## Problems
|
@@ -168,6 +187,13 @@ PaperTrail has a thorough suite of tests. However they only run when PaperTrail
|
|
168
187
|
Please use GitHub's [issue tracker](http://github.com/airblade/paper_trail/issues).
|
169
188
|
|
170
189
|
|
190
|
+
## Contributors
|
191
|
+
|
192
|
+
Many thanks to:
|
193
|
+
|
194
|
+
* [Zachery Hostens](http://github.com/zacheryph)
|
195
|
+
|
196
|
+
|
171
197
|
## Inspirations
|
172
198
|
|
173
199
|
* [Simply Versioned](http://github.com/github/simply_versioned)
|
data/Rakefile
CHANGED
@@ -11,8 +11,9 @@ begin
|
|
11
11
|
gemspec.homepage = 'http://github.com/airblade/paper_trail'
|
12
12
|
gemspec.authors = ['Andy Stewart']
|
13
13
|
end
|
14
|
+
Jeweler::GemcutterTasks.new
|
14
15
|
rescue LoadError
|
15
|
-
puts "Jeweler not available. Install it with: sudo gem install
|
16
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
16
17
|
end
|
17
18
|
|
18
19
|
desc 'Test the paper_trail plugin.'
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.3.1
|
@@ -7,10 +7,8 @@ class CreateVersions < ActiveRecord::Migration
|
|
7
7
|
t.string :whodunnit
|
8
8
|
t.text :object
|
9
9
|
t.datetime :created_at
|
10
|
-
t.integer :user_id, :null => true
|
11
10
|
end
|
12
11
|
add_index :versions, [:item_type, :item_id]
|
13
|
-
add_index :versions, :user_id
|
14
12
|
end
|
15
13
|
|
16
14
|
def self.down
|
data/lib/paper_trail.rb
CHANGED
@@ -1,27 +1,14 @@
|
|
1
1
|
require 'yaml'
|
2
|
-
require 'paper_trail/config'
|
3
2
|
require 'paper_trail/has_paper_trail'
|
4
3
|
require 'paper_trail/version'
|
5
4
|
|
6
5
|
module PaperTrail
|
7
6
|
@@whodunnit = nil
|
8
7
|
|
9
|
-
def self.config
|
10
|
-
@@config ||= PaperTrail::Config.instance
|
11
|
-
end
|
12
|
-
|
13
8
|
def self.included(base)
|
14
9
|
base.before_filter :set_whodunnit
|
15
10
|
end
|
16
11
|
|
17
|
-
def self.enabled=(value)
|
18
|
-
PaperTrail.config.enabled = value
|
19
|
-
end
|
20
|
-
|
21
|
-
def self.enabled?
|
22
|
-
!!PaperTrail.config.enabled
|
23
|
-
end
|
24
|
-
|
25
12
|
def self.whodunnit
|
26
13
|
@@whodunnit.respond_to?(:call) ? @@whodunnit.call : @@whodunnit
|
27
14
|
end
|
@@ -37,7 +24,6 @@ module PaperTrail
|
|
37
24
|
self.send :current_user rescue nil
|
38
25
|
}
|
39
26
|
end
|
40
|
-
|
41
27
|
end
|
42
28
|
|
43
29
|
ActionController::Base.send :include, PaperTrail
|
@@ -6,9 +6,14 @@ module PaperTrail
|
|
6
6
|
|
7
7
|
|
8
8
|
module ClassMethods
|
9
|
-
|
9
|
+
# Options:
|
10
|
+
# :ignore an array of attributes for which a new +Version+ will not be created if only they change.
|
11
|
+
def has_paper_trail(options = {})
|
10
12
|
send :include, InstanceMethods
|
11
13
|
|
14
|
+
cattr_accessor :ignore
|
15
|
+
self.ignore = (options[:ignore] || []).map &:to_s
|
16
|
+
|
12
17
|
cattr_accessor :paper_trail_active
|
13
18
|
self.paper_trail_active = true
|
14
19
|
|
@@ -32,11 +37,11 @@ module PaperTrail
|
|
32
37
|
module InstanceMethods
|
33
38
|
def record_create
|
34
39
|
versions.create(:event => 'create',
|
35
|
-
:whodunnit => PaperTrail.whodunnit) if self.class.paper_trail_active
|
40
|
+
:whodunnit => PaperTrail.whodunnit) if self.class.paper_trail_active
|
36
41
|
end
|
37
42
|
|
38
43
|
def record_update
|
39
|
-
if
|
44
|
+
if changed_and_we_care? and self.class.paper_trail_active
|
40
45
|
versions.build :event => 'update',
|
41
46
|
:object => object_to_string(previous_version),
|
42
47
|
:whodunnit => PaperTrail.whodunnit
|
@@ -46,59 +51,9 @@ module PaperTrail
|
|
46
51
|
def record_destroy
|
47
52
|
versions.create(:event => 'destroy',
|
48
53
|
:object => object_to_string(previous_version),
|
49
|
-
:whodunnit => PaperTrail.whodunnit) if self.class.paper_trail_active
|
54
|
+
:whodunnit => PaperTrail.whodunnit) if self.class.paper_trail_active
|
50
55
|
end
|
51
56
|
|
52
|
-
# Returns the object at the version that was valid at the given timestamp.
|
53
|
-
def version_at timestamp
|
54
|
-
# short-circuit if the current state is valid
|
55
|
-
return self if self.updated_at < timestamp
|
56
|
-
|
57
|
-
version = versions.first(
|
58
|
-
:conditions => ['created_at < ?', timestamp],
|
59
|
-
:order => 'created_at DESC')
|
60
|
-
version.reify if version
|
61
|
-
end
|
62
|
-
|
63
|
-
# Walk the versions to construct an audit trail of the edits made
|
64
|
-
# over time, and by whom.
|
65
|
-
def audit_trail options={}
|
66
|
-
options[:attributes_to_ignore] ||= %w(updated_at)
|
67
|
-
|
68
|
-
audit_trail = []
|
69
|
-
|
70
|
-
versions_desc = versions_including_current_in_descending_order
|
71
|
-
|
72
|
-
versions_desc.each_with_index do |version, index|
|
73
|
-
previous_version = versions_desc[index + 1]
|
74
|
-
break if previous_version.nil?
|
75
|
-
|
76
|
-
attributes_after = yaml_to_hash(version.object)
|
77
|
-
attributes_before = yaml_to_hash(previous_version.object)
|
78
|
-
|
79
|
-
# remove some attributes that we don't need to report
|
80
|
-
[attributes_before, attributes_after].each do |hash|
|
81
|
-
hash.reject! { |k,v| k.in? Array(options[:attributes_to_ignore]) }
|
82
|
-
end
|
83
|
-
|
84
|
-
audit_trail << {
|
85
|
-
:event => previous_version.event,
|
86
|
-
:changed_by => transform_whodunnit(previous_version.whodunnit),
|
87
|
-
:changed_at => previous_version.created_at,
|
88
|
-
:changes => differences(attributes_before, attributes_after)
|
89
|
-
}
|
90
|
-
end
|
91
|
-
|
92
|
-
audit_trail
|
93
|
-
end
|
94
|
-
|
95
|
-
protected
|
96
|
-
|
97
|
-
def transform_whodunnit(whodunnit)
|
98
|
-
whodunnit
|
99
|
-
end
|
100
|
-
|
101
|
-
|
102
57
|
private
|
103
58
|
|
104
59
|
def previous_version
|
@@ -114,30 +69,8 @@ module PaperTrail
|
|
114
69
|
object.attributes.to_yaml
|
115
70
|
end
|
116
71
|
|
117
|
-
def
|
118
|
-
|
119
|
-
YAML::load(yaml).to_hash
|
120
|
-
end
|
121
|
-
|
122
|
-
# Returns an array of hashes, where each hash specifies the +:attribute+,
|
123
|
-
# value +:before+ the change, and value +:after+ the change.
|
124
|
-
def differences(before, after)
|
125
|
-
before.diff(after).keys.sort.inject([]) do |diffs, k|
|
126
|
-
diff = { :attribute => k, :before => before[k], :after => after[k] }
|
127
|
-
diffs << diff; diffs
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
def versions_including_current_in_descending_order
|
132
|
-
if self.new_record?
|
133
|
-
v = Version.all(:order => 'created_at desc', :conditions => {:item_id => id, :item_type => self.class.name})
|
134
|
-
else
|
135
|
-
v = self.versions.dup
|
136
|
-
end
|
137
|
-
v << Version.new(:event => 'update',
|
138
|
-
:object => object_to_string(self),
|
139
|
-
:created_at => self.updated_at)
|
140
|
-
v.reverse # newest first
|
72
|
+
def changed_and_we_care?
|
73
|
+
changed? and !(changed - self.class.ignore).empty?
|
141
74
|
end
|
142
75
|
end
|
143
76
|
|
data/lib/paper_trail/version.rb
CHANGED
@@ -1,19 +1,7 @@
|
|
1
1
|
class Version < ActiveRecord::Base
|
2
2
|
belongs_to :item, :polymorphic => true
|
3
|
-
belongs_to :user
|
4
|
-
before_save :set_user_id
|
5
3
|
validates_presence_of :event
|
6
4
|
|
7
|
-
named_scope :for_item_type, lambda { |item_types|
|
8
|
-
{ :conditions => { :item_type => item_types } }
|
9
|
-
}
|
10
|
-
|
11
|
-
named_scope :created_after, lambda { |time|
|
12
|
-
{ :conditions => ['versions.created_at > ?', time] }
|
13
|
-
}
|
14
|
-
|
15
|
-
named_scope :by_created_at_ascending, :order => 'versions.created_at asc'
|
16
|
-
|
17
5
|
def reify
|
18
6
|
unless object.nil?
|
19
7
|
# Attributes
|
@@ -45,7 +33,7 @@ class Version < ActiveRecord::Base
|
|
45
33
|
begin
|
46
34
|
model.send "#{k}=", v
|
47
35
|
rescue NoMethodError
|
48
|
-
|
36
|
+
logger.warn "Attribute #{k} does not exist on #{item_type} (Version id: #{id})."
|
49
37
|
end
|
50
38
|
end
|
51
39
|
|
@@ -68,10 +56,4 @@ class Version < ActiveRecord::Base
|
|
68
56
|
:order => 'id ASC').index(self)
|
69
57
|
end
|
70
58
|
|
71
|
-
private
|
72
|
-
|
73
|
-
def set_user_id
|
74
|
-
self.user_id = self.whodunnit.id if self.whodunnit.is_a?(ActiveRecord::Base)
|
75
|
-
return true
|
76
|
-
end
|
77
59
|
end
|
data/paper_trail.gemspec
CHANGED
@@ -1,13 +1,16 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in rakefile, and run the gemspec command
|
1
4
|
# -*- encoding: utf-8 -*-
|
2
5
|
|
3
6
|
Gem::Specification.new do |s|
|
4
7
|
s.name = %q{paper_trail}
|
5
|
-
s.version = "1.
|
8
|
+
s.version = "1.3.1"
|
6
9
|
|
7
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
-
s.authors = ["Andy Stewart"
|
9
|
-
s.date = %q{2009-
|
10
|
-
s.email = %q{
|
11
|
+
s.authors = ["Andy Stewart"]
|
12
|
+
s.date = %q{2009-11-24}
|
13
|
+
s.email = %q{boss@airbladesoftware.com}
|
11
14
|
s.extra_rdoc_files = [
|
12
15
|
"README.md"
|
13
16
|
]
|
@@ -23,7 +26,6 @@ Gem::Specification.new do |s|
|
|
23
26
|
"init.rb",
|
24
27
|
"install.rb",
|
25
28
|
"lib/paper_trail.rb",
|
26
|
-
"lib/paper_trail/config.rb",
|
27
29
|
"lib/paper_trail/has_paper_trail.rb",
|
28
30
|
"lib/paper_trail/version.rb",
|
29
31
|
"paper_trail.gemspec",
|
@@ -38,8 +40,7 @@ Gem::Specification.new do |s|
|
|
38
40
|
"test/test_helper.rb",
|
39
41
|
"uninstall.rb"
|
40
42
|
]
|
41
|
-
s.
|
42
|
-
s.homepage = %q{http://github.com/jeremyw/paper_trail}
|
43
|
+
s.homepage = %q{http://github.com/airblade/paper_trail}
|
43
44
|
s.rdoc_options = ["--charset=UTF-8"]
|
44
45
|
s.require_paths = ["lib"]
|
45
46
|
s.rubygems_version = %q{1.3.5}
|
@@ -53,13 +54,14 @@ Gem::Specification.new do |s|
|
|
53
54
|
"test/test_helper.rb"
|
54
55
|
]
|
55
56
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
57
|
+
if s.respond_to? :specification_version then
|
58
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
59
|
+
s.specification_version = 3
|
60
|
+
|
61
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
62
|
+
else
|
63
|
+
end
|
64
|
+
else
|
65
|
+
end
|
65
66
|
end
|
67
|
+
|
data/test/database.yml
CHANGED
@@ -1,22 +1,18 @@
|
|
1
|
-
sqlite:
|
2
|
-
:adapter: sqlite
|
3
|
-
:dbfile: vendor/plugins/paper_trail/test/paper_trail_plugin.sqlite.db
|
4
|
-
|
5
1
|
sqlite3:
|
6
|
-
|
7
|
-
:
|
2
|
+
adapter: sqlite3
|
3
|
+
database: ":memory:"
|
8
4
|
|
9
5
|
postgresql:
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
6
|
+
adapter: postgresql
|
7
|
+
username: postgres
|
8
|
+
password: postgres
|
9
|
+
database: paper_trail_plugin_test
|
10
|
+
min_messages: ERROR
|
15
11
|
|
16
12
|
mysql:
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
13
|
+
adapter: mysql
|
14
|
+
host: localhost
|
15
|
+
username: andy
|
16
|
+
password:
|
17
|
+
database: paper_trail_plugin_test
|
18
|
+
socket: /tmp/mysql.sock
|
@@ -17,10 +17,29 @@ class Fluxor < ActiveRecord::Base
|
|
17
17
|
belongs_to :widget
|
18
18
|
end
|
19
19
|
|
20
|
+
class Article < ActiveRecord::Base
|
21
|
+
has_paper_trail :ignore => [:title]
|
22
|
+
end
|
23
|
+
|
20
24
|
|
21
25
|
class HasPaperTrailModelTest < Test::Unit::TestCase
|
22
26
|
load_schema
|
23
27
|
|
28
|
+
context 'A record' do
|
29
|
+
setup { @article = Article.create }
|
30
|
+
|
31
|
+
context 'which updates an ignored column' do
|
32
|
+
setup { @article.update_attributes :title => 'My first title' }
|
33
|
+
should_not_change('the number of versions') { Version.count }
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'which updates an ignored column and a non-ignored column' do
|
37
|
+
setup { @article.update_attributes :title => 'My first title', :content => 'Some text here.' }
|
38
|
+
should_change('the number of versions', :by => 1) { Version.count }
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
24
43
|
context 'A new record' do
|
25
44
|
setup { @widget = Widget.new }
|
26
45
|
|
@@ -194,7 +213,7 @@ class HasPaperTrailModelTest < Test::Unit::TestCase
|
|
194
213
|
should 'handle datetimes' do
|
195
214
|
# Is there a better way to test equality of two datetimes?
|
196
215
|
format = '%a, %d %b %Y %H:%M:%S %z' # :rfc822
|
197
|
-
assert_equal @date_time.strftime(format), @previous.a_datetime.strftime(format)
|
216
|
+
assert_equal @date_time.utc.strftime(format), @previous.a_datetime.utc.strftime(format)
|
198
217
|
end
|
199
218
|
|
200
219
|
should 'handle times' do
|
@@ -224,14 +243,14 @@ class HasPaperTrailModelTest < Test::Unit::TestCase
|
|
224
243
|
|
225
244
|
should 'restore all forward-compatible attributes' do
|
226
245
|
format = '%a, %d %b %Y %H:%M:%S %z' # :rfc822
|
227
|
-
assert_equal 'Warble',
|
228
|
-
assert_equal 'The quick brown fox',
|
229
|
-
assert_equal 42,
|
230
|
-
assert_in_delta 153.01,
|
231
|
-
assert_in_delta 2.71828,
|
232
|
-
assert_equal @date_time.strftime(format), @last.reify.a_datetime.strftime(format)
|
233
|
-
assert_equal @time,
|
234
|
-
assert_equal @date,
|
246
|
+
assert_equal 'Warble', @last.reify.name
|
247
|
+
assert_equal 'The quick brown fox', @last.reify.a_text
|
248
|
+
assert_equal 42, @last.reify.an_integer
|
249
|
+
assert_in_delta 153.01, @last.reify.a_float, 0.001
|
250
|
+
assert_in_delta 2.71828, @last.reify.a_decimal, 0.00001
|
251
|
+
assert_equal @date_time.utc.strftime(format), @last.reify.a_datetime.utc.strftime(format)
|
252
|
+
assert_equal @time, @last.reify.a_time
|
253
|
+
assert_equal @date, @last.reify.a_date
|
235
254
|
assert @last.reify.a_boolean
|
236
255
|
end
|
237
256
|
end
|
data/test/schema.rb
CHANGED
data/test/test_helper.rb
CHANGED
@@ -1,33 +1,29 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'active_support'
|
3
|
-
require 'active_support/test_case'
|
4
|
-
require 'shoulda'
|
5
|
-
|
6
|
-
ENV['RAILS_ENV'] = 'test'
|
7
|
-
ENV['RAILS_ROOT'] ||= File.dirname(__FILE__) + '/../../../..'
|
8
|
-
|
9
1
|
require 'test/unit'
|
10
|
-
|
2
|
+
RAILS_ROOT = File.join(File.dirname(__FILE__), %w{.. .. .. ..})
|
3
|
+
$:.unshift(File.join(File.dirname(__FILE__), %w{.. lib}))
|
4
|
+
|
5
|
+
unless defined?(ActiveRecord)
|
6
|
+
if File.directory? RAILS_ROOT + 'config'
|
7
|
+
puts 'using config/boot.rb'
|
8
|
+
ENV['RAILS_ENV'] = 'test'
|
9
|
+
require File.join(RAILS_ROOT, 'config', 'boot.rb')
|
10
|
+
else
|
11
|
+
# simply use installed gems if available
|
12
|
+
puts 'using rubygems'
|
13
|
+
require 'rubygems'
|
14
|
+
gem 'actionpack'; gem 'activerecord'; gem 'activesupport'; gem 'rails'
|
15
|
+
end
|
16
|
+
|
17
|
+
%w(action_pack action_controller active_record active_support initializer).each {|f| require f}
|
18
|
+
end
|
19
|
+
require 'shoulda'
|
20
|
+
require 'paper_trail'
|
11
21
|
|
12
22
|
def connect_to_database
|
13
23
|
config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
|
14
24
|
ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log")
|
15
25
|
|
16
|
-
db_adapter = ENV['DB']
|
17
|
-
|
18
|
-
# no db passed, try one of these fine config-free DBs before bombing.
|
19
|
-
db_adapter ||=
|
20
|
-
begin
|
21
|
-
require 'rubygems'
|
22
|
-
require 'sqlite'
|
23
|
-
'sqlite'
|
24
|
-
rescue MissingSourceFile
|
25
|
-
begin
|
26
|
-
require 'sqlite3'
|
27
|
-
'sqlite3'
|
28
|
-
rescue MissingSourceFile
|
29
|
-
end
|
30
|
-
end
|
26
|
+
db_adapter = ENV['DB'] || 'sqlite3'
|
31
27
|
|
32
28
|
if db_adapter.nil?
|
33
29
|
raise "No DB Adapter selected. Pass the DB= option to pick one, or install Sqlite or Sqlite3."
|
metadata
CHANGED
@@ -1,22 +1,20 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: paper_trail
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andy Stewart
|
8
|
-
- Jeremy Weiskotten
|
9
|
-
- Joe Lind
|
10
8
|
autorequire:
|
11
9
|
bindir: bin
|
12
10
|
cert_chain: []
|
13
11
|
|
14
|
-
date: 2009-
|
12
|
+
date: 2009-11-24 00:00:00 +00:00
|
15
13
|
default_executable:
|
16
14
|
dependencies: []
|
17
15
|
|
18
16
|
description:
|
19
|
-
email:
|
17
|
+
email: boss@airbladesoftware.com
|
20
18
|
executables: []
|
21
19
|
|
22
20
|
extensions: []
|
@@ -35,7 +33,6 @@ files:
|
|
35
33
|
- init.rb
|
36
34
|
- install.rb
|
37
35
|
- lib/paper_trail.rb
|
38
|
-
- lib/paper_trail/config.rb
|
39
36
|
- lib/paper_trail/has_paper_trail.rb
|
40
37
|
- lib/paper_trail/version.rb
|
41
38
|
- paper_trail.gemspec
|
@@ -50,7 +47,7 @@ files:
|
|
50
47
|
- test/test_helper.rb
|
51
48
|
- uninstall.rb
|
52
49
|
has_rdoc: true
|
53
|
-
homepage: http://github.com/
|
50
|
+
homepage: http://github.com/airblade/paper_trail
|
54
51
|
licenses: []
|
55
52
|
|
56
53
|
post_install_message:
|