paper_trail 2.0.2 → 2.1.0

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 CHANGED
@@ -1,6 +1,9 @@
1
1
  test/debug.log
2
2
  test/paper_trail_plugin.sqlite3.db
3
+ test/dummy/log/*
4
+ test/dummy/tmp/*
3
5
  coverage
4
6
  pkg/*
5
7
  *.gem
6
8
  .bundle
9
+ Gemfile.lock
data/README.md CHANGED
@@ -20,7 +20,8 @@ There's an excellent [Railscast on implementing Undo with Paper Trail](http://ra
20
20
  * Can be turned off/on per class (useful for migrations).
21
21
  * Can be turned off/on globally (useful for testing).
22
22
  * No configuration necessary.
23
- * Stores everything in a single database table (generates migration for you).
23
+ * Stores everything in a single database table by default (generates migration for you), or can use separate tables for separate models.
24
+ * Supports custom version classes so different models' versions can have different behaviour.
24
25
  * Thoroughly tested.
25
26
  * Threadsafe.
26
27
 
@@ -308,6 +309,24 @@ To find out who made a `version`'s object look that way, use `version.originator
308
309
  >> last_version.terminator # 'Bob'
309
310
 
310
311
 
312
+ ## Custom Version Classes
313
+
314
+ You can specify custom version subclasses with the `:class_name` option:
315
+
316
+ class Post < ActiveRecord::Base
317
+ has_paper_trail :class_name => 'PostVersion'
318
+ end
319
+
320
+ class PostVersion < Version
321
+ # custom behaviour, e.g:
322
+ set_table_name :post_versions
323
+ end
324
+
325
+ This allows you to store each model's versions in a separate table, which is useful if you have a lot of versions being created.
326
+
327
+ Alternatively you could store certain metadata for one type of version, and other metadata for other versions.
328
+
329
+
311
330
  ## Associations
312
331
 
313
332
  I haven't yet found a good way to get PaperTrail to automatically restore associations when you reify a model. See [here for a little more info](http://airbladesoftware.com/notes/undo-and-redo-with-papertrail).
@@ -562,6 +581,7 @@ Many thanks to:
562
581
  * [Franco Catena](https://github.com/francocatena)
563
582
  * [Emmanuel Gomez](https://github.com/emmanuel)
564
583
  * [Matthew MacLeod](https://github.com/mattmacleod)
584
+ * [benzittlau](https://github.com/benzittlau)
565
585
 
566
586
 
567
587
  ## Inspirations
@@ -11,12 +11,13 @@ module PaperTrail
11
11
  # the model is available in the `versions` association.
12
12
  #
13
13
  # Options:
14
- # :ignore an array of attributes for which a new `Version` will not be created if only they change.
15
- # :only inverse of `ignore` - a new `Version` will be created only for these attributes if supplied
16
- # :meta a hash of extra data to store. You must add a column to the `versions` table for each key.
17
- # Values are objects or procs (which are called with `self`, i.e. the model with the paper
18
- # trail). See `PaperTrail::Controller.info_for_paper_trail` for how to store data from
19
- # the controller.
14
+ # :class_name the name of a custom Version class. This class should inherit from Version.
15
+ # :ignore an array of attributes for which a new `Version` will not be created if only they change.
16
+ # :only inverse of `ignore` - a new `Version` will be created only for these attributes if supplied
17
+ # :meta a hash of extra data to store. You must add a column to the `versions` table for each key.
18
+ # Values are objects or procs (which are called with `self`, i.e. the model with the paper
19
+ # trail). See `PaperTrail::Controller.info_for_paper_trail` for how to store data from
20
+ # the controller.
20
21
  def has_paper_trail(options = {})
21
22
  # Lazily include the instance methods so we don't clutter up
22
23
  # any more ActiveRecord models than we have to.
@@ -24,6 +25,9 @@ module PaperTrail
24
25
 
25
26
  # The version this instance was reified from.
26
27
  attr_accessor :version
28
+
29
+ cattr_accessor :version_class_name
30
+ self.version_class_name = options[:class_name] || "Version"
27
31
 
28
32
  cattr_accessor :ignore
29
33
  self.ignore = ([options[:ignore]].flatten.compact || []).map &:to_s
@@ -39,7 +43,7 @@ module PaperTrail
39
43
  cattr_accessor :paper_trail_active
40
44
  self.paper_trail_active = true
41
45
 
42
- has_many :versions, :as => :item, :order => 'created_at ASC, id ASC'
46
+ has_many :versions, :class_name => version_class_name, :as => :item, :order => 'created_at ASC, id ASC'
43
47
 
44
48
  after_create :record_create
45
49
  before_update :record_update
@@ -68,7 +72,7 @@ module PaperTrail
68
72
 
69
73
  # Returns who put the object into its current state.
70
74
  def originator
71
- Version.with_item_keys(self.class.name, id).last.try :whodunnit
75
+ version_class_name.constantize.with_item_keys(self.class.name, id).last.try :whodunnit
72
76
  end
73
77
 
74
78
  # Returns the object (not a Version) as it was at the given timestamp.
@@ -111,7 +115,7 @@ module PaperTrail
111
115
 
112
116
  def record_destroy
113
117
  if switched_on? and not new_record?
114
- Version.create merge_metadata(:item_id => self.id,
118
+ version_class_name.constantize.create merge_metadata(:item_id => self.id,
115
119
  :item_type => self.class.name,
116
120
  :event => 'destroy',
117
121
  :object => object_to_string(item_before_change),
@@ -2,16 +2,16 @@ class Version < ActiveRecord::Base
2
2
  belongs_to :item, :polymorphic => true
3
3
  validates_presence_of :event
4
4
 
5
- scope :with_item_keys, lambda { |item_type, item_id|
6
- where(:item_type => item_type, :item_id => item_id)
7
- }
5
+ def self.with_item_keys(item_type, item_id)
6
+ scoped(:conditions => { :item_type => item_type, :item_id => item_id })
7
+ end
8
8
 
9
9
  scope :subsequent, lambda { |version|
10
- where(["id > ?", version.is_a?(Version) ? version.id : version]).order("id ASC")
10
+ where(["id > ?", version.is_a?(self) ? version.id : version]).order("id ASC")
11
11
  }
12
12
 
13
13
  scope :preceding, lambda { |version|
14
- where(["id < ?", version.is_a?(Version) ? version.id : version]).order("id DESC")
14
+ where(["id < ?", version.is_a?(self) ? version.id : version]).order("id DESC")
15
15
  }
16
16
 
17
17
  scope :after, lambda { |timestamp|
@@ -87,7 +87,7 @@ class Version < ActiveRecord::Base
87
87
  end
88
88
 
89
89
  def sibling_versions
90
- Version.with_item_keys(item_type, item_id)
90
+ self.class.with_item_keys(item_type, item_id)
91
91
  end
92
92
 
93
93
  def next
@@ -1,3 +1,3 @@
1
1
  module PaperTrail
2
- VERSION = '2.0.2'
2
+ VERSION = '2.1.0'
3
3
  end
@@ -0,0 +1,4 @@
1
+ class Post < ActiveRecord::Base
2
+ has_paper_trail :class_name => "PostVersion"
3
+
4
+ end
@@ -0,0 +1,3 @@
1
+ class PostVersion < Version
2
+ set_table_name :post_versions
3
+ end
Binary file
@@ -34,6 +34,20 @@ class SetUpTestTables < ActiveRecord::Migration
34
34
  t.string :user_agent
35
35
  end
36
36
  add_index :versions, [:item_type, :item_id]
37
+
38
+ create_table :post_versions, :force => true do |t|
39
+ t.string :item_type, :null => false
40
+ t.integer :item_id, :null => false
41
+ t.string :event, :null => false
42
+ t.string :whodunnit
43
+ t.text :object
44
+ t.datetime :created_at
45
+
46
+ # Controller info columns.
47
+ t.string :ip
48
+ t.string :user_agent
49
+ end
50
+ add_index :post_versions, [:item_type, :item_id]
37
51
 
38
52
  create_table :wotsits, :force => true do |t|
39
53
  t.integer :widget_id
@@ -68,9 +82,15 @@ class SetUpTestTables < ActiveRecord::Migration
68
82
  create_table :songs, :force => true do |t|
69
83
  t.integer :length
70
84
  end
85
+
86
+ create_table :posts, :force => true do |t|
87
+ t.string :title
88
+ t.string :content
89
+ end
71
90
  end
72
91
 
73
92
  def self.down
93
+ drop_table :posts
74
94
  drop_table :songs
75
95
  drop_table :people
76
96
  drop_table :authorships
@@ -78,6 +98,8 @@ class SetUpTestTables < ActiveRecord::Migration
78
98
  drop_table :articles
79
99
  drop_table :fluxors
80
100
  drop_table :wotsits
101
+ remove_index :post_versions, :column => [:item_type, :item_id]
102
+ drop_table :post_versions
81
103
  remove_index :versions, :column => [:item_type, :item_id]
82
104
  drop_table :versions
83
105
  drop_table :widgets
@@ -36,6 +36,24 @@ ActiveRecord::Schema.define(:version => 20110208155312) do
36
36
  t.string "name"
37
37
  end
38
38
 
39
+ create_table "post_versions", :force => true do |t|
40
+ t.string "item_type", :null => false
41
+ t.integer "item_id", :null => false
42
+ t.string "event", :null => false
43
+ t.string "whodunnit"
44
+ t.text "object"
45
+ t.datetime "created_at"
46
+ t.string "ip"
47
+ t.string "user_agent"
48
+ end
49
+
50
+ add_index "post_versions", ["item_type", "item_id"], :name => "index_post_versions_on_item_type_and_item_id"
51
+
52
+ create_table "posts", :force => true do |t|
53
+ t.string "title"
54
+ t.string "content"
55
+ end
56
+
39
57
  create_table "songs", :force => true do |t|
40
58
  t.integer "length"
41
59
  end
Binary file
@@ -710,6 +710,38 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase
710
710
  end
711
711
  end
712
712
 
713
+ context 'A new model instance which uses a custom Version class' do
714
+ setup { @post = Post.new }
715
+
716
+ context 'which is then saved' do
717
+ setup { @post.save }
718
+ should_change('the number of post versions') { PostVersion.count }
719
+ should_not_change('the number of versions') { Version.count }
720
+ end
721
+ end
722
+
723
+ context 'An existing model instance which uses a custom Version class' do
724
+ setup { @post = Post.create }
725
+
726
+ context 'on the first version' do
727
+ setup { @version = @post.versions.first }
728
+
729
+ should 'have the correct index' do
730
+ assert_equal 0, @version.index
731
+ end
732
+ end
733
+
734
+ should 'should have versions of the custom class' do
735
+ assert_equal "PostVersion", @post.versions.first.class.name
736
+ end
737
+
738
+ context 'which is modified' do
739
+ setup { @post.update_attributes({ :content => "Some new content" }) }
740
+ should_change('the number of post versions') { PostVersion.count }
741
+ should_not_change('the number of versions') { Version.count }
742
+ end
743
+ end
744
+
713
745
 
714
746
  context 'An overwritten default accessor' do
715
747
  setup do
metadata CHANGED
@@ -5,9 +5,9 @@ version: !ruby/object:Gem::Version
5
5
  prerelease: false
6
6
  segments:
7
7
  - 2
8
+ - 1
8
9
  - 0
9
- - 2
10
- version: 2.0.2
10
+ version: 2.1.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Andy Stewart
@@ -15,12 +15,13 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-03-16 00:00:00 +01:00
18
+ date: 2011-03-31 00:00:00 +01:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
+ name: rails
22
23
  prerelease: false
23
- version_requirements: &id001 !ruby/object:Gem::Requirement
24
+ requirement: &id001 !ruby/object:Gem::Requirement
24
25
  none: false
25
26
  requirements:
26
27
  - - ~>
@@ -29,12 +30,12 @@ dependencies:
29
30
  segments:
30
31
  - 3
31
32
  version: "3"
32
- requirement: *id001
33
- name: rails
34
33
  type: :runtime
34
+ version_requirements: *id001
35
35
  - !ruby/object:Gem::Dependency
36
+ name: shoulda
36
37
  prerelease: false
37
- version_requirements: &id002 !ruby/object:Gem::Requirement
38
+ requirement: &id002 !ruby/object:Gem::Requirement
38
39
  none: false
39
40
  requirements:
40
41
  - - "="
@@ -45,12 +46,12 @@ dependencies:
45
46
  - 10
46
47
  - 3
47
48
  version: 2.10.3
48
- requirement: *id002
49
- name: shoulda
50
49
  type: :development
50
+ version_requirements: *id002
51
51
  - !ruby/object:Gem::Dependency
52
+ name: sqlite3-ruby
52
53
  prerelease: false
53
- version_requirements: &id003 !ruby/object:Gem::Requirement
54
+ requirement: &id003 !ruby/object:Gem::Requirement
54
55
  none: false
55
56
  requirements:
56
57
  - - ~>
@@ -60,12 +61,12 @@ dependencies:
60
61
  - 1
61
62
  - 2
62
63
  version: "1.2"
63
- requirement: *id003
64
- name: sqlite3-ruby
65
64
  type: :development
65
+ version_requirements: *id003
66
66
  - !ruby/object:Gem::Dependency
67
+ name: capybara
67
68
  prerelease: false
68
- version_requirements: &id004 !ruby/object:Gem::Requirement
69
+ requirement: &id004 !ruby/object:Gem::Requirement
69
70
  none: false
70
71
  requirements:
71
72
  - - ">="
@@ -76,9 +77,8 @@ dependencies:
76
77
  - 4
77
78
  - 0
78
79
  version: 0.4.0
79
- requirement: *id004
80
- name: capybara
81
80
  type: :development
81
+ version_requirements: *id004
82
82
  description: Track changes to your models' data. Good for auditing or versioning.
83
83
  email: boss@airbladesoftware.com
84
84
  executables: []
@@ -90,7 +90,6 @@ extra_rdoc_files: []
90
90
  files:
91
91
  - .gitignore
92
92
  - Gemfile
93
- - Gemfile.lock
94
93
  - MIT-LICENSE
95
94
  - README.md
96
95
  - Rakefile
@@ -115,9 +114,11 @@ files:
115
114
  - test/dummy/app/models/fluxor.rb
116
115
  - test/dummy/app/models/foo_widget.rb
117
116
  - test/dummy/app/models/person.rb
117
+ - test/dummy/app/models/post.rb
118
118
  - test/dummy/app/models/song.rb
119
119
  - test/dummy/app/models/widget.rb
120
120
  - test/dummy/app/models/wotsit.rb
121
+ - test/dummy/app/versions/post_version.rb
121
122
  - test/dummy/app/views/layouts/application.html.erb
122
123
  - test/dummy/config.ru
123
124
  - test/dummy/config/application.rb
@@ -203,9 +204,11 @@ test_files:
203
204
  - test/dummy/app/models/fluxor.rb
204
205
  - test/dummy/app/models/foo_widget.rb
205
206
  - test/dummy/app/models/person.rb
207
+ - test/dummy/app/models/post.rb
206
208
  - test/dummy/app/models/song.rb
207
209
  - test/dummy/app/models/widget.rb
208
210
  - test/dummy/app/models/wotsit.rb
211
+ - test/dummy/app/versions/post_version.rb
209
212
  - test/dummy/app/views/layouts/application.html.erb
210
213
  - test/dummy/config.ru
211
214
  - test/dummy/config/application.rb
data/Gemfile.lock DELETED
@@ -1,107 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- paper_trail (2.0.2)
5
- rails (~> 3)
6
-
7
- GEM
8
- remote: http://rubygems.org/
9
- specs:
10
- abstract (1.0.0)
11
- actionmailer (3.0.4)
12
- actionpack (= 3.0.4)
13
- mail (~> 2.2.15)
14
- actionpack (3.0.4)
15
- activemodel (= 3.0.4)
16
- activesupport (= 3.0.4)
17
- builder (~> 2.1.2)
18
- erubis (~> 2.6.6)
19
- i18n (~> 0.4)
20
- rack (~> 1.2.1)
21
- rack-mount (~> 0.6.13)
22
- rack-test (~> 0.5.7)
23
- tzinfo (~> 0.3.23)
24
- activemodel (3.0.4)
25
- activesupport (= 3.0.4)
26
- builder (~> 2.1.2)
27
- i18n (~> 0.4)
28
- activerecord (3.0.4)
29
- activemodel (= 3.0.4)
30
- activesupport (= 3.0.4)
31
- arel (~> 2.0.2)
32
- tzinfo (~> 0.3.23)
33
- activeresource (3.0.4)
34
- activemodel (= 3.0.4)
35
- activesupport (= 3.0.4)
36
- activesupport (3.0.4)
37
- arel (2.0.9)
38
- builder (2.1.2)
39
- capybara (0.4.1.1)
40
- celerity (>= 0.7.9)
41
- culerity (>= 0.2.4)
42
- mime-types (>= 1.16)
43
- nokogiri (>= 1.3.3)
44
- rack (>= 1.0.0)
45
- rack-test (>= 0.5.4)
46
- selenium-webdriver (>= 0.0.27)
47
- xpath (~> 0.1.3)
48
- celerity (0.8.7)
49
- childprocess (0.1.6)
50
- ffi (~> 0.6.3)
51
- culerity (0.2.15)
52
- erubis (2.6.6)
53
- abstract (>= 1.0.0)
54
- ffi (0.6.3)
55
- rake (>= 0.8.7)
56
- i18n (0.5.0)
57
- json_pure (1.5.1)
58
- mail (2.2.15)
59
- activesupport (>= 2.3.6)
60
- i18n (>= 0.4.0)
61
- mime-types (~> 1.16)
62
- treetop (~> 1.4.8)
63
- mime-types (1.16)
64
- nokogiri (1.4.4)
65
- polyglot (0.3.1)
66
- rack (1.2.1)
67
- rack-mount (0.6.13)
68
- rack (>= 1.0.0)
69
- rack-test (0.5.7)
70
- rack (>= 1.0)
71
- rails (3.0.4)
72
- actionmailer (= 3.0.4)
73
- actionpack (= 3.0.4)
74
- activerecord (= 3.0.4)
75
- activeresource (= 3.0.4)
76
- activesupport (= 3.0.4)
77
- bundler (~> 1.0)
78
- railties (= 3.0.4)
79
- railties (3.0.4)
80
- actionpack (= 3.0.4)
81
- activesupport (= 3.0.4)
82
- rake (>= 0.8.7)
83
- thor (~> 0.14.4)
84
- rake (0.8.7)
85
- rubyzip (0.9.4)
86
- selenium-webdriver (0.1.2)
87
- childprocess (~> 0.1.5)
88
- ffi (~> 0.6.3)
89
- json_pure
90
- rubyzip
91
- shoulda (2.10.3)
92
- sqlite3-ruby (1.3.1)
93
- thor (0.14.6)
94
- treetop (1.4.9)
95
- polyglot (>= 0.3.1)
96
- tzinfo (0.3.24)
97
- xpath (0.1.3)
98
- nokogiri (~> 1.3)
99
-
100
- PLATFORMS
101
- ruby
102
-
103
- DEPENDENCIES
104
- capybara (>= 0.4.0)
105
- paper_trail!
106
- shoulda (= 2.10.3)
107
- sqlite3-ruby (~> 1.2)