acts_as_versioned_rails3 0.6.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.
@@ -0,0 +1,16 @@
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
@@ -0,0 +1,8 @@
1
+ welcome:
2
+ id: 1
3
+ title: Welcome to the weblog
4
+ body: Such a lovely day
5
+ version: 24
6
+ author_id: 1
7
+ revisor_id: 1
8
+ 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,45 @@
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
+ end
23
+
24
+ def test_versioned_migration
25
+ assert_raises(ActiveRecord::StatementInvalid) { Thing.create :title => 'blah blah' }
26
+ # take 'er up
27
+ ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/')
28
+ t = Thing.create :title => 'blah blah', :price => 123.45, :type => 'Thing'
29
+ assert_equal 1, t.versions.size
30
+
31
+ # check that the price column has remembered its value correctly
32
+ assert_equal t.price, t.versions.first.price
33
+ assert_equal t.title, t.versions.first.title
34
+ assert_equal t[:type], t.versions.first[:type]
35
+
36
+ # make sure that the precision of the price column has been preserved
37
+ assert_equal 7, Thing::Version.columns.find{|c| c.name == "price"}.precision
38
+ assert_equal 2, Thing::Version.columns.find{|c| c.name == "price"}.scale
39
+
40
+ # now lets take 'er back down
41
+ ActiveRecord::Migrator.down(File.dirname(__FILE__) + '/fixtures/migrations/')
42
+ assert_raises(ActiveRecord::StatementInvalid) { Thing.create :title => 'blah blah' }
43
+ end
44
+ end
45
+ end
data/test/schema.rb ADDED
@@ -0,0 +1,82 @@
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 :created_on, :datetime
7
+ t.column :updated_on, :datetime
8
+ t.column :author_id, :integer
9
+ t.column :revisor_id, :integer
10
+ end
11
+
12
+ create_table :page_versions, :force => true do |t|
13
+ t.column :page_id, :integer
14
+ t.column :version, :integer
15
+ t.column :title, :string, :limit => 255
16
+ t.column :body, :text
17
+ t.column :created_on, :datetime
18
+ t.column :updated_on, :datetime
19
+ t.column :author_id, :integer
20
+ t.column :revisor_id, :integer
21
+ end
22
+
23
+ add_index :page_versions, [:page_id, :version], :unique => true
24
+
25
+ create_table :authors, :force => true do |t|
26
+ t.column :page_id, :integer
27
+ t.column :name, :string
28
+ end
29
+
30
+ create_table :locked_pages, :force => true do |t|
31
+ t.column :lock_version, :integer
32
+ t.column :title, :string, :limit => 255
33
+ t.column :body, :text
34
+ t.column :type, :string, :limit => 255
35
+ end
36
+
37
+ create_table :locked_pages_revisions, :force => true do |t|
38
+ t.column :page_id, :integer
39
+ t.column :lock_version, :integer
40
+ t.column :title, :string, :limit => 255
41
+ t.column :body, :text
42
+ t.column :version_type, :string, :limit => 255
43
+ t.column :updated_at, :datetime
44
+ end
45
+
46
+ add_index :locked_pages_revisions, [:page_id, :lock_version], :unique => true
47
+
48
+ create_table :widgets, :force => true do |t|
49
+ t.column :name, :string, :limit => 50
50
+ t.column :foo, :string
51
+ t.column :version, :integer
52
+ t.column :updated_at, :datetime
53
+ end
54
+
55
+ create_table :widget_versions, :force => true do |t|
56
+ t.column :widget_id, :integer
57
+ t.column :name, :string, :limit => 50
58
+ t.column :version, :integer
59
+ t.column :updated_at, :datetime
60
+ end
61
+
62
+ add_index :widget_versions, [:widget_id, :version], :unique => true
63
+
64
+ create_table :landmarks, :force => true do |t|
65
+ t.column :name, :string
66
+ t.column :latitude, :float
67
+ t.column :longitude, :float
68
+ t.column :doesnt_trigger_version,:string
69
+ t.column :version, :integer
70
+ end
71
+
72
+ create_table :landmark_versions, :force => true do |t|
73
+ t.column :landmark_id, :integer
74
+ t.column :name, :string
75
+ t.column :latitude, :float
76
+ t.column :longitude, :float
77
+ t.column :doesnt_trigger_version,:string
78
+ t.column :version, :integer
79
+ end
80
+
81
+ add_index :landmark_versions, [:landmark_id, :version], :unique => true
82
+ end
@@ -0,0 +1,370 @@
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
+ 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 page_versions(: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 0, 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 :delete_all, 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 1, 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 page_versions(:welcome_1), pages(:welcome).versions.earliest
306
+ end
307
+
308
+ def test_should_find_latest_version
309
+ assert_equal page_versions(:welcome_2), pages(:welcome).versions.latest
310
+ end
311
+
312
+ def test_should_find_previous_version
313
+ assert_equal page_versions(:welcome_1), page_versions(:welcome_2).previous
314
+ assert_equal page_versions(:welcome_1), pages(:welcome).versions.before(page_versions(:welcome_2))
315
+ end
316
+
317
+ def test_should_find_next_version
318
+ assert_equal page_versions(:welcome_2), page_versions(:welcome_1).next
319
+ assert_equal page_versions(:welcome_2), pages(:welcome).versions.after(page_versions(: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
+ end
metadata ADDED
@@ -0,0 +1,95 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: acts_as_versioned_rails3
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.6.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - René Madsen
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-05-16 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activerecord
16
+ requirement: &9242940 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 3.0.9
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *9242940
25
+ - !ruby/object:Gem::Dependency
26
+ name: sqlite3-ruby
27
+ requirement: &9242420 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: 1.3.1
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *9242420
36
+ description: Add simple versioning to ActiveRecord models.
37
+ email: rm@microting.com
38
+ executables: []
39
+ extensions: []
40
+ extra_rdoc_files:
41
+ - README
42
+ - MIT-LICENSE
43
+ - CHANGELOG
44
+ files:
45
+ - CHANGELOG
46
+ - Gemfile
47
+ - MIT-LICENSE
48
+ - README
49
+ - RUNNING_UNIT_TESTS
50
+ - Rakefile
51
+ - acts_as_versioned.gemspec
52
+ - init.rb
53
+ - lib/acts_as_versioned.rb
54
+ - test/abstract_unit.rb
55
+ - test/database.yml
56
+ - test/fixtures/authors.yml
57
+ - test/fixtures/landmark.rb
58
+ - test/fixtures/landmark_versions.yml
59
+ - test/fixtures/landmarks.yml
60
+ - test/fixtures/locked_pages.yml
61
+ - test/fixtures/locked_pages_revisions.yml
62
+ - test/fixtures/migrations/2_add_versioned_tables.rb
63
+ - test/fixtures/page.rb
64
+ - test/fixtures/page_versions.yml
65
+ - test/fixtures/pages.yml
66
+ - test/fixtures/widget.rb
67
+ - test/migration_test.rb
68
+ - test/schema.rb
69
+ - test/versioned_test.rb
70
+ homepage: http://github.com/renemadsen/acts_as_versioned_rails3
71
+ licenses: []
72
+ post_install_message:
73
+ rdoc_options:
74
+ - --charset=UTF-8
75
+ require_paths:
76
+ - lib
77
+ required_ruby_version: !ruby/object:Gem::Requirement
78
+ none: false
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ required_rubygems_version: !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ! '>='
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ requirements: []
90
+ rubyforge_project: acts_as_versioned_rails3
91
+ rubygems_version: 1.8.15
92
+ signing_key:
93
+ specification_version: 2
94
+ summary: Add simple versioning to ActiveRecord models.
95
+ test_files: []