set_vestal_versions 1.2.2

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 (40) hide show
  1. data/LICENSE +20 -0
  2. data/README.rdoc +196 -0
  3. data/lib/generators/vestal_versions.rb +11 -0
  4. data/lib/generators/vestal_versions/migration/migration_generator.rb +17 -0
  5. data/lib/generators/vestal_versions/migration/templates/initializer.rb +9 -0
  6. data/lib/generators/vestal_versions/migration/templates/migration.rb +28 -0
  7. data/lib/vestal_versions.rb +126 -0
  8. data/lib/vestal_versions/changes.rb +122 -0
  9. data/lib/vestal_versions/conditions.rb +57 -0
  10. data/lib/vestal_versions/control.rb +200 -0
  11. data/lib/vestal_versions/creation.rb +93 -0
  12. data/lib/vestal_versions/deletion.rb +39 -0
  13. data/lib/vestal_versions/options.rb +41 -0
  14. data/lib/vestal_versions/reload.rb +17 -0
  15. data/lib/vestal_versions/reset.rb +24 -0
  16. data/lib/vestal_versions/reversion.rb +82 -0
  17. data/lib/vestal_versions/users.rb +55 -0
  18. data/lib/vestal_versions/version.rb +80 -0
  19. data/lib/vestal_versions/version_num.rb +3 -0
  20. data/lib/vestal_versions/version_tagging.rb +50 -0
  21. data/lib/vestal_versions/versioned.rb +27 -0
  22. data/lib/vestal_versions/versions.rb +74 -0
  23. data/spec/spec_helper.rb +20 -0
  24. data/spec/support/models.rb +19 -0
  25. data/spec/support/schema.rb +25 -0
  26. data/spec/vestal_versions/changes_spec.rb +134 -0
  27. data/spec/vestal_versions/conditions_spec.rb +103 -0
  28. data/spec/vestal_versions/control_spec.rb +120 -0
  29. data/spec/vestal_versions/creation_spec.rb +90 -0
  30. data/spec/vestal_versions/deletion_spec.rb +86 -0
  31. data/spec/vestal_versions/options_spec.rb +45 -0
  32. data/spec/vestal_versions/reload_spec.rb +18 -0
  33. data/spec/vestal_versions/reset_spec.rb +111 -0
  34. data/spec/vestal_versions/reversion_spec.rb +103 -0
  35. data/spec/vestal_versions/users_spec.rb +21 -0
  36. data/spec/vestal_versions/version_spec.rb +61 -0
  37. data/spec/vestal_versions/version_tagging_spec.rb +39 -0
  38. data/spec/vestal_versions/versioned_spec.rb +16 -0
  39. data/spec/vestal_versions/versions_spec.rb +176 -0
  40. metadata +165 -0
@@ -0,0 +1,86 @@
1
+ require 'spec_helper'
2
+
3
+ describe VestalVersions::Deletion do
4
+ let(:name){ 'Steve Richert' }
5
+ subject{ DeletedUser.create(:first_name => 'Steve', :last_name => 'Richert') }
6
+
7
+ context "a deleted version's changes" do
8
+
9
+ before do
10
+ subject.update_attribute(:last_name, 'Jobs')
11
+ end
12
+
13
+ it "removes the original record" do
14
+ subject.destroy
15
+
16
+ DeletedUser.find_by_id(subject.id).should be_nil
17
+ end
18
+
19
+ it "creates another version record" do
20
+ expect{ subject.destroy }.to change{ VestalVersions::Version.count }.by(1)
21
+ end
22
+
23
+ it "creates a version with a tag 'deleted'" do
24
+ subject.destroy
25
+ VestalVersions::Version.last.tag.should == 'deleted'
26
+ end
27
+
28
+ end
29
+
30
+ context "deleted versions" do
31
+ let(:last_version){ VestalVersions::Version.last }
32
+ before do
33
+ subject.update_attribute(:last_name, 'Jobs')
34
+ subject.destroy
35
+ end
36
+
37
+ context "restoring a record with a bang" do
38
+ it "is able to restore the user record" do
39
+ last_version.restore!
40
+
41
+ last_version.versioned.should == subject
42
+ end
43
+
44
+ it "removes the last versioned entry" do
45
+ expect{
46
+ last_version.restore!
47
+ }.to change{ VestalVersions::Version.count }.by(-1)
48
+ end
49
+
50
+ it "works properly even if it's not on the proper version" do
51
+ another_version = VestalVersions::Version.where(
52
+ :versioned_id => last_version.versioned_id,
53
+ :versioned_type => last_version.versioned_type
54
+ ).first
55
+
56
+ another_version.should_not == last_version
57
+
58
+ another_version.restore!.should == subject
59
+ end
60
+
61
+ it "restores even if the schema has changed" do
62
+ new_mods = last_version.modifications.merge(:old_column => 'old')
63
+ last_version.update_attributes(:modifications => new_mods)
64
+
65
+ last_version.restore.should == subject
66
+ end
67
+ end
68
+
69
+ context "restoring a record without a save" do
70
+ it "does not save the DeletedUser when restoring" do
71
+ last_version.restore.should be_new_record
72
+ end
73
+
74
+ it "restores the user object properly" do
75
+ last_version.restore.should == subject
76
+ end
77
+
78
+ it "does not decrement the versions table" do
79
+ expect{
80
+ last_version.restore
81
+ }.to change{ VestalVersions::Version.count }.by(0)
82
+ end
83
+ end
84
+ end
85
+
86
+ end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+
3
+ describe VestalVersions::Options do
4
+ context 'with explicit configuration' do
5
+ let(:options){ {:dependent => :destroy} }
6
+ let(:prepared_options){ User.prepare_versioned_options(options.dup) }
7
+
8
+ before do
9
+ VestalVersions::Version.config.clear
10
+ VestalVersions::Version.config.class_name = 'MyCustomVersion'
11
+ end
12
+
13
+ it 'has symbolized keys' do
14
+ User.vestal_versions_options.keys.all?{|k| k.is_a?(Symbol) }
15
+ end
16
+
17
+ it 'combines class-level and global configuration options' do
18
+ prepared_options.slice(:dependent, :class_name).should == {
19
+ :dependent => :destroy,
20
+ :class_name => 'MyCustomVersion'
21
+ }
22
+ end
23
+
24
+ end
25
+
26
+ context 'default configuration options' do
27
+ subject { User.prepare_versioned_options({}) }
28
+
29
+ it 'defaults to "VestalVersions::Version" for :class_name' do
30
+ subject[:class_name].should == 'VestalVersions::Version'
31
+ end
32
+
33
+ it 'defaults to :delete_all for :dependent' do
34
+ subject[:dependent].should == :delete_all
35
+ end
36
+
37
+ it 'forces the :as option value to :versioned' do
38
+ subject[:as].should == :versioned
39
+ end
40
+
41
+ it 'defaults to [VestalVersions::Versions] for :extend' do
42
+ subject[:extend].should == [VestalVersions::Versions]
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe VestalVersions::Reload do
4
+ let(:user){ User.create(:name => 'Steve Richert') }
5
+
6
+ before do
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
+ it 'resets the version number to the most recent version' do
14
+ user.version.should_not == @last_version
15
+ user.reload
16
+ user.version.should == @last_version
17
+ end
18
+ end
@@ -0,0 +1,111 @@
1
+ require 'spec_helper'
2
+
3
+ describe VestalVersions::Reset do
4
+ let(:names){
5
+ ['Steve Richert', 'Stephen Richert', 'Stephen Jobs', 'Steve Jobs']
6
+ }
7
+
8
+ subject{ User.new }
9
+ let(:versions){ names.map{ |name|
10
+ subject.update_attribute :name, name
11
+ subject.version
12
+ } }
13
+
14
+ before do
15
+ @dependent = User.reflect_on_association(:versions).options[:dependent]
16
+ end
17
+
18
+ after do
19
+ User.reflect_on_association(:versions).options[:dependent] = @dependent
20
+ end
21
+
22
+ it "properly reverts the model's attributes" do
23
+ versions.reverse.each_with_index do |version, i|
24
+ subject.reset_to!(version)
25
+ subject.name.should == names.reverse[i]
26
+ end
27
+ end
28
+
29
+ it 'dissociates all versions after the target' do
30
+ versions.reverse.each do |version|
31
+ subject.reset_to!(version)
32
+ subject.versions(true).after(version).count.should == 0
33
+ end
34
+ end
35
+
36
+ context 'with the :dependent option as :delete_all' do
37
+ before do
38
+ User.reflect_on_association(:versions).options[:dependent] = :delete_all
39
+ end
40
+
41
+ it 'deletes all versions after the target version' do
42
+ versions.reverse.each do |version|
43
+ later_versions = subject.versions.after(version)
44
+ subject.reset_to!(version)
45
+
46
+ later_versions.each do |later_version|
47
+ expect{
48
+ later_version.reload
49
+ }.to raise_error(ActiveRecord::RecordNotFound)
50
+ end
51
+ end
52
+ end
53
+
54
+ it 'does not destroy all versions after the target version' do
55
+ expect {
56
+ versions.reverse.each do |version|
57
+ subject.reset_to! version
58
+ end
59
+ }.to_not change{ VestalVersions::Version.count }
60
+ end
61
+ end
62
+
63
+ context 'with the :dependent option as :destroy' do
64
+ before do
65
+ User.reflect_on_association(:versions).options[:dependent] = :destroy
66
+ end
67
+
68
+ it 'deletes all versions after the target version' do
69
+ versions.reverse.each do |version|
70
+ later_versions = subject.versions.after(version)
71
+ subject.reset_to!(version)
72
+
73
+ later_versions.each do |later_version|
74
+ expect{
75
+ later_version.reload
76
+ }.to raise_error(ActiveRecord::RecordNotFound)
77
+ end
78
+ end
79
+ end
80
+
81
+ it 'destroys all versions after the target version' do
82
+ expect {
83
+ versions.reverse.each do |version|
84
+ later_versions = subject.versions.after(version)
85
+
86
+ subject.reset_to!(version)
87
+ end
88
+ }.to change{ VestalVersions::Version.count }.by(-versions.size + 1)
89
+ end
90
+ end
91
+
92
+ context 'with the :dependent option as :nullify' do
93
+ before do
94
+ User.reflect_on_association(:versions).options[:dependent] = :nullify
95
+ end
96
+
97
+ it 'leaves all versions after the target version' do
98
+ versions.reverse.each do |version|
99
+ later_versions = subject.versions.after(version)
100
+ subject.reset_to!(version)
101
+
102
+ later_versions.each do |later_version|
103
+ expect{
104
+ later_version.reload
105
+ }.to_not raise_error
106
+ end
107
+ end
108
+ end
109
+ end
110
+
111
+ end
@@ -0,0 +1,103 @@
1
+ require 'spec_helper'
2
+
3
+ describe VestalVersions::Reversion do
4
+ subject{ User.new }
5
+ let(:attributes){ {} }
6
+ let(:first_version){ attributes.keys.min }
7
+ let(:last_version){ attributes.keys.max }
8
+ let(:times){ {} }
9
+ let(:names){
10
+ ['Steve Richert', 'Stephen Richert', 'Stephen Jobs', 'Steve Jobs']
11
+ }
12
+
13
+ before do
14
+ time = names.size.hours.ago
15
+
16
+ names.each do |name|
17
+ subject.update_attribute(:name, name)
18
+ attributes[subject.version] = subject.attributes
19
+ time += 1.hour
20
+
21
+ subject.versions.last.try(:update_attribute, :created_at, time)
22
+
23
+ times[subject.version] = time
24
+ end
25
+ end
26
+
27
+ it 'returns the new version number' do
28
+ subject.revert_to(first_version).should == first_version
29
+ end
30
+
31
+ it 'changes the version number when saved' do
32
+ expect{ subject.revert_to! first_version }.to change{ subject.version }
33
+ end
34
+
35
+ it 'does nothing for a invalid argument' do
36
+ [nil, :bogus, 'bogus', (1..2)].each do |invalid|
37
+ expect{ subject.revert_to(invalid) }.to_not change{ subject.version }
38
+ end
39
+ end
40
+
41
+ it 'is able to target a version number' do
42
+ subject.revert_to(1)
43
+ subject.version.should == 1
44
+ end
45
+
46
+ it 'is able to target a date and time' do
47
+ times.each do |version, time|
48
+ subject.revert_to(time + 1.second)
49
+ subject.version.should == version
50
+ end
51
+ end
52
+
53
+ it 'is able to target a version object' do
54
+ subject.versions.each do |version|
55
+ subject.revert_to(version)
56
+ subject.version.should == version.number
57
+ end
58
+ end
59
+
60
+ it "correctly rolls back the model's attributes" do
61
+ except = %w(created_at created_on updated_at updated_on)
62
+
63
+ attributes.each do |version, attributes|
64
+ subject.revert_to!(version)
65
+ subject.attributes.except(*except).should == attributes.except(*except)
66
+ end
67
+ end
68
+
69
+ it "stores the reverted_from pointing to the previous version" do
70
+ subject.revert_to!(1)
71
+ subject.versions.last.reverted_from.should == 1
72
+ end
73
+
74
+ it "does not store the reverted_from for subsequent saves" do
75
+ subject.revert_to!(1)
76
+ subject.update_attributes(:name => 'Bill Gates')
77
+ subject.versions.last.reverted_from.should be_nil
78
+ end
79
+
80
+ it "stores the reverted_from pointing to the version it was reverted from when save is called later" do
81
+ subject.revert_to(1)
82
+ subject.name = "Reverted"
83
+ subject.save
84
+ subject.versions.last.reverted_from.should == 1
85
+ end
86
+
87
+ it "does not store the reverted_from for subsequent saves when the revert_to-save is called later" do
88
+ subject.revert_to(1)
89
+ subject.name = "Reverted"
90
+ subject.save
91
+ subject.update_attributes(:name => 'Bill Gates')
92
+ subject.versions.last.reverted_from.should be_nil
93
+ end
94
+
95
+ it "clears the reverted_from if the model is reloaded after a revert_to without a save" do
96
+ subject.revert_to(1)
97
+ subject.reload
98
+ subject.update_attributes(:name => 'Bill Gates')
99
+
100
+ subject.versions.last.reverted_from.should be_nil
101
+ end
102
+
103
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe VestalVersions::Users do
4
+ let(:updated_by){ User.create(:name => 'Steve Jobs') }
5
+ let(:user){ User.create(:name => 'Steve Richert') }
6
+
7
+ it 'defaults to nil' do
8
+ user.update_attributes(:first_name => 'Stephen')
9
+ user.versions.last.user.should be_nil
10
+ end
11
+
12
+ it 'accepts and returns an ActiveRecord user' do
13
+ user.update_attributes(:first_name => 'Stephen', :updated_by => updated_by)
14
+ user.versions.last.user.should == updated_by
15
+ end
16
+
17
+ it 'accepts and returns a string user name' do
18
+ user.update_attributes(:first_name => 'Stephen', :updated_by => updated_by.name)
19
+ user.versions.last.user.should == updated_by.name
20
+ end
21
+ end
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+
3
+ describe VestalVersions::Versions do
4
+ let(:user){ User.create(:name => 'Stephen Richert') }
5
+
6
+ before do
7
+ user.update_attribute(:name, 'Steve Jobs')
8
+ user.update_attribute(:last_name, 'Richert')
9
+ @first_version, @last_version = user.versions.first, user.versions.last
10
+ end
11
+
12
+ it 'is comparable to another version based on version number' do
13
+ @first_version.should == @first_version
14
+ @last_version.should == @last_version
15
+ @first_version.should_not == @last_version
16
+ @last_version.should_not == @first_version
17
+ @first_version.should < @last_version
18
+ @last_version.should > @first_version
19
+ @first_version.should <= @last_version
20
+ @last_version.should >= @first_version
21
+ end
22
+
23
+ it "is not equal a separate model's version with the same number" do
24
+ other = User.create(:name => 'Stephen Richert')
25
+ other.update_attribute(:name, 'Steve Jobs')
26
+ other.update_attribute(:last_name, 'Richert')
27
+ first_version, last_version = other.versions.first, other.versions.last
28
+
29
+ @first_version.should_not == first_version
30
+ @last_version.should_not == last_version
31
+ end
32
+
33
+ it 'defaults to ordering by number when finding through association' do
34
+ numbers = user.versions.map(&:number)
35
+ numbers.sort.should == numbers
36
+ end
37
+
38
+ it 'returns true for the "initial?" method when the version number is 1' do
39
+ version = user.versions.build(:number => 1)
40
+ version.number.should == 1
41
+ version.should be_initial
42
+ end
43
+
44
+ it "sreturn the version number if it is not a revert" do
45
+ user.version.should == user.versions.last.original_number
46
+ end
47
+
48
+ it "return the reverted_version if it is a revert" do
49
+ user.revert_to!(1)
50
+ user.versions.last.original_number.should == 1
51
+ end
52
+
53
+ it "return the original version if it is a double revert" do
54
+ user.revert_to!(2)
55
+ version = user.version
56
+ user.update_attributes(:last_name => 'Gates')
57
+ user.revert_to!(version)
58
+ user.versions.last.original_number.should == 2
59
+ end
60
+
61
+ end