vestal_versions 0.8.3 → 1.0.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.
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