paper_trail 2.1.1 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +32 -7
- data/lib/paper_trail/controller.rb +8 -0
- data/lib/paper_trail/has_paper_trail.rb +5 -9
- data/lib/paper_trail/version_number.rb +1 -1
- data/lib/paper_trail.rb +9 -0
- data/paper_trail.gemspec +1 -0
- data/test/dummy/app/controllers/application_controller.rb +1 -0
- data/test/dummy/app/controllers/widgets_controller.rb +5 -0
- data/test/dummy/app/models/animal.rb +1 -0
- data/test/dummy/app/models/cat.rb +0 -1
- data/test/dummy/app/models/dog.rb +0 -1
- data/test/functional/controller_test.rb +30 -0
- data/test/test_helper.rb +6 -0
- data/test/unit/inheritance_column_test.rb +19 -8
- data/test/unit/model_test.rb +9 -9
- metadata +31 -17
data/README.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
# Extended
|
2
|
+
|
3
|
+
Added the possibility to disable/enable PaperTrail from a controller.
|
4
|
+
|
5
|
+
|
6
|
+
|
1
7
|
# PaperTrail
|
2
8
|
|
3
9
|
PaperTrail lets you track changes to your models' data. It's good for auditing or versioning. You can see how a model looked at any stage in its lifecycle, revert it to any version, and even undelete it after it's been destroyed.
|
@@ -18,6 +24,7 @@ There's an excellent [Railscast on implementing Undo with Paper Trail](http://ra
|
|
18
24
|
* Allows you to store arbitrary model-level metadata with each version (useful for filtering versions).
|
19
25
|
* Allows you to store arbitrary controller-level information with each version, e.g. remote IP.
|
20
26
|
* Can be turned off/on per class (useful for migrations).
|
27
|
+
* Can be turned off/on per request (useful for testing with an external service).
|
21
28
|
* Can be turned off/on globally (useful for testing).
|
22
29
|
* No configuration necessary.
|
23
30
|
* Stores everything in a single database table by default (generates migration for you), or can use separate tables for separate models.
|
@@ -478,15 +485,11 @@ For diffing two ActiveRecord objects:
|
|
478
485
|
|
479
486
|
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.
|
480
487
|
|
481
|
-
|
488
|
+
You can turn PaperTrail on or off in three ways: globally, per request, or per class.
|
482
489
|
|
483
|
-
|
490
|
+
### Globally
|
484
491
|
|
485
|
-
|
486
|
-
|
487
|
-
>> Widget.paper_trail_on
|
488
|
-
|
489
|
-
You can also disable PaperTrail for all models:
|
492
|
+
On a global level you can turn PaperTrail off like this:
|
490
493
|
|
491
494
|
>> PaperTrail.enabled = false
|
492
495
|
|
@@ -518,6 +521,27 @@ And then use it in your tests like this:
|
|
518
521
|
end
|
519
522
|
end
|
520
523
|
|
524
|
+
### Per request
|
525
|
+
|
526
|
+
You can turn PaperTrail on or off per request by adding a `paper_trail_enabled_for_controller` method to your controller which returns true or false:
|
527
|
+
|
528
|
+
class ApplicationController < ActionController::Base
|
529
|
+
def paper_trail_enabled_for_controller
|
530
|
+
request.user_agent != 'Disable User-Agent'
|
531
|
+
end
|
532
|
+
end
|
533
|
+
|
534
|
+
### Per class
|
535
|
+
|
536
|
+
If you are about change some widgets and you don't want a paper trail of your changes, you can turn PaperTrail off like this:
|
537
|
+
|
538
|
+
>> Widget.paper_trail_off
|
539
|
+
|
540
|
+
And on again like this:
|
541
|
+
|
542
|
+
>> Widget.paper_trail_on
|
543
|
+
|
544
|
+
|
521
545
|
|
522
546
|
## Deleting Old Versions
|
523
547
|
|
@@ -583,6 +607,7 @@ Many thanks to:
|
|
583
607
|
* [Matthew MacLeod](https://github.com/mattmacleod)
|
584
608
|
* [benzittlau](https://github.com/benzittlau)
|
585
609
|
* [Tom Derks](https://github.com/EgoH)
|
610
|
+
* [Jonas Hoglund](https://github.com/jhoglund)
|
586
611
|
|
587
612
|
|
588
613
|
## Inspirations
|
@@ -4,6 +4,7 @@ module PaperTrail
|
|
4
4
|
def self.included(base)
|
5
5
|
base.before_filter :set_paper_trail_whodunnit
|
6
6
|
base.before_filter :set_paper_trail_controller_info
|
7
|
+
base.before_filter :set_paper_trail_enabled_for_controller
|
7
8
|
end
|
8
9
|
|
9
10
|
protected
|
@@ -40,6 +41,13 @@ module PaperTrail
|
|
40
41
|
|
41
42
|
private
|
42
43
|
|
44
|
+
# Tells PaperTrail if version should be saved.
|
45
|
+
def set_paper_trail_enabled_for_controller
|
46
|
+
if respond_to? :paper_trail_enabled_for_controller
|
47
|
+
::PaperTrail.enabled_for_controller = paper_trail_enabled_for_controller
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
43
51
|
# Tells PaperTrail who is responsible for any changes that occur.
|
44
52
|
def set_paper_trail_whodunnit
|
45
53
|
::PaperTrail.whodunnit = user_for_paper_trail
|
@@ -38,10 +38,8 @@ module PaperTrail
|
|
38
38
|
cattr_accessor :meta
|
39
39
|
self.meta = options[:meta] || {}
|
40
40
|
|
41
|
-
|
42
|
-
|
43
|
-
cattr_accessor :paper_trail_active
|
44
|
-
self.paper_trail_active = true
|
41
|
+
cattr_accessor :paper_trail_enabled_for_model
|
42
|
+
self.paper_trail_enabled_for_model = true
|
45
43
|
|
46
44
|
has_many :versions, :class_name => version_class_name, :as => :item, :order => 'created_at ASC, id ASC'
|
47
45
|
|
@@ -52,12 +50,12 @@ module PaperTrail
|
|
52
50
|
|
53
51
|
# Switches PaperTrail off for this class.
|
54
52
|
def paper_trail_off
|
55
|
-
self.
|
53
|
+
self.paper_trail_enabled_for_model = false
|
56
54
|
end
|
57
55
|
|
58
56
|
# Switches PaperTrail on for this class.
|
59
57
|
def paper_trail_on
|
60
|
-
self.
|
58
|
+
self.paper_trail_enabled_for_model = true
|
61
59
|
end
|
62
60
|
end
|
63
61
|
|
@@ -167,10 +165,8 @@ module PaperTrail
|
|
167
165
|
changed - self.class.ignore
|
168
166
|
end
|
169
167
|
|
170
|
-
# Returns `true` if PaperTrail is globally enabled and active for this class,
|
171
|
-
# `false` otherwise.
|
172
168
|
def switched_on?
|
173
|
-
PaperTrail.enabled? && self.class.
|
169
|
+
PaperTrail.enabled? && PaperTrail.enabled_for_controller? && self.class.paper_trail_enabled_for_model
|
174
170
|
end
|
175
171
|
end
|
176
172
|
|
data/lib/paper_trail.rb
CHANGED
@@ -20,6 +20,15 @@ module PaperTrail
|
|
20
20
|
!!PaperTrail.config.enabled
|
21
21
|
end
|
22
22
|
|
23
|
+
# Returns `true` if PaperTrail is enabled for the controller, `false` otherwise.
|
24
|
+
def self.enabled_for_controller?
|
25
|
+
!!paper_trail_store[:request_enabled_for_controller]
|
26
|
+
end
|
27
|
+
|
28
|
+
# Sets if PaperTrails is disabled by controller
|
29
|
+
def self.enabled_for_controller=(value)
|
30
|
+
paper_trail_store[:request_enabled_for_controller] = value
|
31
|
+
end
|
23
32
|
|
24
33
|
# Returns who is reponsible for any changes that occur.
|
25
34
|
def self.whodunnit
|
data/paper_trail.gemspec
CHANGED
@@ -7,6 +7,36 @@ class ControllerTest < ActionController::TestCase
|
|
7
7
|
@request.env['REMOTE_ADDR'] = '127.0.0.1'
|
8
8
|
end
|
9
9
|
|
10
|
+
teardown do
|
11
|
+
PaperTrail.enabled_for_controller = true
|
12
|
+
end
|
13
|
+
|
14
|
+
test 'disable on create' do
|
15
|
+
@request.env['HTTP_USER_AGENT'] = 'Disable User-Agent'
|
16
|
+
post :create, :widget => { :name => 'Flugel' }
|
17
|
+
assert_equal 0, assigns(:widget).versions.length
|
18
|
+
end
|
19
|
+
|
20
|
+
test 'disable on update' do
|
21
|
+
@request.env['HTTP_USER_AGENT'] = 'Disable User-Agent'
|
22
|
+
post :create, :widget => { :name => 'Flugel' }
|
23
|
+
w = assigns(:widget)
|
24
|
+
assert_equal 0, w.versions.length
|
25
|
+
put :update, :id => w.id, :widget => { :name => 'Bugle' }
|
26
|
+
widget = assigns(:widget)
|
27
|
+
assert_equal 0, widget.versions.length
|
28
|
+
end
|
29
|
+
|
30
|
+
test 'disable on destroy' do
|
31
|
+
@request.env['HTTP_USER_AGENT'] = 'Disable User-Agent'
|
32
|
+
post :create, :widget => { :name => 'Flugel' }
|
33
|
+
w = assigns(:widget)
|
34
|
+
assert_equal 0, w.versions.length
|
35
|
+
delete :destroy, :id => w.id
|
36
|
+
widget = assigns(:widget)
|
37
|
+
assert_equal 0, Version.with_item_keys('Widget', w.id).size
|
38
|
+
end
|
39
|
+
|
10
40
|
test 'create' do
|
11
41
|
post :create, :widget => { :name => 'Flugel' }
|
12
42
|
widget = assigns(:widget)
|
data/test/test_helper.rb
CHANGED
@@ -4,6 +4,12 @@ ENV["RAILS_ENV"] = "test"
|
|
4
4
|
require File.expand_path("../dummy/config/environment.rb", __FILE__)
|
5
5
|
require "rails/test_help"
|
6
6
|
|
7
|
+
begin
|
8
|
+
require 'turn'
|
9
|
+
rescue LoadError
|
10
|
+
# noop
|
11
|
+
end
|
12
|
+
|
7
13
|
#ActionMailer::Base.delivery_method = :test
|
8
14
|
#ActionMailer::Base.perform_deliveries = true
|
9
15
|
#ActionMailer::Base.default_url_options[:host] = "test.com"
|
@@ -7,25 +7,36 @@ class InheritanceColumnTest < ActiveSupport::TestCase
|
|
7
7
|
@animal = Animal.create :name => 'Animal'
|
8
8
|
@animal.update_attributes :name => 'Animal from the Muppets'
|
9
9
|
@animal.update_attributes :name => 'Animal Muppet'
|
10
|
+
@animal.destroy
|
10
11
|
|
11
12
|
@dog = Dog.create :name => 'Snoopy'
|
12
13
|
@dog.update_attributes :name => 'Scooby'
|
13
14
|
@dog.update_attributes :name => 'Scooby Doo'
|
15
|
+
@dog.destroy
|
14
16
|
|
15
17
|
@cat = Cat.create :name => 'Garfield'
|
16
18
|
@cat.update_attributes :name => 'Garfield (I hate Mondays)'
|
17
19
|
@cat.update_attributes :name => 'Garfield The Cat'
|
20
|
+
@cat.destroy
|
18
21
|
end
|
19
22
|
|
20
23
|
should 'work with custom STI inheritance column' do
|
21
|
-
assert_equal
|
22
|
-
assert_equal
|
23
|
-
|
24
|
-
assert_equal
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
24
|
+
assert_equal 12, Version.count
|
25
|
+
assert_equal 4, @animal.versions.count
|
26
|
+
assert @animal.versions.first.reify.nil?
|
27
|
+
@animal.versions[1..-1].each { |v| assert_equal 'Animal', v.reify.class.name }
|
28
|
+
|
29
|
+
# For some reason `@dog.versions` doesn't include the final `destroy` version.
|
30
|
+
# Neither do `@dog.versions.scoped` nor `@dog.versions(true)` nor `@dog.versions.reload`.
|
31
|
+
dog_versions = Version.where(:item_id => @dog.id)
|
32
|
+
assert_equal 4, dog_versions.count
|
33
|
+
assert dog_versions.first.reify.nil?
|
34
|
+
dog_versions[1..-1].each { |v| assert_equal 'Dog', v.reify.class.name }
|
35
|
+
|
36
|
+
cat_versions = Version.where(:item_id => @cat.id)
|
37
|
+
assert_equal 4, cat_versions.count
|
38
|
+
assert cat_versions.first.reify.nil?
|
39
|
+
cat_versions[1..-1].each { |v| assert_equal 'Cat', v.reify.class.name }
|
29
40
|
end
|
30
41
|
end
|
31
42
|
|
data/test/unit/model_test.rb
CHANGED
@@ -14,7 +14,7 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase
|
|
14
14
|
setup { @article.update_attributes :title => 'My first title', :content => 'Some text here.' }
|
15
15
|
should_change('the number of versions', :by => 1) { Version.count }
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
context 'which updates a selected column' do
|
19
19
|
setup { @article.update_attributes :content => 'Some text here.' }
|
20
20
|
should_change('the number of versions', :by => 1) { Version.count }
|
@@ -24,7 +24,7 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase
|
|
24
24
|
setup { @article.update_attributes :abstract => 'Other abstract'}
|
25
25
|
should_not_change('the number of versions') { Version.count }
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
end
|
29
29
|
|
30
30
|
|
@@ -712,36 +712,36 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase
|
|
712
712
|
|
713
713
|
context 'A new model instance which uses a custom Version class' do
|
714
714
|
setup { @post = Post.new }
|
715
|
-
|
715
|
+
|
716
716
|
context 'which is then saved' do
|
717
717
|
setup { @post.save }
|
718
718
|
should_change('the number of post versions') { PostVersion.count }
|
719
719
|
should_not_change('the number of versions') { Version.count }
|
720
720
|
end
|
721
721
|
end
|
722
|
-
|
722
|
+
|
723
723
|
context 'An existing model instance which uses a custom Version class' do
|
724
724
|
setup { @post = Post.create }
|
725
|
-
|
725
|
+
|
726
726
|
context 'on the first version' do
|
727
727
|
setup { @version = @post.versions.first }
|
728
|
-
|
728
|
+
|
729
729
|
should 'have the correct index' do
|
730
730
|
assert_equal 0, @version.index
|
731
731
|
end
|
732
732
|
end
|
733
|
-
|
733
|
+
|
734
734
|
should 'should have versions of the custom class' do
|
735
735
|
assert_equal "PostVersion", @post.versions.first.class.name
|
736
736
|
end
|
737
|
-
|
737
|
+
|
738
738
|
context 'which is modified' do
|
739
739
|
setup { @post.update_attributes({ :content => "Some new content" }) }
|
740
740
|
should_change('the number of post versions') { PostVersion.count }
|
741
741
|
should_not_change('the number of versions') { Version.count }
|
742
742
|
end
|
743
743
|
end
|
744
|
-
|
744
|
+
|
745
745
|
|
746
746
|
context 'An overwritten default accessor' do
|
747
747
|
setup do
|
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: 7
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 2
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 2.
|
8
|
+
- 2
|
9
|
+
- 0
|
10
|
+
version: 2.2.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Andy Stewart
|
@@ -15,13 +15,12 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-04-05 00:00:00 +01:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
|
-
name: rails
|
23
22
|
prerelease: false
|
24
|
-
|
23
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
25
24
|
none: false
|
26
25
|
requirements:
|
27
26
|
- - ~>
|
@@ -30,12 +29,12 @@ dependencies:
|
|
30
29
|
segments:
|
31
30
|
- 3
|
32
31
|
version: "3"
|
32
|
+
requirement: *id001
|
33
|
+
name: rails
|
33
34
|
type: :runtime
|
34
|
-
version_requirements: *id001
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
|
-
name: shoulda
|
37
36
|
prerelease: false
|
38
|
-
|
37
|
+
version_requirements: &id002 !ruby/object:Gem::Requirement
|
39
38
|
none: false
|
40
39
|
requirements:
|
41
40
|
- - "="
|
@@ -46,12 +45,12 @@ dependencies:
|
|
46
45
|
- 10
|
47
46
|
- 3
|
48
47
|
version: 2.10.3
|
48
|
+
requirement: *id002
|
49
|
+
name: shoulda
|
49
50
|
type: :development
|
50
|
-
version_requirements: *id002
|
51
51
|
- !ruby/object:Gem::Dependency
|
52
|
-
name: sqlite3-ruby
|
53
52
|
prerelease: false
|
54
|
-
|
53
|
+
version_requirements: &id003 !ruby/object:Gem::Requirement
|
55
54
|
none: false
|
56
55
|
requirements:
|
57
56
|
- - ~>
|
@@ -61,12 +60,12 @@ dependencies:
|
|
61
60
|
- 1
|
62
61
|
- 2
|
63
62
|
version: "1.2"
|
63
|
+
requirement: *id003
|
64
|
+
name: sqlite3-ruby
|
64
65
|
type: :development
|
65
|
-
version_requirements: *id003
|
66
66
|
- !ruby/object:Gem::Dependency
|
67
|
-
name: capybara
|
68
67
|
prerelease: false
|
69
|
-
|
68
|
+
version_requirements: &id004 !ruby/object:Gem::Requirement
|
70
69
|
none: false
|
71
70
|
requirements:
|
72
71
|
- - ">="
|
@@ -77,8 +76,23 @@ dependencies:
|
|
77
76
|
- 4
|
78
77
|
- 0
|
79
78
|
version: 0.4.0
|
79
|
+
requirement: *id004
|
80
|
+
name: capybara
|
81
|
+
type: :development
|
82
|
+
- !ruby/object:Gem::Dependency
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: &id005 !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
hash: 3
|
90
|
+
segments:
|
91
|
+
- 0
|
92
|
+
version: "0"
|
93
|
+
requirement: *id005
|
94
|
+
name: turn
|
80
95
|
type: :development
|
81
|
-
version_requirements: *id004
|
82
96
|
description: Track changes to your models' data. Good for auditing or versioning.
|
83
97
|
email: boss@airbladesoftware.com
|
84
98
|
executables: []
|