vestal_versions 0.8.3 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/.gitignore +20 -2
  2. data/README.rdoc +110 -8
  3. data/Rakefile +14 -3
  4. data/VERSION +1 -1
  5. data/lib/vestal_versions.rb +93 -143
  6. data/lib/vestal_versions/changes.rb +125 -0
  7. data/lib/vestal_versions/conditions.rb +69 -0
  8. data/lib/vestal_versions/configuration.rb +40 -0
  9. data/lib/vestal_versions/control.rb +175 -0
  10. data/lib/vestal_versions/creation.rb +85 -0
  11. data/lib/vestal_versions/options.rb +42 -0
  12. data/lib/vestal_versions/reload.rb +23 -0
  13. data/lib/vestal_versions/reset.rb +56 -0
  14. data/lib/vestal_versions/reversion.rb +69 -0
  15. data/lib/vestal_versions/tagging.rb +50 -0
  16. data/lib/vestal_versions/users.rb +57 -0
  17. data/lib/vestal_versions/version.rb +32 -0
  18. data/lib/vestal_versions/versioned.rb +30 -0
  19. data/lib/vestal_versions/versions.rb +74 -0
  20. data/rails/init.rb +1 -0
  21. data/rails_generators/vestal_versions/templates/initializer.rb +9 -0
  22. data/{generators/vestal_versions_migration → rails_generators/vestal_versions}/templates/migration.rb +9 -2
  23. data/rails_generators/vestal_versions/vestal_versions_generator.rb +10 -0
  24. data/test/changes_test.rb +154 -13
  25. data/test/conditions_test.rb +137 -0
  26. data/test/configuration_test.rb +39 -0
  27. data/test/control_test.rb +152 -0
  28. data/test/creation_test.rb +70 -30
  29. data/test/options_test.rb +52 -0
  30. data/test/reload_test.rb +19 -0
  31. data/test/reset_test.rb +107 -0
  32. data/test/{revert_test.rb → reversion_test.rb} +8 -22
  33. data/test/schema.rb +4 -1
  34. data/test/tagging_test.rb +38 -0
  35. data/test/test_helper.rb +2 -1
  36. data/test/users_test.rb +25 -0
  37. data/test/version_test.rb +43 -0
  38. data/test/versioned_test.rb +18 -0
  39. data/test/versions_test.rb +172 -0
  40. data/vestal_versions.gemspec +61 -21
  41. metadata +75 -15
  42. data/generators/vestal_versions_migration/vestal_versions_migration_generator.rb +0 -11
  43. data/init.rb +0 -1
  44. data/lib/version.rb +0 -14
  45. data/test/between_test.rb +0 -58
  46. data/test/comparable_test.rb +0 -35
  47. data/test/latest_changes_test.rb +0 -42
@@ -1,4 +1,4 @@
1
- require 'test_helper'
1
+ require File.join(File.dirname(__FILE__), 'test_helper')
2
2
 
3
3
  class CreationTest < Test::Unit::TestCase
4
4
  context 'The number of versions' do
@@ -8,8 +8,8 @@ class CreationTest < Test::Unit::TestCase
8
8
  @count = @user.versions.count
9
9
  end
10
10
 
11
- should 'initially equal one' do
12
- assert_equal 1, @count
11
+ should 'initially equal zero' do
12
+ assert_equal 0, @count
13
13
  end
14
14
 
15
15
  should 'not increase when no changes are made in an update' do
@@ -22,48 +22,88 @@ class CreationTest < Test::Unit::TestCase
22
22
  assert_equal @count, @user.versions.count
23
23
  end
24
24
 
25
- should 'not increase when reverting to the current version' do
26
- @user.revert_to!(@user.version)
27
- assert_equal @count, @user.versions.count
28
- end
29
-
30
25
  context 'after an update' do
31
26
  setup do
32
- @initial_count = @count
33
- @name = 'Steve Jobs'
34
- @user.update_attribute(:name, @name)
35
- @count = @user.versions.count
27
+ @user.update_attribute(:last_name, 'Jobs')
36
28
  end
37
29
 
38
30
  should 'increase by one' do
39
- assert_equal @initial_count + 1, @count
31
+ assert_equal @count + 1, @user.versions.count
40
32
  end
33
+ end
41
34
 
42
- should 'increase by one when reverted' do
43
- @user.revert_to!(:first)
44
- assert_equal @count + 1, @user.versions.count
35
+ context 'after multiple updates' do
36
+ setup do
37
+ @user.update_attribute(:last_name, 'Jobs')
38
+ @user.update_attribute(:last_name, 'Richert')
45
39
  end
46
40
 
47
- should 'not increase until a revert is saved' do
48
- @user.revert_to(:first)
49
- assert_equal @count, @user.versions.count
50
- @user.save
51
- assert_not_equal @count, @user.versions.count
41
+ should 'increase multiple times' do
42
+ assert_operator @count + 1, :<, @user.versions.count
52
43
  end
53
44
  end
45
+ end
54
46
 
55
- context 'after multiple updates' do
47
+ context "A created version's changes" do
48
+ setup do
49
+ @user = User.create(:name => 'Steve Richert')
50
+ @user.update_attribute(:last_name, 'Jobs')
51
+ end
52
+
53
+ should 'not contain Rails timestamps' do
54
+ %w(created_at created_on updated_at updated_on).each do |timestamp|
55
+ assert_does_not_contain @user.versions.last.changes.keys, timestamp
56
+ end
57
+ end
58
+
59
+ context '(with :only options)' do
60
+ setup do
61
+ @only = %w(first_name)
62
+ User.prepare_versioned_options(:only => @only)
63
+ @user.update_attribute(:name, 'Steven Tyler')
64
+ end
65
+
66
+ should 'only contain the specified columns' do
67
+ assert_equal @only, @user.versions.last.changes.keys
68
+ end
69
+
70
+ teardown do
71
+ User.prepare_versioned_options(:only => nil)
72
+ end
73
+ end
74
+
75
+ context '(with :except options)' do
56
76
  setup do
57
- @initial_count = @count
58
- @new_name = 'Steve Jobs'
59
- @user.update_attribute(:name, @new_name)
60
- @user.update_attribute(:name, @name)
61
- @count = @user.versions.count
77
+ @except = %w(first_name)
78
+ User.prepare_versioned_options(:except => @except)
79
+ @user.update_attribute(:name, 'Steven Tyler')
80
+ end
81
+
82
+ should 'not contain the specified columns' do
83
+ @except.each do |column|
84
+ assert_does_not_contain @user.versions.last.changes.keys, column
85
+ end
86
+ end
87
+
88
+ teardown do
89
+ User.prepare_versioned_options(:except => nil)
90
+ end
91
+ end
92
+
93
+ context '(with both :only and :except options)' do
94
+ setup do
95
+ @only = %w(first_name)
96
+ @except = @only
97
+ User.prepare_versioned_options(:only => @only, :except => @except)
98
+ @user.update_attribute(:name, 'Steven Tyler')
99
+ end
100
+
101
+ should 'respect only the :only options' do
102
+ assert_equal @only, @user.versions.last.changes.keys
62
103
  end
63
104
 
64
- should 'not increase when reverting to an identical version' do
65
- @user.revert_to!(:first)
66
- assert_equal @count, @user.versions.count
105
+ teardown do
106
+ User.prepare_versioned_options(:only => nil, :except => nil)
67
107
  end
68
108
  end
69
109
  end
@@ -0,0 +1,52 @@
1
+ require File.join(File.dirname(__FILE__), 'test_helper')
2
+
3
+ class OptionsTest < Test::Unit::TestCase
4
+ context 'Configuration options' do
5
+ setup do
6
+ @options = {:dependent => :destroy}
7
+ @configuration = {:class_name => 'MyCustomVersion'}
8
+
9
+ VestalVersions::Configuration.options.clear
10
+ @configuration.each{|k,v| VestalVersions::Configuration.send("#{k}=", v) }
11
+
12
+ @prepared_options = User.prepare_versioned_options(@options.dup)
13
+ end
14
+
15
+ should 'have symbolized keys' do
16
+ assert User.vestal_versions_options.keys.all?{|k| k.is_a?(Symbol) }
17
+ end
18
+
19
+ should 'combine class-level and global configuration options' do
20
+ combined_keys = (@options.keys + @configuration.keys).map(&:to_sym).uniq
21
+ combined_options = @configuration.symbolize_keys.merge(@options.symbolize_keys)
22
+ assert_equal @prepared_options.slice(*combined_keys), combined_options
23
+ end
24
+
25
+ teardown do
26
+ VestalVersions::Configuration.options.clear
27
+ User.prepare_versioned_options({})
28
+ end
29
+ end
30
+
31
+ context 'Given no options, configuration options' do
32
+ setup do
33
+ @prepared_options = User.prepare_versioned_options({})
34
+ end
35
+
36
+ should 'default to "VestalVersions::Version" for :class_name' do
37
+ assert_equal 'VestalVersions::Version', @prepared_options[:class_name]
38
+ end
39
+
40
+ should 'default to :delete_all for :dependent' do
41
+ assert_equal :delete_all, @prepared_options[:dependent]
42
+ end
43
+
44
+ should 'force the :as option value to :versioned' do
45
+ assert_equal :versioned, @prepared_options[:as]
46
+ end
47
+
48
+ should 'default to [VestalVersions::Versions] for :extend' do
49
+ assert_equal [VestalVersions::Versions], @prepared_options[:extend]
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,19 @@
1
+ require File.join(File.dirname(__FILE__), 'test_helper')
2
+
3
+ class ReloadTest < Test::Unit::TestCase
4
+ context 'Reloading a reverted model' do
5
+ setup do
6
+ @user = User.create(:name => 'Steve Richert')
7
+ first_version = @user.version
8
+ @user.update_attribute(:last_name, 'Jobs')
9
+ @last_version = @user.version
10
+ @user.revert_to(first_version)
11
+ end
12
+
13
+ should 'reset the version number to the most recent version' do
14
+ assert_not_equal @last_version, @user.version
15
+ @user.reload
16
+ assert_equal @last_version, @user.version
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,107 @@
1
+ require File.join(File.dirname(__FILE__), 'test_helper')
2
+
3
+ class ResetTest < Test::Unit::TestCase
4
+ context 'Resetting a model' do
5
+ setup do
6
+ @user, @versions = User.new, []
7
+ @names = ['Steve Richert', 'Stephen Richert', 'Stephen Jobs', 'Steve Jobs']
8
+ @names.each do |name|
9
+ @user.update_attribute(:name, name)
10
+ @versions << @user.version
11
+ end
12
+ end
13
+
14
+ should "properly revert the model's attributes" do
15
+ @versions.reverse.each_with_index do |version, i|
16
+ @user.reset_to!(version)
17
+ assert_equal @names.reverse[i], @user.name
18
+ end
19
+ end
20
+
21
+ should 'dissociate all versions after the target' do
22
+ @versions.reverse.each_with_index do |version, i|
23
+ @user.reset_to!(version)
24
+ assert_equal 0, @user.versions(true).after(version).count
25
+ end
26
+ end
27
+
28
+ context 'with the :dependent option as :delete_all' do
29
+ setup do
30
+ User.prepare_versioned_options(:dependent => :delete_all)
31
+ end
32
+
33
+ should 'delete all versions after the target version' do
34
+ @versions.reverse.each_with_index do |version, i|
35
+ later_versions = @user.versions.after(version)
36
+ @user.reset_to!(version)
37
+ later_versions.each do |later_version|
38
+ assert_raise ActiveRecord::RecordNotFound do
39
+ later_version.reload
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ should 'not destroy all versions after the target version' do
46
+ VestalVersions::Version.any_instance.stubs(:destroy).raises(RuntimeError)
47
+ @versions.reverse.each_with_index do |version, i|
48
+ assert_nothing_raised do
49
+ @user.reset_to!(version)
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ context 'with the :dependent option as :destroy' do
56
+ setup do
57
+ User.prepare_versioned_options(:dependent => :destroy)
58
+ end
59
+
60
+ should 'delete all versions after the target version' do
61
+ @versions.reverse.each_with_index do |version, i|
62
+ later_versions = @user.versions.after(version)
63
+ @user.reset_to!(version)
64
+ later_versions.each do |later_version|
65
+ assert_raise ActiveRecord::RecordNotFound do
66
+ later_version.reload
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ should 'destroy all versions after the target version' do
73
+ VestalVersions::Version.any_instance.stubs(:destroy).raises(RuntimeError)
74
+ @versions.reverse.each_with_index do |version, i|
75
+ later_versions = @user.versions.after(version)
76
+ if later_versions.empty?
77
+ assert_nothing_raised do
78
+ @user.reset_to!(version)
79
+ end
80
+ else
81
+ assert_raise RuntimeError do
82
+ @user.reset_to!(version)
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+
89
+ context 'with the :dependent option as :nullify' do
90
+ setup do
91
+ User.prepare_versioned_options(:dependent => :nullify)
92
+ end
93
+
94
+ should 'leave all versions after the target version' do
95
+ @versions.reverse.each_with_index do |version, i|
96
+ later_versions = @user.versions.after(version)
97
+ @user.reset_to!(version)
98
+ later_versions.each do |later_version|
99
+ assert_nothing_raised do
100
+ later_version.reload
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
@@ -1,6 +1,6 @@
1
- require 'test_helper'
1
+ require File.join(File.dirname(__FILE__), 'test_helper')
2
2
 
3
- class RevertTest < Test::Unit::TestCase
3
+ class ReversionTest < Test::Unit::TestCase
4
4
  context 'A model reversion' do
5
5
  setup do
6
6
  @user, @attributes, @times = User.new, {}, {}
@@ -10,19 +10,13 @@ class RevertTest < Test::Unit::TestCase
10
10
  @user.update_attribute(:name, name)
11
11
  @attributes[@user.version] = @user.attributes
12
12
  time += 1.hour
13
- @user.versions.last.update_attribute(:created_at, time)
13
+ @user.versions.last.try(:update_attribute, :created_at, time)
14
14
  @times[@user.version] = time
15
15
  end
16
16
  @user.reload.versions.reload
17
17
  @first_version, @last_version = @attributes.keys.min, @attributes.keys.max
18
18
  end
19
19
 
20
- should 'do nothing for a non-existent version' do
21
- attributes = @user.attributes
22
- @user.revert_to!(nil)
23
- assert_equal attributes, @user.attributes
24
- end
25
-
26
20
  should 'return the new version number' do
27
21
  new_version = @user.revert_to(@first_version)
28
22
  assert_equal @first_version, new_version
@@ -34,20 +28,12 @@ class RevertTest < Test::Unit::TestCase
34
28
  assert_not_equal current_version, @user.version
35
29
  end
36
30
 
37
- should 'be able to target the first version' do
38
- @user.revert_to(:first)
39
- assert_equal @first_version, @user.version
40
- end
41
-
42
- should 'be able to target the last version' do
43
- @user.revert_to(:last)
44
- assert_equal @last_version, @user.version
45
- end
46
-
47
- should 'do nothing for a non-existent method name' do
31
+ should 'do nothing for a invalid argument' do
48
32
  current_version = @user.version
49
- @user.revert_to(:bogus)
50
- assert_equal current_version, @user.version
33
+ [nil, :bogus, 'bogus', (1..2)].each do |invalid|
34
+ @user.revert_to(invalid)
35
+ assert_equal current_version, @user.version
36
+ end
51
37
  end
52
38
 
53
39
  should 'be able to target a version number' do
@@ -13,9 +13,12 @@ class CreateSchema < ActiveRecord::Migration
13
13
 
14
14
  create_table :versions, :force => true do |t|
15
15
  t.belongs_to :versioned, :polymorphic => true
16
+ t.belongs_to :user, :polymorphic => true
17
+ t.string :user_name
16
18
  t.text :changes
17
19
  t.integer :number
18
- t.datetime :created_at
20
+ t.string :tag
21
+ t.timestamps
19
22
  end
20
23
  end
21
24
  end
@@ -0,0 +1,38 @@
1
+ require File.join(File.dirname(__FILE__), 'test_helper')
2
+
3
+ class TaggingTest < Test::Unit::TestCase
4
+ context 'Tagging a version' do
5
+ setup do
6
+ @user = User.create(:name => 'Steve Richert')
7
+ @user.update_attribute(:last_name, 'Jobs')
8
+ end
9
+
10
+ should "update the version record's tag column" do
11
+ tag_name = 'TAG'
12
+ assert_not_equal tag_name, @user.versions.last.tag
13
+ @user.tag_version(tag_name)
14
+ assert_equal tag_name, @user.versions.last.tag
15
+ end
16
+
17
+ should 'create a version record for an initial version' do
18
+ @user.revert_to(1)
19
+ assert_nil @user.versions.at(1)
20
+ @user.tag_version('TAG')
21
+ assert_not_nil @user.versions.at(1)
22
+ end
23
+ end
24
+
25
+ context 'A tagged version' do
26
+ setup do
27
+ user = User.create(:name => 'Steve Richert')
28
+ user.update_attribute(:last_name, 'Jobs')
29
+ user.tag_version('TAG')
30
+ @version = user.versions.last
31
+ end
32
+
33
+ should 'return true for the "tagged?" method' do
34
+ assert @version.respond_to?(:tagged?)
35
+ assert_equal true, @version.tagged?
36
+ end
37
+ end
38
+ end
@@ -3,8 +3,9 @@ $: << File.dirname(__FILE__)
3
3
 
4
4
  require 'rubygems'
5
5
  require 'test/unit'
6
- require 'activerecord'
6
+ require 'active_record'
7
7
  require 'shoulda'
8
+ require 'mocha'
8
9
  require 'vestal_versions'
9
10
  require 'schema'
10
11
  begin; require 'redgreen'; rescue LoadError; end
@@ -0,0 +1,25 @@
1
+ require 'test_helper'
2
+
3
+ class UsersTest < Test::Unit::TestCase
4
+ context 'The user responsible for an update' do
5
+ setup do
6
+ @updated_by = User.create(:name => 'Steve Jobs')
7
+ @user = User.create(:name => 'Steve Richert')
8
+ end
9
+
10
+ should 'default to nil' do
11
+ @user.update_attributes(:first_name => 'Stephen')
12
+ assert_nil @user.versions.last.user
13
+ end
14
+
15
+ should 'accept and return an ActiveRecord user' do
16
+ @user.update_attributes(:first_name => 'Stephen', :updated_by => @updated_by)
17
+ assert_equal @updated_by, @user.versions.last.user
18
+ end
19
+
20
+ should 'accept and return a string user name' do
21
+ @user.update_attributes(:first_name => 'Stephen', :updated_by => @updated_by.name)
22
+ assert_equal @updated_by.name, @user.versions.last.user
23
+ end
24
+ end
25
+ end