gluttonberg_acts_as_versioned 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,49 @@
1
+ require "rubygems"
2
+ require "bundler"
3
+ Bundler.setup(:default, :development)
4
+
5
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
6
+ require 'test/unit'
7
+ require 'active_support'
8
+ require 'active_record'
9
+ require 'active_record/fixtures'
10
+ require 'active_record/test_case'
11
+
12
+ begin
13
+ require 'ruby-debug'
14
+ Debugger.start
15
+ rescue LoadError
16
+ end
17
+
18
+ require 'acts_as_versioned'
19
+
20
+ config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
21
+ ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log")
22
+ ActiveRecord::Base.configurations = {'test' => config[ENV['DB'] || 'sqlite3']}
23
+ ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['test'])
24
+
25
+ load(File.dirname(__FILE__) + "/schema.rb")
26
+
27
+ # set up custom sequence on widget_versions for DBs that support sequences
28
+ if ENV['DB'] == 'postgresql'
29
+ ActiveRecord::Base.connection.execute "DROP SEQUENCE widgets_seq;" rescue nil
30
+ ActiveRecord::Base.connection.remove_column :widget_versions, :id
31
+ ActiveRecord::Base.connection.execute "CREATE SEQUENCE widgets_seq START 101;"
32
+ ActiveRecord::Base.connection.execute "ALTER TABLE widget_versions ADD COLUMN id INTEGER PRIMARY KEY DEFAULT nextval('widgets_seq');"
33
+ end
34
+
35
+ class ActiveSupport::TestCase #:nodoc:
36
+ include ActiveRecord::TestFixtures
37
+
38
+ self.fixture_path = File.dirname(__FILE__) + "/fixtures/"
39
+
40
+ # Turn off transactional fixtures if you're working with MyISAM tables in MySQL
41
+ self.use_transactional_fixtures = true
42
+
43
+ # Instantiated fixtures are slow, but give you @david where you otherwise would need people(:david)
44
+ self.use_instantiated_fixtures = false
45
+
46
+ # Add more helper methods to be used by all tests here...
47
+ end
48
+
49
+ $:.unshift(ActiveSupport::TestCase.fixture_path)
@@ -0,0 +1,12 @@
1
+ postgresql:
2
+ adapter: postgresql
3
+ username: postgres
4
+ password:
5
+ database: acts_as_versioned_plugin_test
6
+ min_messages: ERROR
7
+ mysql:
8
+ adapter: mysql
9
+ host: localhost
10
+ username: root
11
+ password:
12
+ database: acts_as_versioned_plugin_test
@@ -0,0 +1,6 @@
1
+ caged:
2
+ id: 1
3
+ name: caged
4
+ mly:
5
+ id: 2
6
+ name: mly
@@ -0,0 +1,3 @@
1
+ class Landmark < ActiveRecord::Base
2
+ acts_as_versioned :if_changed => [ :name, :longitude, :latitude ]
3
+ end
@@ -0,0 +1,7 @@
1
+ washington:
2
+ id: 1
3
+ landmark_id: 1
4
+ version: 1
5
+ name: Washington, D.C.
6
+ latitude: 38.895
7
+ longitude: -77.036667
@@ -0,0 +1,7 @@
1
+ washington:
2
+ id: 1
3
+ name: Washington, D.C.
4
+ latitude: 38.895
5
+ longitude: -77.036667
6
+ doesnt_trigger_version: This is not important
7
+ version: 1
@@ -0,0 +1,10 @@
1
+ welcome:
2
+ id: 1
3
+ title: Welcome to the weblog
4
+ lock_version: 24
5
+ type: LockedPage
6
+ thinking:
7
+ id: 2
8
+ title: So I was thinking
9
+ lock_version: 24
10
+ type: SpecialLockedPage
@@ -0,0 +1,27 @@
1
+ welcome_1:
2
+ id: 1
3
+ page_id: 1
4
+ title: Welcome to the weblg
5
+ lock_version: 23
6
+ version_type: LockedPage
7
+
8
+ welcome_2:
9
+ id: 2
10
+ page_id: 1
11
+ title: Welcome to the weblog
12
+ lock_version: 24
13
+ version_type: LockedPage
14
+
15
+ thinking_1:
16
+ id: 3
17
+ page_id: 2
18
+ title: So I was thinking!!!
19
+ lock_version: 23
20
+ version_type: SpecialLockedPage
21
+
22
+ thinking_2:
23
+ id: 4
24
+ page_id: 2
25
+ title: So I was thinking
26
+ lock_version: 24
27
+ version_type: SpecialLockedPage
@@ -0,0 +1,15 @@
1
+ class AddVersionedTables < ActiveRecord::Migration
2
+ def self.up
3
+ create_table("things") do |t|
4
+ t.column :title, :text
5
+ t.column :price, :decimal, :precision => 7, :scale => 2
6
+ t.column :type, :string
7
+ end
8
+ Thing.create_versioned_table
9
+ end
10
+
11
+ def self.down
12
+ Thing.drop_versioned_table
13
+ drop_table "things" rescue nil
14
+ end
15
+ end
@@ -0,0 +1,43 @@
1
+ class Page < ActiveRecord::Base
2
+ belongs_to :author
3
+ has_many :authors, :through => :versions, :order => 'name'
4
+ belongs_to :revisor, :class_name => 'Author'
5
+ has_many :revisors, :class_name => 'Author', :through => :versions, :order => 'name'
6
+ acts_as_versioned :non_versioned_columns => [:state], :if => :feeling_good? do
7
+ def self.included(base)
8
+ base.cattr_accessor :feeling_good
9
+ base.feeling_good = true
10
+ base.belongs_to :author
11
+ base.belongs_to :revisor, :class_name => 'Author'
12
+ end
13
+
14
+ def feeling_good?
15
+ @@feeling_good == true
16
+ end
17
+ end
18
+ end
19
+
20
+ module LockedPageExtension
21
+ def hello_world
22
+ 'hello_world'
23
+ end
24
+ end
25
+
26
+ class LockedPage < ActiveRecord::Base
27
+ acts_as_versioned \
28
+ :inheritance_column => :version_type,
29
+ :foreign_key => :page_id,
30
+ :table_name => :locked_pages_revisions,
31
+ :class_name => 'LockedPageRevision',
32
+ :version_column => :lock_version,
33
+ :limit => 2,
34
+ :if_changed => :title,
35
+ :extend => LockedPageExtension
36
+ end
37
+
38
+ class SpecialLockedPage < LockedPage
39
+ end
40
+
41
+ class Author < ActiveRecord::Base
42
+ has_many :pages
43
+ end
@@ -0,0 +1,17 @@
1
+ welcome_2:
2
+ id: 1
3
+ page_id: 1
4
+ title: Welcome to the weblog
5
+ body: Such a lovely day
6
+ version: 24
7
+ author_id: 1
8
+ revisor_id: 1
9
+ welcome_1:
10
+ id: 2
11
+ page_id: 1
12
+ title: Welcome to the weblg
13
+ body: Such a lovely day
14
+ version: 23
15
+ author_id: 2
16
+ revisor_id: 2
17
+ version_status: draft
@@ -0,0 +1,9 @@
1
+ welcome:
2
+ id: 1
3
+ title: Welcome to the weblog
4
+ body: Such a lovely day
5
+ state: published
6
+ version: 24
7
+ author_id: 1
8
+ revisor_id: 1
9
+ created_on: "2008-01-01 00:00:00"
@@ -0,0 +1,6 @@
1
+ class Widget < ActiveRecord::Base
2
+ acts_as_versioned :sequence_name => 'widgets_seq', :association_options => {
3
+ :dependent => :nullify, :order => 'version desc'
4
+ }
5
+ non_versioned_columns << 'foo'
6
+ end
@@ -0,0 +1,50 @@
1
+ require File.join(File.dirname(__FILE__), 'abstract_unit')
2
+
3
+ if ActiveRecord::Base.connection.supports_migrations?
4
+ class Thing < ActiveRecord::Base
5
+ attr_accessor :version
6
+ acts_as_versioned
7
+ end
8
+
9
+ class MigrationTest < ActiveSupport::TestCase
10
+ self.use_transactional_fixtures = false
11
+ def teardown
12
+ if ActiveRecord::Base.connection.respond_to?(:initialize_schema_information)
13
+ ActiveRecord::Base.connection.initialize_schema_information
14
+ ActiveRecord::Base.connection.update "UPDATE schema_info SET version = 0"
15
+ else
16
+ ActiveRecord::Base.connection.initialize_schema_migrations_table
17
+ ActiveRecord::Base.connection.assume_migrated_upto_version(0)
18
+ end
19
+
20
+ Thing.connection.drop_table "things" rescue nil
21
+ Thing.connection.drop_table "thing_versions" rescue nil
22
+ Thing.reset_column_information
23
+ end
24
+
25
+ def test_versioned_migration
26
+ assert_raises(ActiveRecord::StatementInvalid) { Thing.create :title => 'blah blah' }
27
+ # take 'er up
28
+ ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/')
29
+ t = Thing.create :title => 'blah blah', :price => 123.45, :type => 'Thing'
30
+ assert_equal 1, t.versions.size
31
+
32
+ # check that the price column has remembered its value correctly
33
+ assert_equal t.price, t.versions.first.price
34
+ assert_equal t.title, t.versions.first.title
35
+ assert_equal t[:type], t.versions.first[:type]
36
+
37
+ # make sure that the precision of the price column has been preserved
38
+ assert_equal 7, Thing::Version.columns.find{|c| c.name == "price"}.precision
39
+ assert_equal 2, Thing::Version.columns.find{|c| c.name == "price"}.scale
40
+
41
+ # make sure freerange version additional fields are also created
42
+ assert_equal :integer, Thing::Version.columns.find{|c| c.name == "version_user_id"}.type
43
+ assert_equal :string, Thing::Version.columns.find{|c| c.name == "version_status"}.type
44
+
45
+ # now lets take 'er back down
46
+ ActiveRecord::Migrator.down(File.dirname(__FILE__) + '/fixtures/migrations/')
47
+ assert_raises(ActiveRecord::StatementInvalid) { Thing.create :title => 'blah blah' }
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,85 @@
1
+ ActiveRecord::Schema.define(:version => 0) do
2
+ create_table :pages, :force => true do |t|
3
+ t.column :version, :integer
4
+ t.column :title, :string, :limit => 255
5
+ t.column :body, :text
6
+ t.column :state, :string #Freerange extension for publishable
7
+ t.column :created_on, :datetime
8
+ t.column :updated_on, :datetime
9
+ t.column :author_id, :integer
10
+ t.column :revisor_id, :integer
11
+ end
12
+
13
+ create_table :page_versions, :force => true do |t|
14
+ t.column :page_id, :integer
15
+ t.column :version, :integer
16
+ t.column :title, :string, :limit => 255
17
+ t.column :body, :text
18
+ t.column :created_on, :datetime
19
+ t.column :updated_on, :datetime
20
+ t.column :author_id, :integer
21
+ t.column :revisor_id, :integer
22
+ t.column :version_status, :string
23
+ t.column :version_user_id, :integer
24
+ end
25
+
26
+ add_index :page_versions, [:page_id, :version], :unique => true
27
+
28
+ create_table :authors, :force => true do |t|
29
+ t.column :page_id, :integer
30
+ t.column :name, :string
31
+ end
32
+
33
+ create_table :locked_pages, :force => true do |t|
34
+ t.column :lock_version, :integer
35
+ t.column :title, :string, :limit => 255
36
+ t.column :body, :text
37
+ t.column :type, :string, :limit => 255
38
+ end
39
+
40
+ create_table :locked_pages_revisions, :force => true do |t|
41
+ t.column :page_id, :integer
42
+ t.column :lock_version, :integer
43
+ t.column :title, :string, :limit => 255
44
+ t.column :body, :text
45
+ t.column :version_type, :string, :limit => 255
46
+ t.column :updated_at, :datetime
47
+ end
48
+
49
+ add_index :locked_pages_revisions, [:page_id, :lock_version], :unique => true
50
+
51
+ create_table :widgets, :force => true do |t|
52
+ t.column :name, :string, :limit => 50
53
+ t.column :foo, :string
54
+ t.column :version, :integer
55
+ t.column :updated_at, :datetime
56
+ end
57
+
58
+ create_table :widget_versions, :force => true do |t|
59
+ t.column :widget_id, :integer
60
+ t.column :name, :string, :limit => 50
61
+ t.column :version, :integer
62
+ t.column :updated_at, :datetime
63
+ end
64
+
65
+ add_index :widget_versions, [:widget_id, :version], :unique => true
66
+
67
+ create_table :landmarks, :force => true do |t|
68
+ t.column :name, :string
69
+ t.column :latitude, :float
70
+ t.column :longitude, :float
71
+ t.column :doesnt_trigger_version,:string
72
+ t.column :version, :integer
73
+ end
74
+
75
+ create_table :landmark_versions, :force => true do |t|
76
+ t.column :landmark_id, :integer
77
+ t.column :name, :string
78
+ t.column :latitude, :float
79
+ t.column :longitude, :float
80
+ t.column :doesnt_trigger_version,:string
81
+ t.column :version, :integer
82
+ end
83
+
84
+ add_index :landmark_versions, [:landmark_id, :version], :unique => true
85
+ end
@@ -0,0 +1,377 @@
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, :page_versions, :locked_pages, :locked_pages_revisions, :authors, :landmarks, :landmark_versions
7
+ set_fixture_class :page_versions => 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
+
39
+ #Freerange extension
40
+ #test loaded_version
41
+ assert_equal p.loaded_version.version , p.version
42
+ #test status
43
+ assert_equal p.loaded_version.version_status , 'draft'
44
+ end
45
+
46
+ def test_versioned_class_name
47
+ assert_equal 'Version', Page.versioned_class_name
48
+ assert_equal 'LockedPageRevision', LockedPage.versioned_class_name
49
+ end
50
+
51
+ def test_versioned_class
52
+ assert_equal Page::Version, Page.versioned_class
53
+ assert_equal LockedPage::LockedPageRevision, LockedPage.versioned_class
54
+ end
55
+
56
+ def test_special_methods
57
+ assert_nothing_raised { pages(:welcome).feeling_good? }
58
+ assert_nothing_raised { pages(:welcome).versions.first.feeling_good? }
59
+ assert_nothing_raised { locked_pages(:welcome).hello_world }
60
+ assert_nothing_raised { locked_pages(:welcome).versions.first.hello_world }
61
+ end
62
+
63
+ def test_rollback_with_version_class
64
+ p = pages(:welcome)
65
+ assert_equal 24, p.version
66
+ assert_equal 'Welcome to the weblog', p.title
67
+
68
+ assert p.revert_to!(p.versions.find_by_version(23)), "Couldn't revert to 23"
69
+ assert_equal 23, p.version
70
+ assert_equal 'Welcome to the weblg', p.title
71
+ end
72
+
73
+ def test_rollback_fails_with_invalid_revision
74
+ p = locked_pages(:welcome)
75
+ assert !p.revert_to!(locked_pages(:thinking))
76
+ end
77
+
78
+ def test_saves_versioned_copy_with_options
79
+ p = LockedPage.create! :title => 'first title'
80
+ assert !p.new_record?
81
+ assert_equal 1, p.versions.size
82
+ assert_instance_of LockedPage.versioned_class, p.versions.first
83
+ end
84
+
85
+ def test_rollback_with_version_number_with_options
86
+ p = locked_pages(:welcome)
87
+ assert_equal 'Welcome to the weblog', p.title
88
+ assert_equal 'LockedPage', p.versions.first.version_type
89
+
90
+ assert p.revert_to!(p.versions.first.lock_version), "Couldn't revert to 23"
91
+ assert_equal 'Welcome to the weblg', p.title
92
+ assert_equal 'LockedPage', p.versions.first.version_type
93
+ end
94
+
95
+ def test_rollback_with_version_class_with_options
96
+ p = locked_pages(:welcome)
97
+ assert_equal 'Welcome to the weblog', p.title
98
+ assert_equal 'LockedPage', p.versions.first.version_type
99
+
100
+ assert p.revert_to!(p.versions.first), "Couldn't revert to 1"
101
+ assert_equal 'Welcome to the weblg', p.title
102
+ assert_equal 'LockedPage', p.versions.first.version_type
103
+ end
104
+
105
+ def test_saves_versioned_copy_with_sti
106
+ p = SpecialLockedPage.create! :title => 'first title'
107
+ assert !p.new_record?
108
+ assert_equal 1, p.versions.size
109
+ assert_instance_of LockedPage.versioned_class, p.versions.first
110
+ assert_equal 'SpecialLockedPage', p.versions.first.version_type
111
+ end
112
+
113
+ def test_rollback_with_version_number_with_sti
114
+ p = locked_pages(:thinking)
115
+ assert_equal 'So I was thinking', p.title
116
+
117
+ assert p.revert_to!(p.versions.first.lock_version), "Couldn't revert to 1"
118
+ assert_equal 'So I was thinking!!!', p.title
119
+ assert_equal 'SpecialLockedPage', p.versions.first.version_type
120
+ end
121
+
122
+ def test_lock_version_works_with_versioning
123
+ p = locked_pages(:thinking)
124
+ p2 = LockedPage.find(p.id)
125
+
126
+ p.title = 'fresh title'
127
+ p.save
128
+ assert_equal 2, p.versions.size # limit!
129
+
130
+ assert_raises(ActiveRecord::StaleObjectError) do
131
+ p2.title = 'stale title'
132
+ p2.save
133
+ end
134
+ end
135
+
136
+ def test_version_if_condition
137
+ p = Page.create! :title => "title"
138
+ assert_equal 1, p.version
139
+
140
+ Page.feeling_good = false
141
+ p.save
142
+ assert_equal 1, p.version
143
+ Page.feeling_good = true
144
+ end
145
+
146
+ def test_version_if_condition2
147
+ # set new if condition
148
+ Page.class_eval do
149
+ def new_feeling_good() title[0..0] == 'a'; end
150
+ alias_method :old_feeling_good, :feeling_good?
151
+ alias_method :feeling_good?, :new_feeling_good
152
+ end
153
+
154
+ p = Page.create! :title => "title", :state => "published"
155
+ assert_equal 1, p.version # version does not increment
156
+ assert_equal 1, p.versions.count
157
+ assert_equal "published", p.versions.first.version_status
158
+
159
+ p.update_attributes(:title => 'new title')
160
+ assert_equal 1, p.version # version does not increment
161
+ assert_equal 1, p.versions.count
162
+
163
+ p.update_attributes(:title => 'a title')
164
+ assert_equal 2, p.version
165
+ assert_equal 2, p.versions.count
166
+
167
+ # reset original if condition
168
+ Page.class_eval { alias_method :feeling_good?, :old_feeling_good }
169
+ end
170
+
171
+ def test_version_if_condition_with_block
172
+ # set new if condition
173
+ old_condition = Page.version_condition
174
+ Page.version_condition = Proc.new { |page| page.title[0..0] == 'b' }
175
+
176
+ p = Page.create! :title => "title"
177
+ assert_equal 1, p.version # version does not increment
178
+ assert_equal 1, p.versions.count
179
+
180
+ p.update_attributes(:title => 'a title')
181
+ assert_equal 1, p.version # version does not increment
182
+ assert_equal 1, p.versions.count
183
+
184
+ p.update_attributes(:title => 'b title')
185
+ assert_equal 2, p.version
186
+ assert_equal 2, p.versions.count
187
+
188
+ # reset original if condition
189
+ Page.version_condition = old_condition
190
+ end
191
+
192
+ def test_version_no_limit
193
+ p = Page.create! :title => "title", :body => 'first body'
194
+ p.save
195
+ p.save
196
+ 5.times do |i|
197
+ p.title = "title#{i}"
198
+ p.save
199
+ assert_equal "title#{i}", p.title
200
+ assert_equal (i+2), p.version
201
+ end
202
+ end
203
+
204
+ def test_version_max_limit
205
+ p = LockedPage.create! :title => "title"
206
+ p.update_attributes(:title => "title1")
207
+ p.update_attributes(:title => "title2")
208
+ 5.times do |i|
209
+ p.title = "title#{i}"
210
+ p.save
211
+ assert_equal "title#{i}", p.title
212
+ assert_equal (i+4), p.lock_version
213
+ assert p.versions(true).size <= 2, "locked version can only store 2 versions"
214
+ end
215
+ end
216
+
217
+ def test_track_altered_attributes_default_value
218
+ assert !Page.track_altered_attributes
219
+ assert LockedPage.track_altered_attributes
220
+ assert SpecialLockedPage.track_altered_attributes
221
+ end
222
+
223
+ def test_track_altered_attributes
224
+ p = LockedPage.create! :title => "title"
225
+ assert_equal 1, p.lock_version
226
+ assert_equal 1, p.versions(true).size
227
+
228
+ p.body = 'whoa'
229
+ assert !p.save_version?
230
+ p.save
231
+ assert_equal 2, p.lock_version # still increments version because of optimistic locking
232
+ assert_equal 1, p.versions(true).size
233
+
234
+ p.title = 'updated title'
235
+ assert p.save_version?
236
+ p.save
237
+ assert_equal 3, p.lock_version
238
+ assert_equal 1, p.versions(true).size # version 1 deleted
239
+
240
+ p.title = 'updated title!'
241
+ assert p.save_version?
242
+ p.save
243
+ assert_equal 4, p.lock_version
244
+ assert_equal 2, p.versions(true).size # version 1 deleted
245
+ end
246
+
247
+ def test_find_versions
248
+ assert_equal 1, locked_pages(:welcome).versions.find(:all, :conditions => ['title LIKE ?', '%weblog%']).size
249
+ end
250
+
251
+ def test_find_version
252
+ assert_equal page_versions(:welcome_1), pages(:welcome).versions.find_by_version(23)
253
+ end
254
+
255
+ def test_with_sequence
256
+ assert_equal 'widgets_seq', Widget.versioned_class.sequence_name
257
+ 3.times { Widget.create! :name => 'new widget' }
258
+ assert_equal 3, Widget.count
259
+ assert_equal 3, Widget.versioned_class.count
260
+ end
261
+
262
+ def test_has_many_through
263
+ assert_equal [authors(:caged), authors(:mly)], pages(:welcome).authors
264
+ end
265
+
266
+ def test_has_many_through_with_custom_association
267
+ assert_equal [authors(:caged), authors(:mly)], pages(:welcome).revisors
268
+ end
269
+
270
+ def test_referential_integrity
271
+ pages(:welcome).destroy
272
+ assert_equal 0, Page.count
273
+ assert_equal 0, Page::Version.count
274
+ end
275
+
276
+ def test_association_options
277
+ association = Page.reflect_on_association(:versions)
278
+ options = association.options
279
+ assert_equal :delete_all, options[:dependent]
280
+
281
+ association = Widget.reflect_on_association(:versions)
282
+ options = association.options
283
+ assert_equal :nullify, options[:dependent]
284
+ assert_equal 'version desc', options[:order]
285
+ assert_equal 'widget_id', options[:foreign_key]
286
+
287
+ widget = Widget.create! :name => 'new widget'
288
+ assert_equal 1, Widget.count
289
+ assert_equal 1, Widget.versioned_class.count
290
+ widget.destroy
291
+ assert_equal 0, Widget.count
292
+ assert_equal 1, Widget.versioned_class.count
293
+ end
294
+
295
+ def test_versioned_records_should_belong_to_parent
296
+ page = pages(:welcome)
297
+ page_version = page.versions.last
298
+ assert_equal page, page_version.page
299
+ end
300
+
301
+ def test_unaltered_attributes
302
+ landmarks(:washington).attributes = landmarks(:washington).attributes.except("id")
303
+ assert !landmarks(:washington).changed?
304
+ end
305
+
306
+ def test_unchanged_string_attributes
307
+ landmarks(:washington).attributes = landmarks(:washington).attributes.except("id").inject({}) { |params, (key, value)| params.update(key => value.to_s) }
308
+ assert !landmarks(:washington).changed?
309
+ end
310
+
311
+ def test_should_find_earliest_version
312
+ assert_equal page_versions(:welcome_1), pages(:welcome).versions.earliest
313
+ end
314
+
315
+ def test_should_find_latest_version
316
+ assert_equal page_versions(:welcome_2), pages(:welcome).versions.latest
317
+ end
318
+
319
+ def test_should_find_previous_version
320
+ assert_equal page_versions(:welcome_1), page_versions(:welcome_2).previous
321
+ assert_equal page_versions(:welcome_1), pages(:welcome).versions.before(page_versions(:welcome_2))
322
+ end
323
+
324
+ def test_should_find_next_version
325
+ assert_equal page_versions(:welcome_2), page_versions(:welcome_1).next
326
+ assert_equal page_versions(:welcome_2), pages(:welcome).versions.after(page_versions(:welcome_1))
327
+ end
328
+
329
+ def test_should_find_version_count
330
+ assert_equal 2, pages(:welcome).versions.size
331
+ end
332
+
333
+ def test_if_changed_creates_version_if_a_listed_column_is_changed
334
+ landmarks(:washington).name = "Washington"
335
+ assert landmarks(:washington).changed?
336
+ assert landmarks(:washington).altered?
337
+ end
338
+
339
+ def test_if_changed_creates_version_if_all_listed_columns_are_changed
340
+ landmarks(:washington).name = "Washington"
341
+ landmarks(:washington).latitude = 1.0
342
+ landmarks(:washington).longitude = 1.0
343
+ assert landmarks(:washington).changed?
344
+ assert landmarks(:washington).altered?
345
+ end
346
+
347
+ def test_if_changed_does_not_create_new_version_if_unlisted_column_is_changed
348
+ landmarks(:washington).doesnt_trigger_version = "This should not trigger version"
349
+ assert landmarks(:washington).changed?
350
+ assert !landmarks(:washington).altered?
351
+ end
352
+
353
+ def test_without_locking_temporarily_disables_optimistic_locking
354
+ enabled1 = false
355
+ block_called = false
356
+
357
+ ActiveRecord::Base.lock_optimistically = true
358
+ LockedPage.without_locking do
359
+ enabled1 = ActiveRecord::Base.lock_optimistically
360
+ block_called = true
361
+ end
362
+ enabled2 = ActiveRecord::Base.lock_optimistically
363
+
364
+ assert block_called
365
+ assert !enabled1
366
+ assert enabled2
367
+ end
368
+
369
+ def test_without_locking_reverts_optimistic_locking_settings_if_block_raises_exception
370
+ assert_raises(RuntimeError) do
371
+ LockedPage.without_locking do
372
+ raise RuntimeError, "oh noes"
373
+ end
374
+ end
375
+ assert ActiveRecord::Base.lock_optimistically
376
+ end
377
+ end