airblade-paper_trail 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
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