simply_versioned 0.9.3.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.
- data/CHANGES +51 -0
- data/MIT-LICENSE +20 -0
- data/README +140 -0
- data/Rakefile +31 -0
- data/generators/simply_versioned_migration/simply_versioned_migration_generator.rb +11 -0
- data/generators/simply_versioned_migration/templates/migration.rb +18 -0
- data/init.rb +1 -0
- data/install.rb +1 -0
- data/lib/simply_versioned.rb +229 -0
- data/lib/version.rb +47 -0
- data/rdoc/classes/SoftwareHeretics.html +122 -0
- data/rdoc/classes/SoftwareHeretics/ActiveRecord.html +111 -0
- data/rdoc/classes/SoftwareHeretics/ActiveRecord/SimplyVersioned.html +149 -0
- data/rdoc/classes/SoftwareHeretics/ActiveRecord/SimplyVersioned/ClassMethods.html +159 -0
- data/rdoc/classes/SoftwareHeretics/ActiveRecord/SimplyVersioned/InstanceMethods.html +178 -0
- data/rdoc/classes/SoftwareHeretics/ActiveRecord/SimplyVersioned/VersionsProxyMethods.html +286 -0
- data/rdoc/created.rid +1 -0
- data/rdoc/files/README.html +216 -0
- data/rdoc/files/lib/simply_versioned_rb.html +112 -0
- data/rdoc/files/lib/version_rb.html +112 -0
- data/rdoc/fr_class_index.html +32 -0
- data/rdoc/fr_file_index.html +29 -0
- data/rdoc/fr_method_index.html +36 -0
- data/rdoc/index.html +24 -0
- data/rdoc/rdoc-style.css +208 -0
- data/simply_versioned.gemspec +18 -0
- data/tasks/simply_versioned_tasks.rake +4 -0
- data/test/simply_versioned_test.rb +326 -0
- data/test/test_helper.rb +56 -0
- data/uninstall.rb +1 -0
- metadata +117 -0
@@ -0,0 +1,29 @@
|
|
1
|
+
|
2
|
+
<?xml version="1.0" encoding="iso-8859-1"?>
|
3
|
+
<!DOCTYPE html
|
4
|
+
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
5
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
6
|
+
|
7
|
+
<!--
|
8
|
+
|
9
|
+
Files
|
10
|
+
|
11
|
+
-->
|
12
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
13
|
+
<head>
|
14
|
+
<title>Files</title>
|
15
|
+
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
16
|
+
<link rel="stylesheet" href="rdoc-style.css" type="text/css" />
|
17
|
+
<base target="docwin" />
|
18
|
+
</head>
|
19
|
+
<body>
|
20
|
+
<div id="index">
|
21
|
+
<h1 class="section-bar">Files</h1>
|
22
|
+
<div id="index-entries">
|
23
|
+
<a href="files/README.html">README</a><br />
|
24
|
+
<a href="files/lib/simply_versioned_rb.html">lib/simply_versioned.rb</a><br />
|
25
|
+
<a href="files/lib/version_rb.html">lib/version.rb</a><br />
|
26
|
+
</div>
|
27
|
+
</div>
|
28
|
+
</body>
|
29
|
+
</html>
|
@@ -0,0 +1,36 @@
|
|
1
|
+
|
2
|
+
<?xml version="1.0" encoding="iso-8859-1"?>
|
3
|
+
<!DOCTYPE html
|
4
|
+
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
5
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
6
|
+
|
7
|
+
<!--
|
8
|
+
|
9
|
+
Methods
|
10
|
+
|
11
|
+
-->
|
12
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
13
|
+
<head>
|
14
|
+
<title>Methods</title>
|
15
|
+
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
16
|
+
<link rel="stylesheet" href="rdoc-style.css" type="text/css" />
|
17
|
+
<base target="docwin" />
|
18
|
+
</head>
|
19
|
+
<body>
|
20
|
+
<div id="index">
|
21
|
+
<h1 class="section-bar">Methods</h1>
|
22
|
+
<div id="index-entries">
|
23
|
+
<a href="classes/SoftwareHeretics/ActiveRecord/SimplyVersioned/VersionsProxyMethods.html#M000005">clean (SoftwareHeretics::ActiveRecord::SimplyVersioned::VersionsProxyMethods)</a><br />
|
24
|
+
<a href="classes/SoftwareHeretics/ActiveRecord/SimplyVersioned/VersionsProxyMethods.html#M000004">current (SoftwareHeretics::ActiveRecord::SimplyVersioned::VersionsProxyMethods)</a><br />
|
25
|
+
<a href="classes/SoftwareHeretics/ActiveRecord/SimplyVersioned/VersionsProxyMethods.html#M000003">first (SoftwareHeretics::ActiveRecord::SimplyVersioned::VersionsProxyMethods)</a><br />
|
26
|
+
<a href="classes/SoftwareHeretics/ActiveRecord/SimplyVersioned/VersionsProxyMethods.html#M000002">get (SoftwareHeretics::ActiveRecord::SimplyVersioned::VersionsProxyMethods)</a><br />
|
27
|
+
<a href="classes/SoftwareHeretics/ActiveRecord/SimplyVersioned.html#M000001">included (SoftwareHeretics::ActiveRecord::SimplyVersioned)</a><br />
|
28
|
+
<a href="classes/SoftwareHeretics/ActiveRecord/SimplyVersioned/VersionsProxyMethods.html#M000006">next (SoftwareHeretics::ActiveRecord::SimplyVersioned::VersionsProxyMethods)</a><br />
|
29
|
+
<a href="classes/SoftwareHeretics/ActiveRecord/SimplyVersioned/VersionsProxyMethods.html#M000007">prev (SoftwareHeretics::ActiveRecord::SimplyVersioned::VersionsProxyMethods)</a><br />
|
30
|
+
<a href="classes/SoftwareHeretics/ActiveRecord/SimplyVersioned/InstanceMethods.html#M000009">revert_to_version (SoftwareHeretics::ActiveRecord::SimplyVersioned::InstanceMethods)</a><br />
|
31
|
+
<a href="classes/SoftwareHeretics/ActiveRecord/SimplyVersioned/ClassMethods.html#M000008">simply_versioned (SoftwareHeretics::ActiveRecord::SimplyVersioned::ClassMethods)</a><br />
|
32
|
+
<a href="classes/SoftwareHeretics/ActiveRecord/SimplyVersioned/InstanceMethods.html#M000010">simply_versioned_create_version (SoftwareHeretics::ActiveRecord::SimplyVersioned::InstanceMethods)</a><br />
|
33
|
+
</div>
|
34
|
+
</div>
|
35
|
+
</body>
|
36
|
+
</html>
|
data/rdoc/index.html
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
<?xml version="1.0" encoding="iso-8859-1"?>
|
2
|
+
<!DOCTYPE html
|
3
|
+
PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
|
4
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
|
5
|
+
|
6
|
+
<!--
|
7
|
+
|
8
|
+
SimplyVersioned
|
9
|
+
|
10
|
+
-->
|
11
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
12
|
+
<head>
|
13
|
+
<title>SimplyVersioned</title>
|
14
|
+
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
15
|
+
</head>
|
16
|
+
<frameset rows="20%, 80%">
|
17
|
+
<frameset cols="25%,35%,45%">
|
18
|
+
<frame src="fr_file_index.html" title="Files" name="Files" />
|
19
|
+
<frame src="fr_class_index.html" name="Classes" />
|
20
|
+
<frame src="fr_method_index.html" name="Methods" />
|
21
|
+
</frameset>
|
22
|
+
<frame src="files/README.html" name="docwin" />
|
23
|
+
</frameset>
|
24
|
+
</html>
|
data/rdoc/rdoc-style.css
ADDED
@@ -0,0 +1,208 @@
|
|
1
|
+
|
2
|
+
body {
|
3
|
+
font-family: Verdana,Arial,Helvetica,sans-serif;
|
4
|
+
font-size: 90%;
|
5
|
+
margin: 0;
|
6
|
+
margin-left: 40px;
|
7
|
+
padding: 0;
|
8
|
+
background: white;
|
9
|
+
}
|
10
|
+
|
11
|
+
h1,h2,h3,h4 { margin: 0; color: #efefef; background: transparent; }
|
12
|
+
h1 { font-size: 150%; }
|
13
|
+
h2,h3,h4 { margin-top: 1em; }
|
14
|
+
|
15
|
+
a { background: #eef; color: #039; text-decoration: none; }
|
16
|
+
a:hover { background: #039; color: #eef; }
|
17
|
+
|
18
|
+
/* Override the base stylesheet's Anchor inside a table cell */
|
19
|
+
td > a {
|
20
|
+
background: transparent;
|
21
|
+
color: #039;
|
22
|
+
text-decoration: none;
|
23
|
+
}
|
24
|
+
|
25
|
+
/* and inside a section title */
|
26
|
+
.section-title > a {
|
27
|
+
background: transparent;
|
28
|
+
color: #eee;
|
29
|
+
text-decoration: none;
|
30
|
+
}
|
31
|
+
|
32
|
+
/* === Structural elements =================================== */
|
33
|
+
|
34
|
+
div#index {
|
35
|
+
margin: 0;
|
36
|
+
margin-left: -40px;
|
37
|
+
padding: 0;
|
38
|
+
font-size: 90%;
|
39
|
+
}
|
40
|
+
|
41
|
+
|
42
|
+
div#index a {
|
43
|
+
margin-left: 0.7em;
|
44
|
+
}
|
45
|
+
|
46
|
+
div#index .section-bar {
|
47
|
+
margin-left: 0px;
|
48
|
+
padding-left: 0.7em;
|
49
|
+
background: #ccc;
|
50
|
+
font-size: small;
|
51
|
+
}
|
52
|
+
|
53
|
+
|
54
|
+
div#classHeader, div#fileHeader {
|
55
|
+
width: auto;
|
56
|
+
color: white;
|
57
|
+
padding: 0.5em 1.5em 0.5em 1.5em;
|
58
|
+
margin: 0;
|
59
|
+
margin-left: -40px;
|
60
|
+
border-bottom: 3px solid #006;
|
61
|
+
}
|
62
|
+
|
63
|
+
div#classHeader a, div#fileHeader a {
|
64
|
+
background: inherit;
|
65
|
+
color: white;
|
66
|
+
}
|
67
|
+
|
68
|
+
div#classHeader td, div#fileHeader td {
|
69
|
+
background: inherit;
|
70
|
+
color: white;
|
71
|
+
}
|
72
|
+
|
73
|
+
|
74
|
+
div#fileHeader {
|
75
|
+
background: #057;
|
76
|
+
}
|
77
|
+
|
78
|
+
div#classHeader {
|
79
|
+
background: #048;
|
80
|
+
}
|
81
|
+
|
82
|
+
|
83
|
+
.class-name-in-header {
|
84
|
+
font-size: 180%;
|
85
|
+
font-weight: bold;
|
86
|
+
}
|
87
|
+
|
88
|
+
|
89
|
+
div#bodyContent {
|
90
|
+
padding: 0 1.5em 0 1.5em;
|
91
|
+
}
|
92
|
+
|
93
|
+
div#description {
|
94
|
+
padding: 0.5em 1.5em;
|
95
|
+
background: #efefef;
|
96
|
+
border: 1px dotted #999;
|
97
|
+
}
|
98
|
+
|
99
|
+
div#description h1,h2,h3,h4,h5,h6 {
|
100
|
+
color: #125;;
|
101
|
+
background: transparent;
|
102
|
+
}
|
103
|
+
|
104
|
+
div#validator-badges {
|
105
|
+
text-align: center;
|
106
|
+
}
|
107
|
+
div#validator-badges img { border: 0; }
|
108
|
+
|
109
|
+
div#copyright {
|
110
|
+
color: #333;
|
111
|
+
background: #efefef;
|
112
|
+
font: 0.75em sans-serif;
|
113
|
+
margin-top: 5em;
|
114
|
+
margin-bottom: 0;
|
115
|
+
padding: 0.5em 2em;
|
116
|
+
}
|
117
|
+
|
118
|
+
|
119
|
+
/* === Classes =================================== */
|
120
|
+
|
121
|
+
table.header-table {
|
122
|
+
color: white;
|
123
|
+
font-size: small;
|
124
|
+
}
|
125
|
+
|
126
|
+
.type-note {
|
127
|
+
font-size: small;
|
128
|
+
color: #DEDEDE;
|
129
|
+
}
|
130
|
+
|
131
|
+
.xxsection-bar {
|
132
|
+
background: #eee;
|
133
|
+
color: #333;
|
134
|
+
padding: 3px;
|
135
|
+
}
|
136
|
+
|
137
|
+
.section-bar {
|
138
|
+
color: #333;
|
139
|
+
border-bottom: 1px solid #999;
|
140
|
+
margin-left: -20px;
|
141
|
+
}
|
142
|
+
|
143
|
+
|
144
|
+
.section-title {
|
145
|
+
background: #79a;
|
146
|
+
color: #eee;
|
147
|
+
padding: 3px;
|
148
|
+
margin-top: 2em;
|
149
|
+
margin-left: -30px;
|
150
|
+
border: 1px solid #999;
|
151
|
+
}
|
152
|
+
|
153
|
+
.top-aligned-row { vertical-align: top }
|
154
|
+
.bottom-aligned-row { vertical-align: bottom }
|
155
|
+
|
156
|
+
/* --- Context section classes ----------------------- */
|
157
|
+
|
158
|
+
.context-row { }
|
159
|
+
.context-item-name { font-family: monospace; font-weight: bold; color: black; }
|
160
|
+
.context-item-value { font-size: small; color: #448; }
|
161
|
+
.context-item-desc { color: #333; padding-left: 2em; }
|
162
|
+
|
163
|
+
/* --- Method classes -------------------------- */
|
164
|
+
.method-detail {
|
165
|
+
background: #efefef;
|
166
|
+
padding: 0;
|
167
|
+
margin-top: 0.5em;
|
168
|
+
margin-bottom: 1em;
|
169
|
+
border: 1px dotted #ccc;
|
170
|
+
}
|
171
|
+
.method-heading {
|
172
|
+
color: black;
|
173
|
+
background: #ccc;
|
174
|
+
border-bottom: 1px solid #666;
|
175
|
+
padding: 0.2em 0.5em 0 0.5em;
|
176
|
+
}
|
177
|
+
.method-signature { color: black; background: inherit; }
|
178
|
+
.method-name { font-weight: bold; }
|
179
|
+
.method-args { font-style: italic; }
|
180
|
+
.method-description { padding: 0 0.5em 0 0.5em; }
|
181
|
+
|
182
|
+
/* --- Source code sections -------------------- */
|
183
|
+
|
184
|
+
a.source-toggle { font-size: 90%; }
|
185
|
+
div.method-source-code {
|
186
|
+
background: #262626;
|
187
|
+
color: #ffdead;
|
188
|
+
margin: 1em;
|
189
|
+
padding: 0.5em;
|
190
|
+
border: 1px dashed #999;
|
191
|
+
overflow: hidden;
|
192
|
+
}
|
193
|
+
|
194
|
+
div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
195
|
+
|
196
|
+
/* --- Ruby keyword styles --------------------- */
|
197
|
+
|
198
|
+
.standalone-code { background: #221111; color: #ffdead; overflow: hidden; }
|
199
|
+
|
200
|
+
.ruby-constant { color: #7fffd4; background: transparent; }
|
201
|
+
.ruby-keyword { color: #00ffff; background: transparent; }
|
202
|
+
.ruby-ivar { color: #eedd82; background: transparent; }
|
203
|
+
.ruby-operator { color: #00ffee; background: transparent; }
|
204
|
+
.ruby-identifier { color: #ffdead; background: transparent; }
|
205
|
+
.ruby-node { color: #ffa07a; background: transparent; }
|
206
|
+
.ruby-comment { color: #b22222; font-weight: bold; background: transparent; }
|
207
|
+
.ruby-regexp { color: #ffa07a; background: transparent; }
|
208
|
+
.ruby-value { color: #7fffd4; background: transparent; }
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib/', __FILE__)
|
3
|
+
$:.unshift lib unless $:.include?(lib)
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "simply_versioned"
|
7
|
+
s.version = "0.9.3.2"
|
8
|
+
s.date = %q{2010-04-05}
|
9
|
+
s.platform = Gem::Platform::RUBY
|
10
|
+
s.authors = ["Matt Mower", "Jérôme Lipowicz"]
|
11
|
+
s.homepage = "http://github.com/jerome/simply_versioned"
|
12
|
+
s.summary = "SimplyVersioned is a simple, non-invasive, approach to versioning ActiveRecord models."
|
13
|
+
|
14
|
+
s.required_rubygems_version = ">= 1.3.6"
|
15
|
+
|
16
|
+
s.files = Dir.glob("{.,generators,lib,rdoc,tasks,test}/**/*")
|
17
|
+
s.require_path = 'lib'
|
18
|
+
end
|
@@ -0,0 +1,326 @@
|
|
1
|
+
require File.join( File.dirname( __FILE__ ), 'test_helper' )
|
2
|
+
|
3
|
+
require 'mocha'
|
4
|
+
|
5
|
+
class Aardvark < ActiveRecord::Base
|
6
|
+
simply_versioned :keep => 3
|
7
|
+
end
|
8
|
+
|
9
|
+
class Gnu < ActiveRecord::Base
|
10
|
+
simply_versioned :keep => 4
|
11
|
+
end
|
12
|
+
|
13
|
+
class Undine < ActiveRecord::Base
|
14
|
+
end
|
15
|
+
|
16
|
+
class Heffalump < ActiveRecord::Base
|
17
|
+
simply_versioned :automatic => false
|
18
|
+
end
|
19
|
+
|
20
|
+
class Saproling < ActiveRecord::Base
|
21
|
+
simply_versioned :exclude => [:trouble]
|
22
|
+
end
|
23
|
+
|
24
|
+
class SimplyVersionedTest < FixturedTestCase
|
25
|
+
|
26
|
+
def self.suite_setup
|
27
|
+
ActiveRecord::Schema.define do
|
28
|
+
create_table :aardvarks, :force => true do |t|
|
29
|
+
t.string :name
|
30
|
+
t.integer :age
|
31
|
+
end
|
32
|
+
|
33
|
+
create_table :gnus, :force => true do |t|
|
34
|
+
t.string :name
|
35
|
+
t.text :description
|
36
|
+
end
|
37
|
+
|
38
|
+
create_table :undines, :force => true do |t|
|
39
|
+
t.string :name
|
40
|
+
t.integer :married, :default => 0
|
41
|
+
end
|
42
|
+
|
43
|
+
create_table :heffalumps, :force => true do |t|
|
44
|
+
t.string :name
|
45
|
+
end
|
46
|
+
|
47
|
+
create_table :saprolings, :force => true do |t|
|
48
|
+
t.string :name
|
49
|
+
t.string :trouble
|
50
|
+
end
|
51
|
+
|
52
|
+
create_table :versions, :force => true do |t|
|
53
|
+
t.integer :versionable_id
|
54
|
+
t.string :versionable_type
|
55
|
+
t.integer :number
|
56
|
+
t.text :yaml
|
57
|
+
t.datetime :created_at
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.suite_teardown
|
63
|
+
ActiveRecord::Schema.define do
|
64
|
+
drop_table :versions
|
65
|
+
drop_table :saprolings
|
66
|
+
drop_table :heffalumps
|
67
|
+
drop_table :undines
|
68
|
+
drop_table :gnus
|
69
|
+
drop_table :aardvarks
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_should_reject_unknown_options
|
74
|
+
assert_raises SoftwareHeretics::ActiveRecord::SimplyVersioned::BadOptions do
|
75
|
+
cls = Class.new( ActiveRecord::Base ) do
|
76
|
+
simply_versioned :bogus => true
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_should_start_with_empty_versions
|
82
|
+
anthony = Aardvark.new( :name => 'Anthony', :age => 35 )
|
83
|
+
assert anthony.versions.empty?
|
84
|
+
assert anthony.unversioned?
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_should_not_be_versioned
|
88
|
+
anthony = Aardvark.create!( :name => 'Anthony', :age => 35 )
|
89
|
+
assert anthony.unversioned?
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_should_not_be_versioned_when_new_record_is_still_unchanged
|
93
|
+
anthony = Aardvark.create!( :name => 'Anthony', :age => 35 )
|
94
|
+
anthony.save!
|
95
|
+
assert anthony.unversioned?
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_should_be_versioned
|
99
|
+
anthony = Aardvark.create!( :name => 'Anthony', :age => 35 )
|
100
|
+
anthony.age += 1
|
101
|
+
anthony.save!
|
102
|
+
assert anthony.versioned?
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_should_get_versions
|
106
|
+
anthony = Aardvark.create!( :name => 'Anthony', :age => 35 )
|
107
|
+
anthony.age += 1
|
108
|
+
anthony.save!
|
109
|
+
|
110
|
+
assert_equal 35, anthony.versions.get_version(1).model.age
|
111
|
+
assert_equal 35, anthony.versions.get(1).model.age
|
112
|
+
|
113
|
+
assert_equal 36, anthony.versions.get_version(2).model.age
|
114
|
+
assert_equal 36, anthony.versions.get(2).model.age
|
115
|
+
end
|
116
|
+
|
117
|
+
def test_should_not_version_on_create
|
118
|
+
anthony = Aardvark.create!( :name => 'Anthony', :age => 35 )
|
119
|
+
assert_equal 0, anthony.versions.count
|
120
|
+
assert_equal 0, anthony.versions.current_version.number
|
121
|
+
assert_equal 0, anthony.versions.current.number
|
122
|
+
end
|
123
|
+
|
124
|
+
def test_should_version_on_save
|
125
|
+
anthony = Aardvark.create!( :name => 'Anthony', :age => 35 )
|
126
|
+
anthony.age += 1
|
127
|
+
anthony.save!
|
128
|
+
assert_equal 2, anthony.versions.count
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_should_trim_versions
|
132
|
+
anthony = Aardvark.create!( :name => 'Anthony', :age => 35 ) # v1
|
133
|
+
anthony.age += 1
|
134
|
+
anthony.save! #v2
|
135
|
+
|
136
|
+
anthony.age += 1
|
137
|
+
anthony.save! #v3
|
138
|
+
|
139
|
+
anthony.age += 1
|
140
|
+
anthony.save! #v4 !!
|
141
|
+
|
142
|
+
assert_equal 3, anthony.versions.count
|
143
|
+
assert_equal 36, anthony.versions.first_version.model.age
|
144
|
+
assert_equal 36, anthony.versions.first.model.age
|
145
|
+
assert_equal 38, anthony.versions.current_version.model.age
|
146
|
+
assert_equal 38, anthony.versions.current.model.age
|
147
|
+
end
|
148
|
+
|
149
|
+
def test_should_revert
|
150
|
+
anthony = Aardvark.create!( :name => 'Anthony', :age => 35 ) # v1
|
151
|
+
anthony.age += 1
|
152
|
+
anthony.save! #v2
|
153
|
+
|
154
|
+
anthony.revert_to_version( 1 )
|
155
|
+
assert_equal 35, anthony.age
|
156
|
+
end
|
157
|
+
|
158
|
+
def test_should_revert_except
|
159
|
+
anthony = Aardvark.create!( :name => 'Anthony', :age => 35 ) # v1
|
160
|
+
|
161
|
+
anthony.name = "Tony"
|
162
|
+
anthony.age = 45
|
163
|
+
anthony.save! # v2
|
164
|
+
|
165
|
+
anthony.revert_to_version( 1, :except => [:name,:created_at,:updated_at] )
|
166
|
+
assert_equal "Tony", anthony.name
|
167
|
+
assert_equal 35, anthony.age
|
168
|
+
end
|
169
|
+
|
170
|
+
def test_should_raise_on_reversion_to_bad_version
|
171
|
+
anthony = Aardvark.create!( :name => 'Anthony', :age => 35 ) # v1
|
172
|
+
anthony.name = "Tony"
|
173
|
+
anthony.age = 45
|
174
|
+
anthony.save! # v2
|
175
|
+
|
176
|
+
assert_raise RuntimeError do
|
177
|
+
anthony.revert_to_version( -1 )
|
178
|
+
end
|
179
|
+
|
180
|
+
assert_raise RuntimeError do
|
181
|
+
anthony.revert_to_version( "a" )
|
182
|
+
end
|
183
|
+
|
184
|
+
assert_raise RuntimeError do
|
185
|
+
anthony.revert_to_version( nil )
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
def test_should_delete_dependent_versions
|
190
|
+
anthony = Aardvark.create!( :name => 'Anthony', :age => 35 ) # v1
|
191
|
+
anthony.age += 1
|
192
|
+
anthony.save! #v2
|
193
|
+
|
194
|
+
assert_difference( 'Version.count', -2 ) do
|
195
|
+
anthony.destroy
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def test_should_isolate_versioned_models
|
200
|
+
anthony = Aardvark.create!( :name => 'Anthony', :age => 35 )
|
201
|
+
gary = Gnu.create!( :name => 'Gary', :description => 'Gary the GNU' )
|
202
|
+
|
203
|
+
assert_equal 2, Version.count
|
204
|
+
assert_equal 1, anthony.versions.first.number
|
205
|
+
assert_equal 1, gary.versions.first.number
|
206
|
+
end
|
207
|
+
|
208
|
+
def test_should_be_able_to_control_versioning
|
209
|
+
anthony = Aardvark.create!( :name => 'Anthony', :age => 35 ) # v1
|
210
|
+
|
211
|
+
assert_no_difference( 'anthony.versions.count' ) do
|
212
|
+
anthony.age += 1
|
213
|
+
anthony.with_versioning( false, &:save! )
|
214
|
+
end
|
215
|
+
|
216
|
+
assert_difference( 'anthony.versions.count' ) do
|
217
|
+
anthony.age += 1
|
218
|
+
anthony.with_versioning( true, &:save! )
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
def test_should_not_version_in_block
|
223
|
+
anthony = Aardvark.create!( :name => 'Anthony', :age => 35 ) # v1
|
224
|
+
|
225
|
+
assert_no_difference( 'anthony.versions.count' ) do
|
226
|
+
anthony.age += 1
|
227
|
+
anthony.with_versioning( false ) do
|
228
|
+
anthony.save!
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
def test_should_begin_versioning_existing_record
|
234
|
+
ulrica = Undine.create!( :name => 'Ulrica' )
|
235
|
+
|
236
|
+
# Now we begin versioning this kind of record
|
237
|
+
Undine.class_eval do
|
238
|
+
simply_versioned
|
239
|
+
end
|
240
|
+
|
241
|
+
ulrica = Undine.find_by_name( 'Ulrica' )
|
242
|
+
assert ulrica.unversioned?
|
243
|
+
|
244
|
+
ulrica.update_attributes( :married => 1 )
|
245
|
+
assert !ulrica.unversioned?
|
246
|
+
assert_equal 1, ulrica.versions.size
|
247
|
+
assert_equal 1, ulrica.versions.first.model.married
|
248
|
+
end
|
249
|
+
|
250
|
+
def test_should_follow_back_and_forth
|
251
|
+
anthony = Aardvark.create!( :name => 'Anthony', :age => 35 ) # v1
|
252
|
+
anthony.age += 1
|
253
|
+
anthony.save! #v2
|
254
|
+
anthony.age += 1
|
255
|
+
anthony.save!
|
256
|
+
|
257
|
+
assert_equal anthony.versions.current_version, anthony.versions.first_version.next.next
|
258
|
+
assert_equal anthony.versions.first_version, anthony.versions.current_version.previous.previous
|
259
|
+
end
|
260
|
+
|
261
|
+
def test_should_be_trustworthy_collection
|
262
|
+
anthony = Aardvark.create!( :name => 'Anthony', :age => 35 ) # v1
|
263
|
+
anthony.age += 1
|
264
|
+
anthony.save! #v2
|
265
|
+
|
266
|
+
# Now create another record
|
267
|
+
|
268
|
+
alan = Aardvark.create!( :name => 'Alan', :age => 35 )
|
269
|
+
assert_equal 1, alan.versions.size
|
270
|
+
end
|
271
|
+
|
272
|
+
def test_should_not_delete_old_versions_by_default
|
273
|
+
ulrica = Undine.create!( :name => 'Ulrica' )
|
274
|
+
ulrica.versions.expects( :clean_old_versions ).never
|
275
|
+
100.times do
|
276
|
+
ulrica.update_attribute( :married, 1 - ulrica.married )
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
def test_should_not_automatically_create_versions
|
281
|
+
henry = Heffalump.create!( :name => 'Henry' )
|
282
|
+
assert_equal 0, henry.versions.count
|
283
|
+
|
284
|
+
assert_no_difference( 'henry.versions.count' ) do
|
285
|
+
henry.name = 'Harry'
|
286
|
+
henry.save!
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
def test_should_create_versions_on_demand
|
291
|
+
henry = Heffalump.create!( :name => 'Henry' )
|
292
|
+
|
293
|
+
assert_difference( "henry.versions.count", 1 ) do
|
294
|
+
henry.with_versioning( true, &:save )
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
def test_should_exclude_columns
|
299
|
+
assert_equal ["trouble"], Saproling.simply_versioned_excluded_columns
|
300
|
+
|
301
|
+
sylvia = Saproling.create!( :name => 'Sylvia', :trouble => "big" )
|
302
|
+
|
303
|
+
yaml = YAML::load( sylvia.versions.first.yaml )
|
304
|
+
assert_equal Set.new( [ "id", "name" ] ), Set.new( yaml.keys )
|
305
|
+
end
|
306
|
+
|
307
|
+
def test_should_exclude_column_equivalent_syntax
|
308
|
+
klass = Class.new( ActiveRecord::Base )
|
309
|
+
klass.module_eval <<-DEFN
|
310
|
+
simply_versioned :exclude => :some_column
|
311
|
+
DEFN
|
312
|
+
assert_equal ['some_column'], klass.simply_versioned_excluded_columns
|
313
|
+
end
|
314
|
+
|
315
|
+
def test_should_report_version_number
|
316
|
+
anthony = Aardvark.new( :name => 'Anthony', :age => 35 )
|
317
|
+
assert_equal 0, anthony.version_number
|
318
|
+
|
319
|
+
anthony.save!
|
320
|
+
assert_equal 1, anthony.version_number
|
321
|
+
|
322
|
+
anthony.save!
|
323
|
+
assert_equal 2, anthony.version_number # and so on
|
324
|
+
end
|
325
|
+
|
326
|
+
end
|