airblade-paper_trail 1.0.1 → 1.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 ADDED
@@ -0,0 +1,2 @@
1
+ test/debug.log
2
+ test/paper_trail_plugin.sqlite3.db
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2009 [name of plugin creator]
1
+ Copyright (c) 2009 Andy Stewart, AirBlade Software Ltd.
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -127,9 +127,11 @@ And on again like this:
127
127
 
128
128
  `config.gem 'airblade-paper_trail', :lib => 'paper_trail', :source => 'http://gems.github.com'`
129
129
 
130
+ or:
131
+
130
132
  `script/plugin install git://github.com/airblade/paper_trail.git`
131
133
 
132
- 2. Generate a migration which wll add a `versions` table to your database.
134
+ 2. Generate a migration which will add a `versions` table to your database.
133
135
 
134
136
  `script/generate paper_trail`
135
137
 
@@ -8,9 +8,11 @@ class CreateVersions < ActiveRecord::Migration
8
8
  t.text :object
9
9
  t.datetime :created_at
10
10
  end
11
+ add_index :versions, [:item_type, :item_id]
11
12
  end
12
13
 
13
14
  def self.down
15
+ remove_index :versions, [:item_type, :item_id]
14
16
  drop_table :versions
15
17
  end
16
18
  end
@@ -4,17 +4,56 @@ class Version < ActiveRecord::Base
4
4
 
5
5
  def reify
6
6
  unless object.nil?
7
- # Using +item_type.constantize+ rather than +item.class+
8
- # allows us to retrieve destroyed objects.
9
- model = item_type.constantize.new
10
- YAML::load(object).each do |k, v|
7
+ # Attributes
8
+
9
+ attrs = YAML::load object
10
+
11
+ # Normally a polymorphic belongs_to relationship allows us
12
+ # to get the object we belong to by calling, in this case,
13
+ # +item+. However this returns nil if +item+ has been
14
+ # destroyed, and we need to be able to retrieve destroyed
15
+ # objects.
16
+ #
17
+ # In this situation we constantize the +item_type+ to get hold of
18
+ # the class...except when the stored object's attributes
19
+ # include a +type+ key. If this is the case, the object
20
+ # we belong to is using single table inheritance and the
21
+ # +item_type+ will be the base class, not the actual subclass.
22
+ # If +type+ is present but empty, the class is the base class.
23
+
24
+ if item
25
+ model = item
26
+ else
27
+ class_name = attrs['type'].blank? ? item_type : attrs['type']
28
+ klass = class_name.constantize
29
+ model = klass.new
30
+ end
31
+
32
+ attrs.each do |k, v|
11
33
  begin
12
34
  model.send "#{k}=", v
13
35
  rescue NoMethodError
14
36
  RAILS_DEFAULT_LOGGER.warn "Attribute #{k} does not exist on #{item_type} (Version id: #{id})."
15
37
  end
16
38
  end
39
+
17
40
  model
18
41
  end
19
42
  end
43
+
44
+ def next
45
+ Version.first :conditions => ["id > ? AND item_type = ? AND item_id = ?", id, item_type, item_id],
46
+ :order => 'id ASC'
47
+ end
48
+
49
+ def previous
50
+ Version.first :conditions => ["id < ? AND item_type = ? AND item_id = ?", id, item_type, item_id],
51
+ :order => 'id DESC'
52
+ end
53
+
54
+ def index
55
+ Version.all(:conditions => ["item_type = ? AND item_id = ?", item_type, item_id],
56
+ :order => 'id ASC').index(self)
57
+ end
58
+
20
59
  end
data/paper_trail.gemspec CHANGED
@@ -2,17 +2,18 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{paper_trail}
5
- s.version = "1.0.1"
5
+ s.version = "1.1.0"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Andy Stewart"]
9
- s.date = %q{2009-05-28}
9
+ s.date = %q{2009-06-22}
10
10
  s.email = %q{boss@airbladesoftware.com}
11
11
  s.extra_rdoc_files = [
12
12
  "README.md"
13
13
  ]
14
14
  s.files = [
15
- "MIT-LICENSE",
15
+ ".gitignore",
16
+ "MIT-LICENSE",
16
17
  "README.md",
17
18
  "Rakefile",
18
19
  "VERSION",
@@ -2,6 +2,19 @@ require File.dirname(__FILE__) + '/test_helper.rb'
2
2
 
3
3
  class Widget < ActiveRecord::Base
4
4
  has_paper_trail
5
+ has_one :wotsit
6
+ has_many :fluxors, :order => :name
7
+ end
8
+
9
+ class FooWidget < Widget
10
+ end
11
+
12
+ class Wotsit < ActiveRecord::Base
13
+ belongs_to :widget
14
+ end
15
+
16
+ class Fluxor < ActiveRecord::Base
17
+ belongs_to :widget
5
18
  end
6
19
 
7
20
 
@@ -65,22 +78,63 @@ class HasPaperTrailModelTest < Test::Unit::TestCase
65
78
  assert_match /update/i, @widget.versions.last.event
66
79
  end
67
80
 
81
+
82
+ context 'and has one associated object' do
83
+ setup do
84
+ @wotsit = @widget.create_wotsit :name => 'John'
85
+ @reified_widget = @widget.versions.last.reify
86
+ end
87
+
88
+ should 'copy the has_one association when reifying' do
89
+ assert_equal @wotsit, @reified_widget.wotsit
90
+ end
91
+ end
92
+
93
+
94
+ context 'and has many associated objects' do
95
+ setup do
96
+ @f0 = @widget.fluxors.create :name => 'f-zero'
97
+ @f1 = @widget.fluxors.create :name => 'f-one'
98
+ @reified_widget = @widget.versions.last.reify
99
+ end
100
+
101
+ should 'copy the has_many associations when reifying' do
102
+ assert_equal @widget.fluxors.length, @reified_widget.fluxors.length
103
+ assert_same_elements @widget.fluxors, @reified_widget.fluxors
104
+
105
+ assert_equal @widget.versions.length, @reified_widget.versions.length
106
+ assert_same_elements @widget.versions, @reified_widget.versions
107
+ end
108
+ end
109
+
68
110
 
69
111
  context 'and then destroyed' do
70
- setup { @widget.destroy }
112
+ setup do
113
+ @fluxor = @widget.fluxors.create :name => 'flux'
114
+ @widget.destroy
115
+ @reified_widget = @widget.versions.last.reify
116
+ end
117
+
118
+ should 'record the correct event' do
119
+ assert_match /destroy/i, @widget.versions.last.event
120
+ end
71
121
 
72
122
  should 'have three previous versions' do
73
123
  assert_equal 3, @widget.versions.length
74
124
  end
75
125
 
76
126
  should 'be available in its previous version' do
77
- widget = @widget.versions.last.reify
78
- assert_equal @widget.id, widget.id
79
- assert_equal @widget.attributes, widget.attributes
127
+ assert_equal @widget.id, @reified_widget.id
128
+ assert_equal @widget.attributes, @reified_widget.attributes
80
129
  end
81
130
 
82
- should 'record the correct event' do
83
- assert_match /destroy/i, @widget.versions.last.event
131
+ should 'be re-creatable from its previous version' do
132
+ assert @reified_widget.save
133
+ end
134
+
135
+ should 'restore its associations on its previous version' do
136
+ @reified_widget.save
137
+ assert_equal 1, @reified_widget.fluxors.length
84
138
  end
85
139
  end
86
140
  end
@@ -88,7 +142,7 @@ class HasPaperTrailModelTest < Test::Unit::TestCase
88
142
  end
89
143
 
90
144
 
91
- # Test the serialisation and unserialisation.
145
+ # Test the serialisation and deserialisation.
92
146
  # TODO: binary
93
147
  context "A record's papertrail" do
94
148
  setup do
@@ -248,4 +302,69 @@ class HasPaperTrailModelTest < Test::Unit::TestCase
248
302
  end
249
303
  end
250
304
  end
305
+
306
+
307
+ context 'A subclass' do
308
+ setup do
309
+ @foo = FooWidget.create
310
+ @foo.update_attributes :name => 'Fooey'
311
+ end
312
+
313
+ should 'reify with the correct type' do
314
+ thing = @foo.versions.last.reify
315
+ assert_kind_of FooWidget, thing
316
+ end
317
+
318
+
319
+ context 'when destroyed' do
320
+ setup { @foo.destroy }
321
+
322
+ should 'reify with the correct type' do
323
+ thing = @foo.versions.last.reify
324
+ assert_kind_of FooWidget, thing
325
+ end
326
+ end
327
+ end
328
+
329
+
330
+ context 'An item with versions' do
331
+ setup do
332
+ @widget = Widget.create :name => 'Widget'
333
+ @widget.update_attributes :name => 'Fidget'
334
+ @widget.update_attributes :name => 'Digit'
335
+ end
336
+
337
+ context 'on the first version' do
338
+ setup { @version = @widget.versions.first }
339
+
340
+ should 'have a nil previous version' do
341
+ assert_nil @version.previous
342
+ end
343
+
344
+ should 'return the next version' do
345
+ assert_equal @widget.versions[1], @version.next
346
+ end
347
+
348
+ should 'return the correct index' do
349
+ assert_equal 0, @version.index
350
+ end
351
+ end
352
+
353
+ context 'on the last version' do
354
+ setup { @version = @widget.versions.last }
355
+
356
+ should 'return the previous version' do
357
+ assert_equal @widget.versions[@widget.versions.length - 2], @version.previous
358
+ end
359
+
360
+ should 'have a nil next version' do
361
+ assert_nil @version.next
362
+ end
363
+
364
+ should 'return the correct index' do
365
+ assert_equal @widget.versions.length - 1, @version.index
366
+ end
367
+ end
368
+ end
369
+
251
370
  end
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- class PaperTrailTest < ActiveSupport::TestCase
3
+ class PaperTrailSchemaTest < ActiveSupport::TestCase
4
4
  def setup
5
5
  load_schema
6
6
  end
@@ -8,6 +8,7 @@ class PaperTrailTest < ActiveSupport::TestCase
8
8
  def test_schema_has_loaded_correctly
9
9
  assert_equal [], Widget.all
10
10
  assert_equal [], Version.all
11
- assert_equal [], User.all
11
+ assert_equal [], Wotsit.all
12
+ assert_equal [], Fluxor.all
12
13
  end
13
14
  end
data/test/schema.rb CHANGED
@@ -12,11 +12,7 @@ ActiveRecord::Schema.define(:version => 0) do
12
12
  t.boolean :a_boolean
13
13
  t.datetime :created_at, :updated_at
14
14
  t.string :sacrificial_column
15
- end
16
-
17
- create_table :users, :force => true do |t|
18
- t.string :name
19
- t.datetime :created_at, :updated_at
15
+ t.string :type
20
16
  end
21
17
 
22
18
  create_table :versions, :force => true do |t|
@@ -27,5 +23,16 @@ ActiveRecord::Schema.define(:version => 0) do
27
23
  t.text :object
28
24
  t.datetime :created_at
29
25
  end
26
+ add_index :versions, [:item_type, :item_id]
27
+
28
+ create_table :wotsits, :force => true do |t|
29
+ t.integer :widget_id
30
+ t.string :name
31
+ end
32
+
33
+ create_table :fluxors, :force => true do |t|
34
+ t.integer :widget_id
35
+ t.string :name
36
+ end
30
37
 
31
38
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: airblade-paper_trail
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Stewart
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-05-28 00:00:00 -07:00
12
+ date: 2009-06-22 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -22,6 +22,7 @@ extensions: []
22
22
  extra_rdoc_files:
23
23
  - README.md
24
24
  files:
25
+ - .gitignore
25
26
  - MIT-LICENSE
26
27
  - README.md
27
28
  - Rakefile