rtiss_acts_as_versioned 0.6.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/CHANGELOG +84 -0
- data/Gemfile +7 -0
- data/MIT-LICENSE +20 -0
- data/README +24 -0
- data/RUNNING_UNIT_TESTS +41 -0
- data/Rakefile +145 -0
- data/init.rb +2 -0
- data/lib/rtiss_acts_as_versioned.rb +625 -0
- data/rtiss_acts_as_versioned.gemspec +96 -0
- data/test/abstract_unit.rb +49 -0
- data/test/database.yml +18 -0
- data/test/fixtures/authors.yml +6 -0
- data/test/fixtures/landmark.rb +3 -0
- data/test/fixtures/landmark_h.yml +7 -0
- data/test/fixtures/landmarks.yml +7 -0
- data/test/fixtures/locked_pages.yml +10 -0
- data/test/fixtures/locked_pages_revisions.yml +27 -0
- data/test/fixtures/locked_rolle.rb +8 -0
- data/test/fixtures/migrations/1_add_versioned_tables.rb +15 -0
- data/test/fixtures/page.rb +43 -0
- data/test/fixtures/pages.yml +8 -0
- data/test/fixtures/pages_h.yml +18 -0
- data/test/fixtures/rolle.rb +7 -0
- data/test/fixtures/widget.rb +6 -0
- data/test/migration_test.rb +46 -0
- data/test/schema.rb +154 -0
- data/test/tiss_test.rb +331 -0
- data/test/versioned_test.rb +384 -0
- metadata +118 -0
data/test/tiss_test.rb
ADDED
@@ -0,0 +1,331 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), 'fixtures/rolle')
|
4
|
+
require File.join(File.dirname(__FILE__), 'fixtures/locked_rolle')
|
5
|
+
|
6
|
+
class TissTest < ActiveSupport::TestCase
|
7
|
+
def test_versioning
|
8
|
+
anzahl = Rolle.count
|
9
|
+
|
10
|
+
oid1 = create_object('test').id
|
11
|
+
oid2 = create_object('tuwien').id
|
12
|
+
oid3 = create_object('ruby').id
|
13
|
+
oid4 = create_object('rails').id
|
14
|
+
oid5 = create_object('times').id
|
15
|
+
|
16
|
+
assert_equal anzahl+5, Rolle.count
|
17
|
+
|
18
|
+
2.upto(5) {|index| edit_object(oid1, "test" + index.to_s)}
|
19
|
+
2.upto(7) {|index| edit_object(oid2, "tuwien" + index.to_s)}
|
20
|
+
2.upto(9) {|index| edit_object(oid3, "ruby" + index.to_s)}
|
21
|
+
2.upto(6) {|index| edit_object(oid4, "rails" + index.to_s)}
|
22
|
+
2.upto(3) {|index| edit_object_with_sleep(oid5, "times" + index.to_s)}
|
23
|
+
|
24
|
+
assert versions_correct?(oid1, 5)
|
25
|
+
assert versions_correct?(oid2, 7)
|
26
|
+
assert versions_correct?(oid3, 9)
|
27
|
+
assert versions_correct?(oid4, 6)
|
28
|
+
|
29
|
+
assert timestamps?(oid1)
|
30
|
+
assert timestamps?(oid2)
|
31
|
+
assert timestamps?(oid3)
|
32
|
+
assert timestamps?(oid4)
|
33
|
+
assert strong_timestamps?(oid5)
|
34
|
+
|
35
|
+
destroy_record(oid2)
|
36
|
+
assert record_unavailable_in_original_table?(oid2)
|
37
|
+
assert deleted_record_versioned?(oid2, 8)
|
38
|
+
|
39
|
+
restore_record(oid2)
|
40
|
+
assert restored_record_available_in_original_table?(oid2)
|
41
|
+
assert restored_record_versioned?(oid2, 9)
|
42
|
+
|
43
|
+
assert save_record_without_changes(oid1)
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_deleted_in_original_table
|
47
|
+
record = create_object('test deleted_in_orginal_table')
|
48
|
+
version_record = record.versions.find(:first)
|
49
|
+
assert version_record != nil
|
50
|
+
|
51
|
+
assert !version_record.deleted_in_original_table
|
52
|
+
record.destroy
|
53
|
+
|
54
|
+
version_record = record.find_newest_version
|
55
|
+
assert version_record != nil
|
56
|
+
assert version_record.version == 2
|
57
|
+
assert version_record.deleted_in_original_table
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_find_versions
|
61
|
+
o = create_object("karin")
|
62
|
+
v = o.find_versions(:all)
|
63
|
+
assert_equal 1, v.count
|
64
|
+
assert_equal v[0].name, "karin"
|
65
|
+
|
66
|
+
edit_object(o.id, "zak")
|
67
|
+
v = o.find_versions(:all)
|
68
|
+
assert_equal 2, v.count
|
69
|
+
assert_equal v[0].name, "karin"
|
70
|
+
assert_equal v[1].name, "zak"
|
71
|
+
|
72
|
+
v = o.find_versions(:all, :conditions => "name = 'zak'")
|
73
|
+
assert_equal 1, v.count
|
74
|
+
assert_equal v[0].name, "zak"
|
75
|
+
|
76
|
+
# v = o.find_versions(:all, :conditions => ["name = 'zak'"])
|
77
|
+
# assert_equal 1, v.count
|
78
|
+
# assert_equal v[0].name, "zak"
|
79
|
+
|
80
|
+
v = o.find_versions(:first)
|
81
|
+
assert_equal v.name, "karin"
|
82
|
+
|
83
|
+
v = o.find_versions(:last)
|
84
|
+
assert_equal v.name, "zak"
|
85
|
+
|
86
|
+
v = o.find_versions(:all, :order => "name desc")
|
87
|
+
assert_equal 2, v.count
|
88
|
+
assert_equal v[0].name, "zak"
|
89
|
+
assert_equal v[1].name, "karin"
|
90
|
+
# mind the missing s
|
91
|
+
|
92
|
+
v = o.find_version(1)
|
93
|
+
assert_equal v.name, "karin"
|
94
|
+
|
95
|
+
v = o.find_version(2)
|
96
|
+
assert_equal v.name, "zak"
|
97
|
+
|
98
|
+
assert_raises(RuntimeError) { o.find_version(3) }
|
99
|
+
|
100
|
+
v = o.find_newest_version
|
101
|
+
assert_equal v.name, "zak"
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_restore
|
105
|
+
o = create_object("lebt")
|
106
|
+
oid = o.id
|
107
|
+
v = o.find_version(1)
|
108
|
+
assert v!=nil
|
109
|
+
|
110
|
+
assert_raises(RuntimeError) { v.restore }
|
111
|
+
assert !v.deleted_in_original_table
|
112
|
+
assert !v.record_restored, "Record_restored shows that the record was undeleted (should be false) for a newly created record"
|
113
|
+
|
114
|
+
o.destroy
|
115
|
+
v = o.find_newest_version
|
116
|
+
assert v.deleted_in_original_table
|
117
|
+
|
118
|
+
v.restore
|
119
|
+
assert !v.record_restored, "Record_restored shows that the record was undeleted (should be false) for the restored version record (but should be in the newly created record)"
|
120
|
+
o = Rolle.find oid
|
121
|
+
assert v.version == o.version, "Version field not restored correctly"
|
122
|
+
|
123
|
+
v = o.find_newest_version
|
124
|
+
assert !v.deleted_in_original_table, "Deleted_in_original_table doesn't show that the record was undeleted (should be false)"
|
125
|
+
assert v.record_restored, "Record_restored doesn't show that the record was undeleted (should be true) for the version record created upon restore"
|
126
|
+
end
|
127
|
+
|
128
|
+
def test_original_record_exists
|
129
|
+
o = create_object("lebt")
|
130
|
+
oid = o.id
|
131
|
+
v = o.find_version(1)
|
132
|
+
assert v!=nil
|
133
|
+
assert v.original_record_exists?
|
134
|
+
|
135
|
+
o.destroy
|
136
|
+
assert !v.original_record_exists?
|
137
|
+
|
138
|
+
v.restore
|
139
|
+
assert v.original_record_exists?
|
140
|
+
end
|
141
|
+
|
142
|
+
def test_restore_deleted
|
143
|
+
o = create_object("lebt")
|
144
|
+
oid = o.id
|
145
|
+
v = o.find_version(1)
|
146
|
+
assert v!=nil
|
147
|
+
|
148
|
+
assert_raises(RuntimeError) { restore_record(oid) }
|
149
|
+
assert !v.deleted_in_original_table
|
150
|
+
|
151
|
+
o.destroy
|
152
|
+
v = o.find_version(2)
|
153
|
+
assert v!=nil
|
154
|
+
assert v.deleted_in_original_table
|
155
|
+
|
156
|
+
restore_record(oid)
|
157
|
+
v = o.find_version(3)
|
158
|
+
assert v!=nil
|
159
|
+
assert !v.deleted_in_original_table
|
160
|
+
end
|
161
|
+
|
162
|
+
def test_restore_deleted_version
|
163
|
+
o = create_object("lebt")
|
164
|
+
oid = o.id
|
165
|
+
v = o.find_version(1)
|
166
|
+
assert v!=nil
|
167
|
+
|
168
|
+
edit_object(oid, "nicht")
|
169
|
+
x = Rolle.find(oid)
|
170
|
+
assert x.name == "nicht"
|
171
|
+
|
172
|
+
v = o.find_version(2)
|
173
|
+
assert v!=nil
|
174
|
+
o.destroy
|
175
|
+
|
176
|
+
v = o.find_version(3)
|
177
|
+
assert v!=nil
|
178
|
+
assert v.deleted_in_original_table
|
179
|
+
|
180
|
+
Rolle.restore_deleted_version(oid, 1)
|
181
|
+
x = Rolle.find(oid)
|
182
|
+
assert x.name == "lebt"
|
183
|
+
end
|
184
|
+
|
185
|
+
def test_destroy_unsaved_record
|
186
|
+
o = Rolle.new(:name => "Nicht Speichern")
|
187
|
+
assert_nothing_raised do o.destroy end
|
188
|
+
assert_equal o.highest_version, -1
|
189
|
+
end
|
190
|
+
|
191
|
+
def test_versions_after_save
|
192
|
+
r = Rolle.new(:name => 'karin')
|
193
|
+
assert r.save
|
194
|
+
r.name = 'zak'
|
195
|
+
assert r.save
|
196
|
+
assert_equal 2, r.versions.size
|
197
|
+
assert_equal 2, r.versions.count
|
198
|
+
end
|
199
|
+
|
200
|
+
def test_restore_without_validations
|
201
|
+
r = Rolle.new(:name => 'karin')
|
202
|
+
assert r.save
|
203
|
+
version = r.find_newest_version
|
204
|
+
r.destroy
|
205
|
+
|
206
|
+
r = Rolle.new(:name => 'karin')
|
207
|
+
assert r.save
|
208
|
+
|
209
|
+
assert_raises RuntimeError do version.restore end
|
210
|
+
assert_nothing_raised do version.restore(perform_validations = false) end
|
211
|
+
end
|
212
|
+
|
213
|
+
def test_save_without_revision
|
214
|
+
r = Rolle.new(:name => 'karin')
|
215
|
+
assert_equal true, r.save_without_revision
|
216
|
+
|
217
|
+
r = Rolle.new(:name => 'karin')
|
218
|
+
assert_equal false, r.save_without_revision
|
219
|
+
end
|
220
|
+
|
221
|
+
=begin
|
222
|
+
# Wait until experimenting-with-optimistic-locking is merged.
|
223
|
+
def test_locked_rolle
|
224
|
+
r = LockedRolle.new(:name => 'karin')
|
225
|
+
r.save
|
226
|
+
assert_equal 1, r.find_newest_version.version
|
227
|
+
r.name = 'zak'
|
228
|
+
r.save
|
229
|
+
assert_equal 2, r.find_newest_version.version
|
230
|
+
end
|
231
|
+
=end
|
232
|
+
|
233
|
+
private
|
234
|
+
def create_object(bezeichnung)
|
235
|
+
o = Rolle.new(:name => bezeichnung)
|
236
|
+
o.save
|
237
|
+
return o
|
238
|
+
end
|
239
|
+
|
240
|
+
def edit_object(id, bezeichnung)
|
241
|
+
Rolle.find(id).update_attributes(:name=>bezeichnung)
|
242
|
+
end
|
243
|
+
|
244
|
+
def edit_object_with_sleep(id, bezeichnung)
|
245
|
+
sleep(2)
|
246
|
+
Rolle.find(id).update_attributes(:name=>bezeichnung)
|
247
|
+
end
|
248
|
+
|
249
|
+
def versions_correct?(id, highest_version)
|
250
|
+
result = Rolle.find(id).versions.find(:all).size == highest_version
|
251
|
+
1.upto(highest_version) do |current_version|
|
252
|
+
current_version_record = Rolle.find(id).versions.find(:first, :conditions => "version = #{current_version}")
|
253
|
+
result = false if current_version_record.nil? || current_version_record.deleted_in_original_table == true
|
254
|
+
end
|
255
|
+
return result
|
256
|
+
end
|
257
|
+
|
258
|
+
def timestamps?(id)
|
259
|
+
result = true;
|
260
|
+
highest_version = Rolle.find(id).versions.find(:all).size
|
261
|
+
highest_version.downto(1) do |current_version|
|
262
|
+
if current_version >= 2
|
263
|
+
rolle_current_version = Rolle.find(id).versions.find(:first, :conditions => "version = #{current_version}")
|
264
|
+
rolle_predecessor_version = Rolle.find(id).versions.find(:first, :conditions => "version = #{current_version-1}")
|
265
|
+
toleranz = rolle_current_version.created_at - rolle_predecessor_version.updated_at
|
266
|
+
result = false if toleranz > 1.0
|
267
|
+
end
|
268
|
+
end
|
269
|
+
return result
|
270
|
+
end
|
271
|
+
|
272
|
+
def strong_timestamps?(id)
|
273
|
+
result = true;
|
274
|
+
highest_version = Rolle.find(id).versions.find(:all).size
|
275
|
+
highest_version.downto(2) do |current_version|
|
276
|
+
rolle_current_version = Rolle.find(id).versions.find(:first, :conditions => "version = #{current_version}")
|
277
|
+
rolle_predecessor_version = Rolle.find(id).versions.find(:first, :conditions => "version = #{current_version-1}")
|
278
|
+
result = false unless rolle_current_version.created_at = rolle_predecessor_version.updated_at
|
279
|
+
result = false unless rolle_current_version.created_at >= rolle_predecessor_version.created_at
|
280
|
+
end
|
281
|
+
return result
|
282
|
+
end
|
283
|
+
|
284
|
+
def destroy_record(id)
|
285
|
+
# Rolle.destroy(id)
|
286
|
+
Rolle.destroy(id)
|
287
|
+
end
|
288
|
+
|
289
|
+
def record_unavailable_in_original_table?(id)
|
290
|
+
begin
|
291
|
+
Rolle.find(id)
|
292
|
+
return false
|
293
|
+
rescue
|
294
|
+
return true
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
def deleted_record_versioned?(id, highest_version)
|
299
|
+
version_of_deleted_record = highest_version
|
300
|
+
rolle_deleted = Rolle::Version.find(:first, :conditions => "version = #{version_of_deleted_record} and rolle_id = #{id}")
|
301
|
+
return rolle_deleted != nil && rolle_deleted.deleted_in_original_table == true
|
302
|
+
end
|
303
|
+
|
304
|
+
def restore_record(id)
|
305
|
+
Rolle.restore_deleted(id)
|
306
|
+
end
|
307
|
+
|
308
|
+
def restored_record_available_in_original_table?(id)
|
309
|
+
begin
|
310
|
+
Rolle.find(id)
|
311
|
+
return true
|
312
|
+
rescue
|
313
|
+
return false
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
def restored_record_versioned?(id, highest_version)
|
318
|
+
version_of_restored_record = highest_version
|
319
|
+
rolle_restored = Rolle.find(id).versions.find(:first, :conditions => "version = #{version_of_restored_record}")
|
320
|
+
return rolle_restored != nil && rolle_restored.deleted_in_original_table == false
|
321
|
+
end
|
322
|
+
|
323
|
+
def save_record_without_changes(id)
|
324
|
+
versions_before_save = Rolle.find(id).versions.find(:all).size
|
325
|
+
rolle = Rolle.find(id)
|
326
|
+
rolle.update_attributes(:name=>rolle.name)
|
327
|
+
versions_after_save = Rolle.find(id).versions.find(:all).size
|
328
|
+
return versions_before_save == versions_after_save
|
329
|
+
end
|
330
|
+
|
331
|
+
end
|
@@ -0,0 +1,384 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'abstract_unit')
|
2
|
+
require File.join(File.dirname(__FILE__), 'fixtures/page')
|
3
|
+
require File.join(File.dirname(__FILE__), 'fixtures/widget')
|
4
|
+
|
5
|
+
class VersionedTest < ActiveSupport::TestCase
|
6
|
+
fixtures :pages, :pages_h, :locked_pages, :locked_pages_revisions, :authors, :landmarks, :landmark_h
|
7
|
+
set_fixture_class :pages_h => Page::Version
|
8
|
+
|
9
|
+
def test_saves_versioned_copy
|
10
|
+
p = Page.create! :title => 'first title', :body => 'first body'
|
11
|
+
assert !p.new_record?
|
12
|
+
assert_equal 1, p.versions.size
|
13
|
+
assert_equal 1, p.version
|
14
|
+
assert_instance_of Page.versioned_class, p.versions.first
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_saves_without_revision
|
18
|
+
p = pages(:welcome)
|
19
|
+
old_versions = p.versions.count
|
20
|
+
|
21
|
+
p.save_without_revision
|
22
|
+
|
23
|
+
p.without_revision do
|
24
|
+
p.update_attributes :title => 'changed'
|
25
|
+
end
|
26
|
+
|
27
|
+
assert_equal old_versions, p.versions.count
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_rollback_with_version_number
|
31
|
+
p = pages(:welcome)
|
32
|
+
assert_equal 24, p.version
|
33
|
+
assert_equal 'Welcome to the weblog', p.title
|
34
|
+
|
35
|
+
assert p.revert_to!(23), "Couldn't revert to 23"
|
36
|
+
assert_equal 23, p.version
|
37
|
+
assert_equal 'Welcome to the weblg', p.title
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_versioned_class_name
|
41
|
+
assert_equal 'Version', Page.versioned_class_name
|
42
|
+
assert_equal 'LockedPageRevision', LockedPage.versioned_class_name
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_versioned_class
|
46
|
+
assert_equal Page::Version, Page.versioned_class
|
47
|
+
assert_equal LockedPage::LockedPageRevision, LockedPage.versioned_class
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_special_methods
|
51
|
+
assert_nothing_raised { pages(:welcome).feeling_good? }
|
52
|
+
assert_nothing_raised { pages(:welcome).versions.first.feeling_good? }
|
53
|
+
assert_nothing_raised { locked_pages(:welcome).hello_world }
|
54
|
+
assert_nothing_raised { locked_pages(:welcome).versions.first.hello_world }
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_rollback_with_version_class
|
58
|
+
p = pages(:welcome)
|
59
|
+
assert_equal 24, p.version
|
60
|
+
assert_equal 'Welcome to the weblog', p.title
|
61
|
+
|
62
|
+
assert p.revert_to!(p.versions.find_by_version(23)), "Couldn't revert to 23"
|
63
|
+
assert_equal 23, p.version
|
64
|
+
assert_equal 'Welcome to the weblg', p.title
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_rollback_fails_with_invalid_revision
|
68
|
+
p = locked_pages(:welcome)
|
69
|
+
assert !p.revert_to!(locked_pages(:thinking))
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_saves_versioned_copy_with_options
|
73
|
+
p = LockedPage.create! :title => 'first title'
|
74
|
+
assert !p.new_record?
|
75
|
+
assert_equal 1, p.versions.size
|
76
|
+
assert_instance_of LockedPage.versioned_class, p.versions.first
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_rollback_with_version_number_with_options
|
80
|
+
p = locked_pages(:welcome)
|
81
|
+
assert_equal 'Welcome to the weblog', p.title
|
82
|
+
assert_equal 'LockedPage', p.versions.first.version_type
|
83
|
+
|
84
|
+
assert p.revert_to!(p.versions.first.lock_version), "Couldn't revert to 23"
|
85
|
+
assert_equal 'Welcome to the weblg', p.title
|
86
|
+
assert_equal 'LockedPage', p.versions.first.version_type
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_rollback_with_version_class_with_options
|
90
|
+
p = locked_pages(:welcome)
|
91
|
+
assert_equal 'Welcome to the weblog', p.title
|
92
|
+
assert_equal 'LockedPage', p.versions.first.version_type
|
93
|
+
|
94
|
+
assert p.revert_to!(p.versions.first), "Couldn't revert to 1"
|
95
|
+
assert_equal 'Welcome to the weblg', p.title
|
96
|
+
assert_equal 'LockedPage', p.versions.first.version_type
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_saves_versioned_copy_with_sti
|
100
|
+
p = SpecialLockedPage.create! :title => 'first title'
|
101
|
+
assert !p.new_record?
|
102
|
+
assert_equal 1, p.versions.size
|
103
|
+
assert_instance_of LockedPage.versioned_class, p.versions.first
|
104
|
+
assert_equal 'SpecialLockedPage', p.versions.first.version_type
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_rollback_with_version_number_with_sti
|
108
|
+
p = locked_pages(:thinking)
|
109
|
+
assert_equal 'So I was thinking', p.title
|
110
|
+
|
111
|
+
assert p.revert_to!(p.versions.first.lock_version), "Couldn't revert to 1"
|
112
|
+
assert_equal 'So I was thinking!!!', p.title
|
113
|
+
assert_equal 'SpecialLockedPage', p.versions.first.version_type
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_lock_version_works_with_versioning
|
117
|
+
p = locked_pages(:thinking)
|
118
|
+
p2 = LockedPage.find(p.id)
|
119
|
+
|
120
|
+
p.title = 'fresh title'
|
121
|
+
p.save
|
122
|
+
assert_equal 2, p.versions.size # limit!
|
123
|
+
|
124
|
+
assert_raises(ActiveRecord::StaleObjectError) do
|
125
|
+
p2.title = 'stale title'
|
126
|
+
p2.save
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def test_version_if_condition
|
131
|
+
p = Page.create! :title => "title"
|
132
|
+
assert_equal 1, p.version
|
133
|
+
|
134
|
+
Page.feeling_good = false
|
135
|
+
p.save
|
136
|
+
assert_equal 1, p.version
|
137
|
+
Page.feeling_good = true
|
138
|
+
end
|
139
|
+
|
140
|
+
def test_version_if_condition2
|
141
|
+
# set new if condition
|
142
|
+
Page.class_eval do
|
143
|
+
def new_feeling_good() title[0..0] == 'a'; end
|
144
|
+
alias_method :old_feeling_good, :feeling_good?
|
145
|
+
alias_method :feeling_good?, :new_feeling_good
|
146
|
+
end
|
147
|
+
|
148
|
+
p = Page.create! :title => "title"
|
149
|
+
assert_equal 1, p.version # version does not increment
|
150
|
+
assert_equal 1, p.versions.count
|
151
|
+
|
152
|
+
p.update_attributes(:title => 'new title')
|
153
|
+
assert_equal 1, p.version # version does not increment
|
154
|
+
assert_equal 1, p.versions.count
|
155
|
+
|
156
|
+
p.update_attributes(:title => 'a title')
|
157
|
+
assert_equal 2, p.version
|
158
|
+
assert_equal 2, p.versions.count
|
159
|
+
|
160
|
+
# reset original if condition
|
161
|
+
Page.class_eval { alias_method :feeling_good?, :old_feeling_good }
|
162
|
+
end
|
163
|
+
|
164
|
+
def test_version_if_condition_with_block
|
165
|
+
# set new if condition
|
166
|
+
old_condition = Page.version_condition
|
167
|
+
Page.version_condition = Proc.new { |page| page.title[0..0] == 'b' }
|
168
|
+
|
169
|
+
p = Page.create! :title => "title"
|
170
|
+
assert_equal 1, p.version # version does not increment
|
171
|
+
assert_equal 1, p.versions.count
|
172
|
+
|
173
|
+
p.update_attributes(:title => 'a title')
|
174
|
+
assert_equal 1, p.version # version does not increment
|
175
|
+
assert_equal 1, p.versions.count
|
176
|
+
|
177
|
+
p.update_attributes(:title => 'b title')
|
178
|
+
assert_equal 2, p.version
|
179
|
+
assert_equal 2, p.versions.count
|
180
|
+
|
181
|
+
# reset original if condition
|
182
|
+
Page.version_condition = old_condition
|
183
|
+
end
|
184
|
+
|
185
|
+
def test_version_no_limit
|
186
|
+
p = Page.create! :title => "title", :body => 'first body'
|
187
|
+
p.save
|
188
|
+
p.save
|
189
|
+
5.times do |i|
|
190
|
+
p.title = "title#{i}"
|
191
|
+
p.save
|
192
|
+
assert_equal "title#{i}", p.title
|
193
|
+
assert_equal (i+2), p.version
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def test_version_max_limit
|
198
|
+
p = LockedPage.create! :title => "title"
|
199
|
+
p.update_attributes(:title => "title1")
|
200
|
+
p.update_attributes(:title => "title2")
|
201
|
+
5.times do |i|
|
202
|
+
p.title = "title#{i}"
|
203
|
+
p.save
|
204
|
+
assert_equal "title#{i}", p.title
|
205
|
+
assert_equal (i+4), p.lock_version
|
206
|
+
assert p.versions(true).size <= 2, "locked version can only store 2 versions"
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
def test_track_altered_attributes_default_value
|
211
|
+
assert !Page.track_altered_attributes
|
212
|
+
assert LockedPage.track_altered_attributes
|
213
|
+
assert SpecialLockedPage.track_altered_attributes
|
214
|
+
end
|
215
|
+
|
216
|
+
def test_track_altered_attributes
|
217
|
+
p = LockedPage.create! :title => "title"
|
218
|
+
assert_equal 1, p.lock_version
|
219
|
+
assert_equal 1, p.versions(true).size
|
220
|
+
|
221
|
+
p.body = 'whoa'
|
222
|
+
assert !p.save_version?
|
223
|
+
p.save
|
224
|
+
assert_equal 2, p.lock_version # still increments version because of optimistic locking
|
225
|
+
assert_equal 1, p.versions(true).size
|
226
|
+
|
227
|
+
p.title = 'updated title'
|
228
|
+
assert p.save_version?
|
229
|
+
p.save
|
230
|
+
assert_equal 3, p.lock_version
|
231
|
+
assert_equal 1, p.versions(true).size # version 1 deleted
|
232
|
+
|
233
|
+
p.title = 'updated title!'
|
234
|
+
assert p.save_version?
|
235
|
+
p.save
|
236
|
+
assert_equal 4, p.lock_version
|
237
|
+
assert_equal 2, p.versions(true).size # version 1 deleted
|
238
|
+
end
|
239
|
+
|
240
|
+
def test_find_versions
|
241
|
+
assert_equal 1, locked_pages(:welcome).versions.find(:all, :conditions => ['title LIKE ?', '%weblog%']).size
|
242
|
+
end
|
243
|
+
|
244
|
+
def test_find_version
|
245
|
+
assert_equal pages_h(:welcome_1), pages(:welcome).versions.find_by_version(23)
|
246
|
+
end
|
247
|
+
|
248
|
+
def test_with_sequence
|
249
|
+
assert_equal 'widgets_seq', Widget.versioned_class.sequence_name
|
250
|
+
3.times { Widget.create! :name => 'new widget' }
|
251
|
+
assert_equal 3, Widget.count
|
252
|
+
assert_equal 3, Widget.versioned_class.count
|
253
|
+
end
|
254
|
+
|
255
|
+
def test_has_many_through
|
256
|
+
assert_equal [authors(:caged), authors(:mly)], pages(:welcome).authors
|
257
|
+
end
|
258
|
+
|
259
|
+
def test_has_many_through_with_custom_association
|
260
|
+
assert_equal [authors(:caged), authors(:mly)], pages(:welcome).revisors
|
261
|
+
end
|
262
|
+
|
263
|
+
def test_referential_integrity
|
264
|
+
pages(:welcome).destroy
|
265
|
+
assert_equal 0, Page.count
|
266
|
+
assert_equal 3, Page::Version.count
|
267
|
+
end
|
268
|
+
|
269
|
+
def test_association_options
|
270
|
+
association = Page.reflect_on_association(:versions)
|
271
|
+
options = association.options
|
272
|
+
assert_equal nil, options[:dependent]
|
273
|
+
|
274
|
+
association = Widget.reflect_on_association(:versions)
|
275
|
+
options = association.options
|
276
|
+
assert_equal :nullify, options[:dependent]
|
277
|
+
assert_equal 'version desc', options[:order]
|
278
|
+
assert_equal 'widget_id', options[:foreign_key]
|
279
|
+
|
280
|
+
widget = Widget.create! :name => 'new widget'
|
281
|
+
assert_equal 1, Widget.count
|
282
|
+
assert_equal 1, Widget.versioned_class.count
|
283
|
+
widget.destroy
|
284
|
+
assert_equal 0, Widget.count
|
285
|
+
assert_equal 2, Widget.versioned_class.count
|
286
|
+
end
|
287
|
+
|
288
|
+
def test_versioned_records_should_belong_to_parent
|
289
|
+
page = pages(:welcome)
|
290
|
+
page_version = page.versions.last
|
291
|
+
assert_equal page, page_version.page
|
292
|
+
end
|
293
|
+
|
294
|
+
def test_unaltered_attributes
|
295
|
+
landmarks(:washington).attributes = landmarks(:washington).attributes.except("id")
|
296
|
+
assert !landmarks(:washington).changed?
|
297
|
+
end
|
298
|
+
|
299
|
+
def test_unchanged_string_attributes
|
300
|
+
landmarks(:washington).attributes = landmarks(:washington).attributes.except("id").inject({}) { |params, (key, value)| params.update(key => value.to_s) }
|
301
|
+
assert !landmarks(:washington).changed?
|
302
|
+
end
|
303
|
+
|
304
|
+
def test_should_find_earliest_version
|
305
|
+
assert_equal pages_h(:welcome_1), pages(:welcome).versions.earliest
|
306
|
+
end
|
307
|
+
|
308
|
+
def test_should_find_latest_version
|
309
|
+
assert_equal pages_h(:welcome_2), pages(:welcome).versions.latest
|
310
|
+
end
|
311
|
+
|
312
|
+
def test_should_find_previous_version
|
313
|
+
assert_equal pages_h(:welcome_1), pages_h(:welcome_2).previous
|
314
|
+
assert_equal pages_h(:welcome_1), pages(:welcome).versions.before(pages_h(:welcome_2))
|
315
|
+
end
|
316
|
+
|
317
|
+
def test_should_find_next_version
|
318
|
+
assert_equal pages_h(:welcome_2), pages_h(:welcome_1).next
|
319
|
+
assert_equal pages_h(:welcome_2), pages(:welcome).versions.after(pages_h(:welcome_1))
|
320
|
+
end
|
321
|
+
|
322
|
+
def test_should_find_version_count
|
323
|
+
assert_equal 2, pages(:welcome).versions.size
|
324
|
+
end
|
325
|
+
|
326
|
+
def test_if_changed_creates_version_if_a_listed_column_is_changed
|
327
|
+
landmarks(:washington).name = "Washington"
|
328
|
+
assert landmarks(:washington).changed?
|
329
|
+
assert landmarks(:washington).altered?
|
330
|
+
end
|
331
|
+
|
332
|
+
def test_if_changed_creates_version_if_all_listed_columns_are_changed
|
333
|
+
landmarks(:washington).name = "Washington"
|
334
|
+
landmarks(:washington).latitude = 1.0
|
335
|
+
landmarks(:washington).longitude = 1.0
|
336
|
+
assert landmarks(:washington).changed?
|
337
|
+
assert landmarks(:washington).altered?
|
338
|
+
end
|
339
|
+
|
340
|
+
def test_if_changed_does_not_create_new_version_if_unlisted_column_is_changed
|
341
|
+
landmarks(:washington).doesnt_trigger_version = "This should not trigger version"
|
342
|
+
assert landmarks(:washington).changed?
|
343
|
+
assert !landmarks(:washington).altered?
|
344
|
+
end
|
345
|
+
|
346
|
+
def test_without_locking_temporarily_disables_optimistic_locking
|
347
|
+
enabled1 = false
|
348
|
+
block_called = false
|
349
|
+
|
350
|
+
ActiveRecord::Base.lock_optimistically = true
|
351
|
+
LockedPage.without_locking do
|
352
|
+
enabled1 = ActiveRecord::Base.lock_optimistically
|
353
|
+
block_called = true
|
354
|
+
end
|
355
|
+
enabled2 = ActiveRecord::Base.lock_optimistically
|
356
|
+
|
357
|
+
assert block_called
|
358
|
+
assert !enabled1
|
359
|
+
assert enabled2
|
360
|
+
end
|
361
|
+
|
362
|
+
def test_without_locking_reverts_optimistic_locking_settings_if_block_raises_exception
|
363
|
+
assert_raises(RuntimeError) do
|
364
|
+
LockedPage.without_locking do
|
365
|
+
raise RuntimeError, "oh noes"
|
366
|
+
end
|
367
|
+
end
|
368
|
+
assert ActiveRecord::Base.lock_optimistically
|
369
|
+
end
|
370
|
+
|
371
|
+
def test_deleted_in_original_table
|
372
|
+
record = Page::Version.find 2
|
373
|
+
assert_equal false, record.deleted_in_original_table
|
374
|
+
record.page.title = "Title changed"
|
375
|
+
assert record.page.save
|
376
|
+
|
377
|
+
record = Page::Version.find 3
|
378
|
+
assert_equal false, record.deleted_in_original_table
|
379
|
+
|
380
|
+
record.page.destroy
|
381
|
+
record = Page::Version.find 4
|
382
|
+
assert_equal true, record.deleted_in_original_table
|
383
|
+
end
|
384
|
+
end
|