paper_trail 1.5.2 → 1.5.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -25,7 +25,7 @@ PaperTrail lets you track changes to your models' data. It's good for auditing
25
25
 
26
26
  ## Rails Version
27
27
 
28
- Reported to work on Rails 3 (though I haven't yet tried myself). Known to work on Rails 2.3. Probably works on Rails 2.2 and 2.1.
28
+ Works on Rails 3 and Rails 2.3. Probably works on Rails 2.2 and 2.1.
29
29
 
30
30
 
31
31
  ## Basic Usage
@@ -212,6 +212,48 @@ To find out who made a `version`'s object look that way, use `version.originator
212
212
  >> last_version.terminator # 'Bob'
213
213
 
214
214
 
215
+ ## Has-Many-Through Associations
216
+
217
+ PaperTrail can track most changes to the join table. Specifically it can track all additions but it can only track removals which fire the `after_destroy` callback on the join table. Here are some examples:
218
+
219
+ Given these models:
220
+
221
+ class Book < ActiveRecord::Base
222
+ has_many :authorships, :dependent => :destroy
223
+ has_many :authors, :through => :authorships, :source => :person
224
+ has_paper_trail
225
+ end
226
+
227
+ class Authorship < ActiveRecord::Base
228
+ belongs_to :book
229
+ belongs_to :person
230
+ has_paper_trail # NOTE
231
+ end
232
+
233
+ class Person < ActiveRecord::Base
234
+ has_many :authorships, :dependent => :destroy
235
+ has_many :books, :through => :authorships
236
+ has_paper_trail
237
+ end
238
+
239
+ Then each of the following will store authorship versions:
240
+
241
+ >> @book.authors << @dostoyevsky
242
+ >> @book.authors.create :name => 'Tolstoy'
243
+ >> @book.authorships.last.destroy
244
+ >> @book.authorships.clear
245
+
246
+ But none of these will:
247
+
248
+ >> @book.authors.delete @tolstoy
249
+ >> @book.author_ids = [@solzhenistyn.id, @dostoyevsky.id]
250
+ >> @book.authors = []
251
+
252
+ Having said that, you can probably (I haven't tested it myself) get the first one (`@book.authors.delete @tolstoy`) working with this [monkey patch](http://stackoverflow.com/questions/2381033/how-to-create-a-full-audit-log-in-rails-for-every-table/2381411#2381411). Many thanks to Danny Trelogan for pointing it out.
253
+
254
+ 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.
255
+
256
+
215
257
  ## Storing metadata
216
258
 
217
259
  You can store arbitrary model-level metadata alongside each version like this:
@@ -315,9 +357,27 @@ Over time your `versions` table will grow to an unwieldy size. Because each ver
315
357
 
316
358
  ## Installation
317
359
 
360
+ ### Rails 3
361
+
362
+ 1. Install PaperTrail as a gem via your `Gemfile`:
363
+
364
+ `gem 'paper_trail'`
365
+
366
+ 2. Generate a migration which will add a `versions` table to your database.
367
+
368
+ `rails generate paper_trail`
369
+
370
+ 3. Run the migration.
371
+
372
+ `rake db:migrate`
373
+
374
+ 4. Add `has_paper_trail` to the models you want to track.
375
+
376
+ ### Rails 2
377
+
318
378
  1. Install PaperTrail as a gem via your `config/environment.rb`:
319
379
 
320
- `config.gem 'paper_trail'
380
+ `config.gem 'paper_trail'`
321
381
 
322
382
  2. Generate a migration which will add a `versions` table to your database.
323
383
 
@@ -353,6 +413,7 @@ Many thanks to:
353
413
  * [Jeremy Weiskotten](http://github.com/jeremyw)
354
414
  * [Phan Le](http://github.com/revo)
355
415
  * [jdrucza](http://github.com/jdrucza)
416
+ * [conickal](http://github.com/conickal)
356
417
 
357
418
 
358
419
  ## Inspirations
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.5.2
1
+ 1.5.3
@@ -0,0 +1,2 @@
1
+ Description:
2
+ Generates (but does not run) a migration to add a versions table.
@@ -0,0 +1,24 @@
1
+ require 'rails/generators/named_base'
2
+ require 'rails/generators/migration'
3
+
4
+ class PaperTrailGenerator < Rails::Generators::NamedBase
5
+ include Rails::Generators::Migration
6
+
7
+ desc "Generates (but does not run) a migration to add a versions table."
8
+ source_root File.expand_path('../templates', __FILE__)
9
+ argument :name, :type => :string, :default => "create_versions"
10
+
11
+ # Implement the required interface for Rails::Generators::Migration.
12
+ # taken from http://github.com/rails/rails/blob/master/activerecord/lib/generators/active_record.rb
13
+ def self.next_migration_number(dirname)
14
+ if ActiveRecord::Base.timestamped_migrations
15
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
16
+ else
17
+ "%.3d" % (current_migration_number(dirname) + 1)
18
+ end
19
+ end
20
+
21
+ def create_migration_file
22
+ migration_template 'create_versions.rb', 'db/migrate/create_versions.rb'
23
+ end
24
+ end
@@ -0,0 +1,18 @@
1
+ class CreateVersions < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :versions do |t|
4
+ t.string :item_type, :null => false
5
+ t.integer :item_id, :null => false
6
+ t.string :event, :null => false
7
+ t.string :whodunnit
8
+ t.text :object
9
+ t.datetime :created_at
10
+ end
11
+ add_index :versions, [:item_type, :item_id]
12
+ end
13
+
14
+ def self.down
15
+ remove_index :versions, [:item_type, :item_id]
16
+ drop_table :versions
17
+ end
18
+ end
data/lib/paper_trail.rb CHANGED
@@ -51,8 +51,6 @@ module PaperTrail
51
51
  private
52
52
 
53
53
  # Thread-safe hash to hold PaperTrail's data.
54
- #
55
- # TODO: is this a memory leak?
56
54
  def self.paper_trail_store
57
55
  Thread.current[:paper_trail] ||= {}
58
56
  end
data/paper_trail.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{paper_trail}
8
- s.version = "1.5.2"
8
+ s.version = "1.5.3"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Andy Stewart"]
12
- s.date = %q{2010-06-28}
12
+ s.date = %q{2010-10-11}
13
13
  s.email = %q{boss@airbladesoftware.com}
14
14
  s.extra_rdoc_files = [
15
15
  "README.md"
@@ -25,6 +25,9 @@ Gem::Specification.new do |s|
25
25
  "generators/paper_trail/templates/create_versions.rb",
26
26
  "init.rb",
27
27
  "install.rb",
28
+ "lib/generators/paper_trail/USAGE",
29
+ "lib/generators/paper_trail/paper_trail_generator.rb",
30
+ "lib/generators/paper_trail/templates/create_versions.rb",
28
31
  "lib/paper_trail.rb",
29
32
  "lib/paper_trail/config.rb",
30
33
  "lib/paper_trail/controller.rb",
@@ -24,6 +24,24 @@ class Article < ActiveRecord::Base
24
24
  :article_id => Proc.new { |article| article.id } }
25
25
  end
26
26
 
27
+ class Book < ActiveRecord::Base
28
+ has_many :authorships, :dependent => :destroy
29
+ has_many :authors, :through => :authorships, :source => :person
30
+ has_paper_trail
31
+ end
32
+
33
+ class Authorship < ActiveRecord::Base
34
+ belongs_to :book
35
+ belongs_to :person
36
+ has_paper_trail
37
+ end
38
+
39
+ class Person < ActiveRecord::Base
40
+ has_many :authorships, :dependent => :destroy
41
+ has_many :books, :through => :authorships
42
+ has_paper_trail
43
+ end
44
+
27
45
 
28
46
  class HasPaperTrailModelTest < Test::Unit::TestCase
29
47
  load_schema
@@ -586,5 +604,44 @@ class HasPaperTrailModelTest < Test::Unit::TestCase
586
604
  end
587
605
  end
588
606
 
607
+ context ":has_many :through" do
608
+ setup do
609
+ @book = Book.create :title => 'War and Peace'
610
+ @dostoyevsky = Person.create :name => 'Dostoyevsky'
611
+ @solzhenitsyn = Person.create :name => 'Solzhenitsyn'
612
+ end
613
+
614
+ should 'store version on source <<' do
615
+ count = Version.count
616
+ @book.authors << @dostoyevsky
617
+ assert_equal 1, Version.count - count
618
+ assert_equal Version.last, @book.authorships.first.versions.first
619
+ end
620
+
621
+ should 'store version on source create' do
622
+ count = Version.count
623
+ @book.authors.create :name => 'Tolstoy'
624
+ assert_equal 2, Version.count - count
625
+ assert_same_elements [Person.last, Authorship.last], [Version.all[-2].item, Version.last.item]
626
+ end
627
+
628
+ should 'store version on join destroy' do
629
+ @book.authors << @dostoyevsky
630
+ count = Version.count
631
+ @book.authorships(true).last.destroy
632
+ assert_equal 1, Version.count - count
633
+ assert_equal @book, Version.last.reify.book
634
+ assert_equal @dostoyevsky, Version.last.reify.person
635
+ end
636
+
637
+ should 'store version on join clear' do
638
+ @book.authors << @dostoyevsky
639
+ count = Version.count
640
+ @book.authorships(true).clear
641
+ assert_equal 1, Version.count - count
642
+ assert_equal @book, Version.last.reify.book
643
+ assert_equal @dostoyevsky, Version.last.reify.person
644
+ end
645
+ end
589
646
 
590
647
  end
data/test/schema.rb CHANGED
@@ -49,4 +49,17 @@ ActiveRecord::Schema.define(:version => 0) do
49
49
  t.string :content
50
50
  end
51
51
 
52
+ create_table :books, :force => true do |t|
53
+ t.string :title
54
+ end
55
+
56
+ create_table :authorships, :force => true do |t|
57
+ t.integer :book_id
58
+ t.integer :person_id
59
+ end
60
+
61
+ create_table :people, :force => true do |t|
62
+ t.string :name
63
+ end
64
+
52
65
  end
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: 7
4
+ hash: 5
5
5
  prerelease: false
6
6
  segments:
7
7
  - 1
8
8
  - 5
9
- - 2
10
- version: 1.5.2
9
+ - 3
10
+ version: 1.5.3
11
11
  platform: ruby
12
12
  authors:
13
13
  - Andy Stewart
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-06-28 00:00:00 +01:00
18
+ date: 2010-10-11 00:00:00 +01:00
19
19
  default_executable:
20
20
  dependencies: []
21
21
 
@@ -38,6 +38,9 @@ files:
38
38
  - generators/paper_trail/templates/create_versions.rb
39
39
  - init.rb
40
40
  - install.rb
41
+ - lib/generators/paper_trail/USAGE
42
+ - lib/generators/paper_trail/paper_trail_generator.rb
43
+ - lib/generators/paper_trail/templates/create_versions.rb
41
44
  - lib/paper_trail.rb
42
45
  - lib/paper_trail/config.rb
43
46
  - lib/paper_trail/controller.rb