rtiss_acts_as_versioned 0.8.2 → 0.8.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +0 -8
- data/lib/rtiss_acts_as_versioned.rb +61 -43
- data/rtiss_acts_as_versioned.gemspec +7 -6
- data/test/abstract_unit.rb +4 -9
- data/test/fixtures/locked_pages.yml +4 -2
- data/test/fixtures/locked_pages_revisions.yml +4 -4
- data/test/fixtures/locked_rolle.rb +1 -1
- data/test/fixtures/migrations/{1_add_versioned_tables.rb → 2_add_versioned_tables.rb} +1 -1
- data/test/fixtures/page.rb +3 -3
- data/test/fixtures/rolle.rb +1 -1
- data/test/fixtures/widget.rb +1 -1
- data/test/migration_test.rb +5 -22
- data/test/schema.rb +11 -9
- data/test/tiss_test.rb +49 -8
- data/test/versioned_test.rb +18 -12
- metadata +36 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b9f5a6e965b68027705381bc7f298c863c4a72f1
|
4
|
+
data.tar.gz: d604439b36e5bd52fe5480dcf5e96a1a74c6f213
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 59bcc2984591245b9dcfafde7e80330388fdff93ca952ba582b3759941dc5c575bc64ea13f7ceff5b6685ae5dcba10273d24bad8839e63ff8afb409b372bb1ea
|
7
|
+
data.tar.gz: e180bd6b6234db9488ce3e9beb9f40b2c4521e57161ab89346cd96b786208822c7340d64f6c9751fce5743f6cfa516b8920b2b8669b37867dfeaf183cd2fc71a
|
data/Rakefile
CHANGED
@@ -73,14 +73,6 @@ task :console do
|
|
73
73
|
sh "irb -rubygems -r ./lib//#{name}.rb"
|
74
74
|
end
|
75
75
|
|
76
|
-
#############################################################################
|
77
|
-
#
|
78
|
-
# Custom tasks (add your own tasks here)
|
79
|
-
#
|
80
|
-
#############################################################################
|
81
|
-
|
82
|
-
|
83
|
-
|
84
76
|
#############################################################################
|
85
77
|
#
|
86
78
|
# Packaging tasks
|
@@ -20,7 +20,7 @@
|
|
20
20
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
21
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
22
|
|
23
|
-
VERSION = '0.8.
|
23
|
+
VERSION = '0.8.3'
|
24
24
|
|
25
25
|
module ActiveRecord #:nodoc:
|
26
26
|
module Acts #:nodoc:
|
@@ -173,7 +173,7 @@ module ActiveRecord #:nodoc:
|
|
173
173
|
|
174
174
|
cattr_accessor :versioned_class_name, :versioned_foreign_key, :versioned_table_name, :versioned_inheritance_column,
|
175
175
|
:version_column, :max_version_limit, :track_altered_attributes, :version_condition, :version_sequence_name, :non_versioned_columns,
|
176
|
-
:version_association_options, :version_if_changed, :deleted_in_original_table_flag, :
|
176
|
+
:version_association_options, :version_if_changed, :deleted_in_original_table_flag, :record_restored_column
|
177
177
|
|
178
178
|
self.versioned_class_name = options[:class_name] || "Version"
|
179
179
|
self.versioned_foreign_key = options[:foreign_key] || self.to_s.foreign_key
|
@@ -182,11 +182,14 @@ module ActiveRecord #:nodoc:
|
|
182
182
|
self.versioned_inheritance_column = options[:inheritance_column] || "versioned_#{inheritance_column}"
|
183
183
|
self.version_column = options[:version_column] || 'version'
|
184
184
|
self.deleted_in_original_table_flag = options[:deleted_in_original_table_flag] || 'deleted_in_original_table'
|
185
|
-
self.
|
185
|
+
self.record_restored_column = options[:record_restored_column] || 'record_restored'
|
186
186
|
self.version_sequence_name = options[:sequence_name]
|
187
187
|
self.max_version_limit = options[:limit].to_i
|
188
188
|
self.version_condition = options[:if] || true
|
189
189
|
self.non_versioned_columns = [self.primary_key, inheritance_column, self.version_column, 'lock_version', versioned_inheritance_column] + options[:non_versioned_columns].to_a.map(&:to_s)
|
190
|
+
if options[:association_options].is_a?(Hash) && options[:association_options][:dependent] == :nullify
|
191
|
+
raise "Illegal option :dependent => :nullify - this would produce orphans in version model"
|
192
|
+
end
|
190
193
|
self.version_association_options = {
|
191
194
|
:class_name => "#{self.to_s}::#{versioned_class_name}",
|
192
195
|
:foreign_key => versioned_foreign_key
|
@@ -205,12 +208,12 @@ module ActiveRecord #:nodoc:
|
|
205
208
|
has_many :versions, version_association_options do
|
206
209
|
# finds earliest version of this record
|
207
210
|
def earliest
|
208
|
-
@earliest ||=
|
211
|
+
@earliest ||= order('#{version_column}').first
|
209
212
|
end
|
210
213
|
|
211
214
|
# find latest version of this record
|
212
215
|
def latest
|
213
|
-
@latest ||=
|
216
|
+
@latest ||= order('#{version_column} desc').first
|
214
217
|
end
|
215
218
|
end
|
216
219
|
before_save :set_new_version
|
@@ -231,15 +234,14 @@ module ActiveRecord #:nodoc:
|
|
231
234
|
const_set(versioned_class_name, Class.new(ActiveRecord::Base)).class_eval do
|
232
235
|
def self.reloadable? ; false ; end
|
233
236
|
# find first version before the given version
|
237
|
+
# TODO: replace "version" in selects with version_column, use select-method instead of find
|
234
238
|
def self.before(version)
|
235
|
-
|
236
|
-
:conditions => ["#{original_class.versioned_foreign_key} = ? and version < ?", version.send(original_class.versioned_foreign_key), version.version]
|
239
|
+
where("#{original_class.versioned_foreign_key} = ? and version < ?", version.send(original_class.versioned_foreign_key), version.version).order('version desc').first
|
237
240
|
end
|
238
241
|
|
239
242
|
# find first version after the given version.
|
240
243
|
def self.after(version)
|
241
|
-
|
242
|
-
:conditions => ["#{original_class.versioned_foreign_key} = ? and version > ?", version.send(original_class.versioned_foreign_key), version.version]
|
244
|
+
where("#{original_class.versioned_foreign_key} = ? and version > ?", version.send(original_class.versioned_foreign_key), version.version).order('version').first
|
243
245
|
end
|
244
246
|
|
245
247
|
def previous
|
@@ -263,7 +265,7 @@ module ActiveRecord #:nodoc:
|
|
263
265
|
version_hash = self.attributes
|
264
266
|
version_hash.delete "id"
|
265
267
|
version_hash.delete self.original_class.deleted_in_original_table_flag.to_s
|
266
|
-
version_hash.delete self.original_class.
|
268
|
+
version_hash.delete self.original_class.record_restored_column.to_s
|
267
269
|
version_hash.delete self.original_class.versioned_foreign_key.to_s
|
268
270
|
|
269
271
|
restored_record = self.original_class.new(version_hash)
|
@@ -271,18 +273,26 @@ module ActiveRecord #:nodoc:
|
|
271
273
|
if restored_record.respond_to? :updated_at=
|
272
274
|
restored_record.updated_at = Time.now
|
273
275
|
end
|
276
|
+
# DON'T EVEN THINK ABOUT CALCULATING THE VERSION NUMBER USING THE VERSIONS ASSOCIATION HERE:
|
277
|
+
# There is a problem in ActiveRecord. An association Relation will be converted to an Array internally, when the SQL-select is
|
278
|
+
# executed.
|
279
|
+
# Some ActiveRecord-Methods (for example #ActiveRecord::Base::AutosaveAssociation#save_collection_association) try to use ActiveRecord methods
|
280
|
+
# with these Relations, and if these Relations have been converted to Arrays, these calls fail with an Exception
|
281
|
+
new_version_number = self.class.where(self.original_class.versioned_foreign_key => id).order('id desc').first.send(restored_record.version_column).to_i + 1
|
282
|
+
restored_record.send("#{restored_record.version_column}=", new_version_number)
|
274
283
|
unless restored_record.save_without_revision(perform_validation)
|
275
284
|
raise RuntimeError.new("Couldn't restore the record, id = #{id} class = #{self.class.name}")
|
276
285
|
end
|
286
|
+
restored_record.save_version(true, false, self.send(self.original_class.version_column))
|
287
|
+
end
|
277
288
|
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
new_version.save!
|
289
|
+
def record_restored?
|
290
|
+
self.read_attribute(self.original_class.record_restored_column) != nil
|
291
|
+
end
|
292
|
+
alias :record_restored :record_restored?
|
293
|
+
|
294
|
+
def record_restored_from_version
|
295
|
+
self.read_attribute(self.original_class.record_restored_column)
|
286
296
|
end
|
287
297
|
|
288
298
|
def original_record_exists?
|
@@ -307,15 +317,15 @@ module ActiveRecord #:nodoc:
|
|
307
317
|
end
|
308
318
|
|
309
319
|
# Saves a version of the model in the versioned table. This is called in the after_save callback by default
|
310
|
-
def save_version
|
311
|
-
if @saving_version
|
320
|
+
def save_version(save_this=false, deleted_flag=false, restored_from_version=nil)
|
321
|
+
if @saving_version || save_this
|
312
322
|
@saving_version = nil
|
313
323
|
rev = self.class.versioned_class.new
|
314
324
|
clone_versioned_model(self, rev)
|
315
325
|
rev.send("#{self.class.version_column}=", send(self.class.version_column))
|
316
326
|
rev.send("#{self.class.versioned_foreign_key}=", id)
|
317
|
-
rev.send("#{self.class.deleted_in_original_table_flag}=",
|
318
|
-
rev.send("#{self.class.
|
327
|
+
rev.send("#{self.class.deleted_in_original_table_flag}=", deleted_flag)
|
328
|
+
rev.send("#{self.class.record_restored_column}=", restored_from_version)
|
319
329
|
if rev.respond_to? :updated_at=
|
320
330
|
rev.updated_at = Time.now
|
321
331
|
end
|
@@ -331,7 +341,7 @@ module ActiveRecord #:nodoc:
|
|
331
341
|
rev.send("#{self.class.version_column}=", highest_version+1)
|
332
342
|
rev.send("#{self.class.versioned_foreign_key}=", id)
|
333
343
|
rev.send("#{self.class.deleted_in_original_table_flag}=", true)
|
334
|
-
rev.send("#{self.class.
|
344
|
+
rev.send("#{self.class.record_restored_column}=", nil)
|
335
345
|
if rev.respond_to? :updated_at=
|
336
346
|
rev.updated_at = Time.now
|
337
347
|
end
|
@@ -351,9 +361,12 @@ module ActiveRecord #:nodoc:
|
|
351
361
|
# Reverts a model to a given version. Takes either a version number or an instance of the versioned model
|
352
362
|
def revert_to(version)
|
353
363
|
if version.is_a?(self.class.versioned_class)
|
364
|
+
@reverted_from = version.send(self.class.version_column)
|
354
365
|
return false unless version.send(self.class.versioned_foreign_key) == id and !version.new_record?
|
355
366
|
else
|
356
|
-
|
367
|
+
@reverted_from = version
|
368
|
+
version = versions.where(self.class.version_column => version).first
|
369
|
+
return false unless version
|
357
370
|
end
|
358
371
|
self.clone_versioned_model(version, self)
|
359
372
|
send("#{self.class.version_column}=", version.send(self.class.version_column))
|
@@ -363,7 +376,13 @@ module ActiveRecord #:nodoc:
|
|
363
376
|
# Reverts a model to a given version and saves the model.
|
364
377
|
# Takes either a version number or an instance of the versioned model
|
365
378
|
def revert_to!(version)
|
366
|
-
revert_to(version)
|
379
|
+
if revert_to(version)
|
380
|
+
set_new_version
|
381
|
+
save_without_revision
|
382
|
+
save_version(true, false, @reverted_from)
|
383
|
+
else
|
384
|
+
false
|
385
|
+
end
|
367
386
|
end
|
368
387
|
|
369
388
|
# Temporarily turns off Optimistic Locking while saving. Used when reverting so that a new version is not created.
|
@@ -451,7 +470,7 @@ module ActiveRecord #:nodoc:
|
|
451
470
|
|
452
471
|
options = args.extract_options!
|
453
472
|
version_condition = "#{self.class.versioned_foreign_key} = #{self.id}"
|
454
|
-
if options[:conditions]
|
473
|
+
if options[:conditions]
|
455
474
|
options[:conditions] += " and #{version_condition}"
|
456
475
|
else
|
457
476
|
options[:conditions] = version_condition
|
@@ -466,7 +485,7 @@ module ActiveRecord #:nodoc:
|
|
466
485
|
def find_newest_version
|
467
486
|
return nil if self.id.nil?
|
468
487
|
|
469
|
-
self.class.versioned_class.
|
488
|
+
self.class.versioned_class.where("#{self.class.versioned_foreign_key} = #{self.id}").order("version DESC").first
|
470
489
|
end
|
471
490
|
|
472
491
|
def highest_version
|
@@ -481,22 +500,22 @@ module ActiveRecord #:nodoc:
|
|
481
500
|
def find_version(version)
|
482
501
|
return nil if self.id.nil?
|
483
502
|
|
484
|
-
ret = self.class.versioned_class.
|
503
|
+
ret = self.class.versioned_class.where("#{self.class.versioned_foreign_key} = #{self.id} and #{self.class.version_column}=#{version}").first
|
485
504
|
raise "find_version: version #{version} not found in database" unless ret
|
486
505
|
ret
|
487
506
|
end
|
488
507
|
|
489
508
|
protected
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
509
|
+
# sets the new version before saving
|
510
|
+
def set_new_version
|
511
|
+
@saving_version = new_record? || save_version?
|
512
|
+
self.send("#{self.class.version_column}=", next_version) if new_record? || save_version?
|
513
|
+
end
|
495
514
|
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
515
|
+
# Gets the next available version for the current record, or 1 for a new record
|
516
|
+
def next_version
|
517
|
+
(new_record? ? 0 : versions.calculate(:maximum, version_column).to_i) + 1
|
518
|
+
end
|
500
519
|
|
501
520
|
module ClassMethods
|
502
521
|
# Returns an array of columns that are versioned. See non_versioned_columns
|
@@ -523,13 +542,13 @@ module ActiveRecord #:nodoc:
|
|
523
542
|
t.column versioned_foreign_key, :integer
|
524
543
|
t.column version_column, :integer
|
525
544
|
t.column deleted_in_original_table_flag, :boolean, :default => false
|
526
|
-
t.column
|
545
|
+
t.column record_restored_column, :integer, :default => nil
|
527
546
|
end
|
528
547
|
|
529
548
|
self.versioned_columns.each do |col|
|
530
549
|
self.connection.add_column versioned_table_name, col.name, col.type,
|
531
550
|
:limit => col.limit,
|
532
|
-
:default => col.default,
|
551
|
+
:default => col.cast_type.type_cast_from_database(col.default), # convert strings to ruby types
|
533
552
|
:scale => col.scale,
|
534
553
|
:precision => col.precision
|
535
554
|
end
|
@@ -537,7 +556,7 @@ module ActiveRecord #:nodoc:
|
|
537
556
|
if type_col = self.columns_hash[inheritance_column]
|
538
557
|
self.connection.add_column versioned_table_name, versioned_inheritance_column, type_col.type,
|
539
558
|
:limit => type_col.limit,
|
540
|
-
:default => type_col.default,
|
559
|
+
:default => type_col.cast_type.type_cast_from_database(type_col.default), # convert strings to ruby types
|
541
560
|
:scale => type_col.scale,
|
542
561
|
:precision => type_col.precision
|
543
562
|
end
|
@@ -551,12 +570,12 @@ module ActiveRecord #:nodoc:
|
|
551
570
|
end
|
552
571
|
|
553
572
|
def restore_deleted(id)
|
554
|
-
version_record = versioned_class.
|
573
|
+
version_record = versioned_class.where("#{versioned_foreign_key} = #{id}").order("version DESC").first
|
555
574
|
version_record.restore
|
556
575
|
end
|
557
576
|
|
558
577
|
def restore_deleted_version(id, version)
|
559
|
-
version_record = versioned_class.
|
578
|
+
version_record = versioned_class.where("#{versioned_foreign_key} = #{id} and version = #{version}").first
|
560
579
|
version_record.restore
|
561
580
|
end
|
562
581
|
|
@@ -604,7 +623,6 @@ module ActiveRecord #:nodoc:
|
|
604
623
|
end
|
605
624
|
|
606
625
|
# TISS extension: do not pull this.
|
607
|
-
# TODO: Move to TISS app (initializer)
|
608
626
|
module ActiveRecord #:nodoc:
|
609
627
|
module ConnectionAdapters #:nodoc:
|
610
628
|
class TableDefinition
|
@@ -12,8 +12,8 @@ Gem::Specification.new do |s|
|
|
12
12
|
## If your rubyforge_project name is different, then edit it and comment out
|
13
13
|
## the sub! line in the Rakefile
|
14
14
|
s.name = 'rtiss_acts_as_versioned'
|
15
|
-
s.version = '0.8.
|
16
|
-
s.date = '
|
15
|
+
s.version = '0.8.3'
|
16
|
+
s.date = '2016-01-25'
|
17
17
|
s.rubyforge_project = 'rtiss_acts_as_versioned'
|
18
18
|
s.summary = "Add simple versioning to ActiveRecord models (TISS version)."
|
19
19
|
s.description = "Add simple versioning to ActiveRecord models (TISS version).
|
@@ -31,10 +31,11 @@ to use technoweenie's version (can be found also on github)"
|
|
31
31
|
s.rdoc_options = ["--charset=UTF-8"]
|
32
32
|
s.extra_rdoc_files = %w[README MIT-LICENSE CHANGELOG]
|
33
33
|
|
34
|
-
s.add_dependency 'activerecord', ">=
|
34
|
+
s.add_dependency 'activerecord', ">= 4.2.5"
|
35
35
|
s.add_development_dependency 'sqlite3-ruby', "~> 1.3.1"
|
36
|
-
s.add_development_dependency 'rails', "~>
|
37
|
-
s.add_development_dependency '
|
36
|
+
s.add_development_dependency 'rails', "~> 4.2.5"
|
37
|
+
s.add_development_dependency 'activerecord-testcase'
|
38
|
+
s.add_development_dependency 'activerecord-deprecated_finders' # todo alte, hash-basierte finders auf die neue AR Query-API migrieren
|
38
39
|
|
39
40
|
## Leave this section as-is. It will be automatically generated from the
|
40
41
|
## contents of your Git repository via the gemspec task. DO NOT REMOVE
|
@@ -59,7 +60,7 @@ to use technoweenie's version (can be found also on github)"
|
|
59
60
|
test/fixtures/locked_pages.yml
|
60
61
|
test/fixtures/locked_pages_revisions.yml
|
61
62
|
test/fixtures/locked_rolle.rb
|
62
|
-
test/fixtures/migrations/
|
63
|
+
test/fixtures/migrations/2_add_versioned_tables.rb
|
63
64
|
test/fixtures/page.rb
|
64
65
|
test/fixtures/pages.yml
|
65
66
|
test/fixtures/pages_h.yml
|
data/test/abstract_unit.rb
CHANGED
@@ -1,22 +1,17 @@
|
|
1
|
-
require "rubygems"
|
2
1
|
require "bundler"
|
3
2
|
Bundler.setup(:default, :development)
|
4
3
|
|
5
4
|
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
6
|
-
require '
|
5
|
+
require 'minitest/autorun'
|
7
6
|
require 'active_support'
|
8
7
|
require 'active_record'
|
9
8
|
require 'active_record/fixtures'
|
10
9
|
require 'active_record/test_case'
|
11
|
-
|
12
|
-
begin
|
13
|
-
require 'ruby-debug'
|
14
|
-
Debugger.start
|
15
|
-
rescue LoadError
|
16
|
-
end
|
17
|
-
|
10
|
+
require 'active_record/deprecated_finders'
|
18
11
|
require 'rtiss_acts_as_versioned'
|
19
12
|
|
13
|
+
ActiveSupport::TestCase.test_order = :sorted
|
14
|
+
|
20
15
|
config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
|
21
16
|
ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log")
|
22
17
|
ActiveRecord::Base.configurations = {'test' => config[ENV['DB'] || 'sqlite3']}
|
@@ -2,26 +2,26 @@ welcome_1:
|
|
2
2
|
id: 1
|
3
3
|
page_id: 1
|
4
4
|
title: Welcome to the weblg
|
5
|
-
|
5
|
+
version: 23
|
6
6
|
version_type: LockedPage
|
7
7
|
|
8
8
|
welcome_2:
|
9
9
|
id: 2
|
10
10
|
page_id: 1
|
11
11
|
title: Welcome to the weblog
|
12
|
-
|
12
|
+
version: 24
|
13
13
|
version_type: LockedPage
|
14
14
|
|
15
15
|
thinking_1:
|
16
16
|
id: 3
|
17
17
|
page_id: 2
|
18
18
|
title: So I was thinking!!!
|
19
|
-
|
19
|
+
version: 23
|
20
20
|
version_type: SpecialLockedPage
|
21
21
|
|
22
22
|
thinking_2:
|
23
23
|
id: 4
|
24
24
|
page_id: 2
|
25
25
|
title: So I was thinking
|
26
|
-
|
26
|
+
version: 24
|
27
27
|
version_type: SpecialLockedPage
|
data/test/fixtures/page.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
class Page < ActiveRecord::Base
|
2
2
|
belongs_to :author
|
3
|
-
has_many :authors,
|
3
|
+
has_many :authors, -> { order(:name)}, :through => :versions
|
4
4
|
belongs_to :revisor, :class_name => 'Author'
|
5
|
-
has_many :revisors, :class_name => 'Author', :through => :versions
|
5
|
+
has_many :revisors, -> { order(:name)}, :class_name => 'Author', :through => :versions
|
6
|
+
|
6
7
|
acts_as_versioned :if => :feeling_good? do
|
7
8
|
def self.included(base)
|
8
9
|
base.cattr_accessor :feeling_good
|
@@ -29,7 +30,6 @@ class LockedPage < ActiveRecord::Base
|
|
29
30
|
:foreign_key => :page_id,
|
30
31
|
:table_name => :locked_pages_revisions,
|
31
32
|
:class_name => 'LockedPageRevision',
|
32
|
-
:version_column => :lock_version,
|
33
33
|
:limit => 2,
|
34
34
|
:if_changed => :title,
|
35
35
|
:extend => LockedPageExtension
|
data/test/fixtures/rolle.rb
CHANGED
data/test/fixtures/widget.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
class Widget < ActiveRecord::Base
|
2
2
|
acts_as_versioned :sequence_name => 'widgets_seq', :association_options => {
|
3
|
-
:
|
3
|
+
:order => 'version desc' # Don't nullify the foreign key column when deleting the original record! :dependent => :nullify option removed
|
4
4
|
}
|
5
5
|
non_versioned_columns << 'foo'
|
6
6
|
end
|
data/test/migration_test.rb
CHANGED
@@ -8,39 +8,22 @@ if ActiveRecord::Base.connection.supports_migrations?
|
|
8
8
|
|
9
9
|
class MigrationTest < ActiveSupport::TestCase
|
10
10
|
self.use_transactional_fixtures = false
|
11
|
-
|
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
|
-
|
11
|
+
|
25
12
|
def test_versioned_migration
|
26
|
-
assert_raises(ActiveRecord::StatementInvalid) { Thing.create :title => 'blah blah' }
|
27
13
|
# take 'er up
|
28
|
-
|
14
|
+
migrations_path = File.expand_path(File.dirname(__FILE__)) + '/fixtures/migrations'
|
15
|
+
require migrations_path + '/2_add_versioned_tables'
|
16
|
+
ActiveRecord::Migrator.new(:up, ActiveRecord::Migrator.migrations(migrations_path), 2).run
|
29
17
|
t = Thing.create :title => 'blah blah', :price => 123.45, :type => 'Thing'
|
30
18
|
assert_equal 1, t.versions.size
|
31
19
|
|
32
20
|
# check that the price column has remembered its value correctly
|
33
21
|
assert_equal t.price, t.versions.first.price
|
34
22
|
assert_equal t.title, t.versions.first.title
|
35
|
-
|
36
|
-
|
23
|
+
|
37
24
|
# make sure that the precision of the price column has been preserved
|
38
25
|
assert_equal 7, Thing::Version.columns.find{|c| c.name == "price"}.precision
|
39
26
|
assert_equal 2, Thing::Version.columns.find{|c| c.name == "price"}.scale
|
40
|
-
|
41
|
-
# now lets take 'er back down
|
42
|
-
ActiveRecord::Migrator.down(File.dirname(__FILE__) + '/fixtures/migrations/')
|
43
|
-
assert_raises(ActiveRecord::StatementInvalid) { Thing.create :title => 'blah blah' }
|
44
27
|
end
|
45
28
|
end
|
46
29
|
end
|
data/test/schema.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
ActiveRecord::Schema.define(:version =>
|
1
|
+
ActiveRecord::Schema.define(:version => 1) do
|
2
2
|
create_table :pages, :force => true do |t|
|
3
3
|
t.column :version, :integer
|
4
4
|
t.column :title, :string, :limit => 255
|
@@ -19,7 +19,7 @@ ActiveRecord::Schema.define(:version => 0) do
|
|
19
19
|
t.column :author_id, :integer
|
20
20
|
t.column :revisor_id, :integer
|
21
21
|
t.column :deleted_in_original_table, :boolean
|
22
|
-
t.column :record_restored, :
|
22
|
+
t.column :record_restored, :integer, :precision => 38, :scale => 0, :default => nil
|
23
23
|
end
|
24
24
|
|
25
25
|
add_index :pages_h, [:page_id, :version], :unique => true
|
@@ -31,6 +31,7 @@ ActiveRecord::Schema.define(:version => 0) do
|
|
31
31
|
|
32
32
|
create_table :locked_pages, :force => true do |t|
|
33
33
|
t.column :lock_version, :integer
|
34
|
+
t.column :version, :integer
|
34
35
|
t.column :title, :string, :limit => 255
|
35
36
|
t.column :body, :text
|
36
37
|
t.column :type, :string, :limit => 255
|
@@ -38,16 +39,17 @@ ActiveRecord::Schema.define(:version => 0) do
|
|
38
39
|
|
39
40
|
create_table :locked_pages_revisions, :force => true do |t|
|
40
41
|
t.column :page_id, :integer
|
41
|
-
t.column :
|
42
|
+
t.column :version, :integer
|
43
|
+
#t.column :lock_version, :integer
|
42
44
|
t.column :title, :string, :limit => 255
|
43
45
|
t.column :body, :text
|
44
46
|
t.column :version_type, :string, :limit => 255
|
45
47
|
t.column :updated_at, :datetime
|
46
48
|
t.column :deleted_in_original_table, :boolean
|
47
|
-
t.column :record_restored, :
|
49
|
+
t.column :record_restored, :integer, :precision => 38, :scale => 0, :default => nil
|
48
50
|
end
|
49
51
|
|
50
|
-
add_index :locked_pages_revisions, [:page_id, :
|
52
|
+
add_index :locked_pages_revisions, [:page_id, :version], :unique => true
|
51
53
|
|
52
54
|
create_table :widgets, :force => true do |t|
|
53
55
|
t.column :name, :string, :limit => 50
|
@@ -62,7 +64,7 @@ ActiveRecord::Schema.define(:version => 0) do
|
|
62
64
|
t.column :version, :integer
|
63
65
|
t.column :updated_at, :datetime
|
64
66
|
t.column :deleted_in_original_table, :boolean
|
65
|
-
t.column :record_restored, :
|
67
|
+
t.column :record_restored, :integer, :precision => 38, :scale => 0, :default => nil
|
66
68
|
end
|
67
69
|
|
68
70
|
add_index :widgets_h, [:widget_id, :version], :unique => true
|
@@ -83,7 +85,7 @@ ActiveRecord::Schema.define(:version => 0) do
|
|
83
85
|
t.column :doesnt_trigger_version,:string
|
84
86
|
t.column :version, :integer
|
85
87
|
t.column :deleted_in_original_table, :boolean
|
86
|
-
t.column :record_restored, :
|
88
|
+
t.column :record_restored, :integer, :precision => 38, :scale => 0, :default => nil
|
87
89
|
end
|
88
90
|
|
89
91
|
add_index :landmark_h, [:landmark_id, :version], :unique => true
|
@@ -111,7 +113,7 @@ ActiveRecord::Schema.define(:version => 0) do
|
|
111
113
|
t.string "name", :limit => 50
|
112
114
|
t.string "beschreibung", :limit => 250
|
113
115
|
t.boolean "deleted_in_original_table", :precision => 1, :scale => 0
|
114
|
-
t.
|
116
|
+
t.integer "record_restored", :precision => 38, :scale => 0, :default => nil
|
115
117
|
t.integer "parent_id", :precision => 38, :scale => 0
|
116
118
|
t.string "beschreibung_intern", :limit => 4000
|
117
119
|
t.string "geltungsbereich", :limit => 1000
|
@@ -144,7 +146,7 @@ ActiveRecord::Schema.define(:version => 0) do
|
|
144
146
|
t.string "name", :limit => 50
|
145
147
|
t.string "beschreibung", :limit => 250
|
146
148
|
t.boolean "deleted_in_original_table", :precision => 1, :scale => 0
|
147
|
-
t.
|
149
|
+
t.integer "record_restored", :precision => 38, :scale => 0, :default => nil
|
148
150
|
t.integer "parent_id", :precision => 38, :scale => 0
|
149
151
|
t.string "beschreibung_intern", :limit => 4000
|
150
152
|
t.string "geltungsbereich", :limit => 1000
|
data/test/tiss_test.rb
CHANGED
@@ -45,7 +45,7 @@ class TissTest < ActiveSupport::TestCase
|
|
45
45
|
|
46
46
|
def test_deleted_in_original_table
|
47
47
|
record = create_object('test deleted_in_orginal_table')
|
48
|
-
version_record = record.versions.
|
48
|
+
version_record = record.versions.first
|
49
49
|
assert version_record != nil
|
50
50
|
|
51
51
|
assert !version_record.deleted_in_original_table
|
@@ -106,23 +106,63 @@ class TissTest < ActiveSupport::TestCase
|
|
106
106
|
oid = o.id
|
107
107
|
v = o.find_version(1)
|
108
108
|
assert v!=nil
|
109
|
-
|
109
|
+
|
110
110
|
assert_raises(RuntimeError) { v.restore }
|
111
111
|
assert !v.deleted_in_original_table
|
112
112
|
assert !v.record_restored, "Record_restored shows that the record was undeleted (should be false) for a newly created record"
|
113
113
|
|
114
|
+
old_version = o.version
|
114
115
|
o.destroy
|
115
116
|
v = o.find_newest_version
|
116
|
-
|
117
|
+
first_delete_version = v.version
|
118
|
+
assert v.deleted_in_original_table, "Deleted-Flag in versioned record is not set"
|
119
|
+
assert_equal old_version + 1, v.version, "Destroy did not increment version number in history record"
|
117
120
|
|
118
121
|
v.restore
|
122
|
+
restored_version = v.version
|
119
123
|
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
124
|
o = Rolle.find oid
|
121
|
-
assert v.version == o.version, "Version field not restored correctly"
|
122
|
-
|
123
125
|
v = o.find_newest_version
|
126
|
+
v_old = v
|
127
|
+
assert_equal v.version, o.version
|
128
|
+
assert_equal old_version + 2, v.version, "Version field not restored correctly"
|
124
129
|
assert !v.deleted_in_original_table, "Deleted_in_original_table doesn't show that the record was undeleted (should be false)"
|
125
130
|
assert v.record_restored, "Record_restored doesn't show that the record was undeleted (should be true) for the version record created upon restore"
|
131
|
+
assert_equal restored_version, v.record_restored_from_version
|
132
|
+
|
133
|
+
o.name = 'kaputt'
|
134
|
+
assert o.save
|
135
|
+
o.destroy
|
136
|
+
v = o.find_newest_version
|
137
|
+
v.restore
|
138
|
+
o = Rolle.find oid
|
139
|
+
assert_equal v.version + 1, o.version
|
140
|
+
assert_equal 'kaputt', o.name
|
141
|
+
assert_equal v.version, o.find_newest_version.record_restored_from_version
|
142
|
+
o.destroy
|
143
|
+
v_old.restore
|
144
|
+
o = Rolle.find oid
|
145
|
+
assert_equal 'lebt', o.name
|
146
|
+
assert_equal v_old.version, o.find_newest_version.record_restored_from_version
|
147
|
+
end
|
148
|
+
|
149
|
+
def test_restore_and_destroy_with_revision_on_every_change
|
150
|
+
r = Rolle.new(:name => 'karin')
|
151
|
+
assert r.save
|
152
|
+
r.name = 'zak'
|
153
|
+
assert r.save
|
154
|
+
assert_equal 2, Rolle::Version.count
|
155
|
+
r.destroy
|
156
|
+
assert_equal 0, Rolle.count
|
157
|
+
assert_equal 3, Rolle::Version.count
|
158
|
+
assert version = r.find_version(3)
|
159
|
+
assert version.deleted_in_original_table?
|
160
|
+
assert version = r.find_version(2)
|
161
|
+
version.restore
|
162
|
+
assert r = Rolle.first
|
163
|
+
assert r.find_newest_version.record_restored?
|
164
|
+
assert_equal 4, Rolle::Version.count
|
165
|
+
assert_equal 4, r.version
|
126
166
|
end
|
127
167
|
|
128
168
|
def test_original_record_exists
|
@@ -193,7 +233,8 @@ class TissTest < ActiveSupport::TestCase
|
|
193
233
|
assert r.save
|
194
234
|
r.name = 'zak'
|
195
235
|
assert r.save
|
196
|
-
|
236
|
+
r.reload
|
237
|
+
assert_equal 2, r.versions.size
|
197
238
|
assert_equal 2, r.versions.count
|
198
239
|
end
|
199
240
|
|
@@ -205,9 +246,9 @@ class TissTest < ActiveSupport::TestCase
|
|
205
246
|
|
206
247
|
r = Rolle.new(:name => 'karin')
|
207
248
|
assert r.save
|
208
|
-
|
209
249
|
assert_raises RuntimeError do version.restore end
|
210
|
-
assert_nothing_raised do
|
250
|
+
#assert_nothing_raised do
|
251
|
+
version.restore(perform_validations = false) #end
|
211
252
|
end
|
212
253
|
|
213
254
|
def test_save_without_revision
|
data/test/versioned_test.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), 'abstract_unit')
|
2
2
|
require File.join(File.dirname(__FILE__), 'fixtures/page')
|
3
|
+
require File.join(File.dirname(__FILE__), 'fixtures/landmark')
|
3
4
|
require File.join(File.dirname(__FILE__), 'fixtures/widget')
|
4
5
|
|
5
6
|
class VersionedTest < ActiveSupport::TestCase
|
@@ -29,11 +30,14 @@ class VersionedTest < ActiveSupport::TestCase
|
|
29
30
|
|
30
31
|
def test_rollback_with_version_number
|
31
32
|
p = pages(:welcome)
|
33
|
+
versioncount = p.versions.count
|
32
34
|
assert_equal 24, p.version
|
33
35
|
assert_equal 'Welcome to the weblog', p.title
|
34
36
|
|
35
37
|
assert p.revert_to!(23), "Couldn't revert to 23"
|
36
|
-
|
38
|
+
assert p.reload
|
39
|
+
assert_equal versioncount + 1, p.versions.count
|
40
|
+
assert_equal 25, p.version
|
37
41
|
assert_equal 'Welcome to the weblg', p.title
|
38
42
|
end
|
39
43
|
|
@@ -56,11 +60,14 @@ class VersionedTest < ActiveSupport::TestCase
|
|
56
60
|
|
57
61
|
def test_rollback_with_version_class
|
58
62
|
p = pages(:welcome)
|
63
|
+
versioncount = p.versions.count
|
59
64
|
assert_equal 24, p.version
|
60
65
|
assert_equal 'Welcome to the weblog', p.title
|
61
66
|
|
62
67
|
assert p.revert_to!(p.versions.find_by_version(23)), "Couldn't revert to 23"
|
63
|
-
|
68
|
+
assert p.reload
|
69
|
+
assert_equal versioncount + 1, p.versions.count
|
70
|
+
assert_equal 25, p.version
|
64
71
|
assert_equal 'Welcome to the weblg', p.title
|
65
72
|
end
|
66
73
|
|
@@ -81,7 +88,7 @@ class VersionedTest < ActiveSupport::TestCase
|
|
81
88
|
assert_equal 'Welcome to the weblog', p.title
|
82
89
|
assert_equal 'LockedPage', p.versions.first.version_type
|
83
90
|
|
84
|
-
assert p.revert_to!(p.versions.first.
|
91
|
+
assert p.revert_to!(p.versions.first.version), "Couldn't revert to 23"
|
85
92
|
assert_equal 'Welcome to the weblg', p.title
|
86
93
|
assert_equal 'LockedPage', p.versions.first.version_type
|
87
94
|
end
|
@@ -108,7 +115,7 @@ class VersionedTest < ActiveSupport::TestCase
|
|
108
115
|
p = locked_pages(:thinking)
|
109
116
|
assert_equal 'So I was thinking', p.title
|
110
117
|
|
111
|
-
assert p.revert_to!(p.versions.first.
|
118
|
+
assert p.revert_to!(p.versions.first.version), "Couldn't revert to 1"
|
112
119
|
assert_equal 'So I was thinking!!!', p.title
|
113
120
|
assert_equal 'SpecialLockedPage', p.versions.first.version_type
|
114
121
|
end
|
@@ -202,7 +209,7 @@ class VersionedTest < ActiveSupport::TestCase
|
|
202
209
|
p.title = "title#{i}"
|
203
210
|
p.save
|
204
211
|
assert_equal "title#{i}", p.title
|
205
|
-
assert_equal (i+4), p.
|
212
|
+
assert_equal (i+4), p.version
|
206
213
|
assert p.versions(true).size <= 2, "locked version can only store 2 versions"
|
207
214
|
end
|
208
215
|
end
|
@@ -215,25 +222,25 @@ class VersionedTest < ActiveSupport::TestCase
|
|
215
222
|
|
216
223
|
def test_track_altered_attributes
|
217
224
|
p = LockedPage.create! :title => "title"
|
218
|
-
assert_equal 1, p.
|
225
|
+
assert_equal 1, p.version
|
219
226
|
assert_equal 1, p.versions(true).size
|
220
227
|
|
221
228
|
p.body = 'whoa'
|
222
229
|
assert !p.save_version?
|
223
230
|
p.save
|
224
|
-
assert_equal
|
231
|
+
assert_equal 1, p.version # no increment, because we're not using lock_version column
|
225
232
|
assert_equal 1, p.versions(true).size
|
226
233
|
|
227
234
|
p.title = 'updated title'
|
228
235
|
assert p.save_version?
|
229
236
|
p.save
|
230
|
-
assert_equal
|
231
|
-
assert_equal
|
237
|
+
assert_equal 2, p.version
|
238
|
+
assert_equal 2, p.versions(true).size
|
232
239
|
|
233
240
|
p.title = 'updated title!'
|
234
241
|
assert p.save_version?
|
235
242
|
p.save
|
236
|
-
assert_equal
|
243
|
+
assert_equal 3, p.version
|
237
244
|
assert_equal 2, p.versions(true).size # version 1 deleted
|
238
245
|
end
|
239
246
|
|
@@ -273,8 +280,7 @@ class VersionedTest < ActiveSupport::TestCase
|
|
273
280
|
|
274
281
|
association = Widget.reflect_on_association(:versions)
|
275
282
|
options = association.options
|
276
|
-
assert_equal :nullify, options[:dependent]
|
277
|
-
assert_equal 'version desc', options[:order]
|
283
|
+
#assert_equal :nullify, options[:dependent] #Removed! we do not nullify the foreign key, because on restore we want to set the correct original ID
|
278
284
|
assert_equal 'widget_id', options[:foreign_key]
|
279
285
|
|
280
286
|
widget = Widget.create! :name => 'new widget'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rtiss_acts_as_versioned
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rick Olson
|
@@ -10,64 +10,78 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2016-01-25 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activerecord
|
17
17
|
requirement: !ruby/object:Gem::Requirement
|
18
18
|
requirements:
|
19
|
-
- -
|
19
|
+
- - ">="
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version:
|
21
|
+
version: 4.2.5
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
25
|
requirements:
|
26
|
-
- -
|
26
|
+
- - ">="
|
27
27
|
- !ruby/object:Gem::Version
|
28
|
-
version:
|
28
|
+
version: 4.2.5
|
29
29
|
- !ruby/object:Gem::Dependency
|
30
30
|
name: sqlite3-ruby
|
31
31
|
requirement: !ruby/object:Gem::Requirement
|
32
32
|
requirements:
|
33
|
-
- - ~>
|
33
|
+
- - "~>"
|
34
34
|
- !ruby/object:Gem::Version
|
35
35
|
version: 1.3.1
|
36
36
|
type: :development
|
37
37
|
prerelease: false
|
38
38
|
version_requirements: !ruby/object:Gem::Requirement
|
39
39
|
requirements:
|
40
|
-
- - ~>
|
40
|
+
- - "~>"
|
41
41
|
- !ruby/object:Gem::Version
|
42
42
|
version: 1.3.1
|
43
43
|
- !ruby/object:Gem::Dependency
|
44
44
|
name: rails
|
45
45
|
requirement: !ruby/object:Gem::Requirement
|
46
46
|
requirements:
|
47
|
-
- - ~>
|
47
|
+
- - "~>"
|
48
48
|
- !ruby/object:Gem::Version
|
49
|
-
version:
|
49
|
+
version: 4.2.5
|
50
50
|
type: :development
|
51
51
|
prerelease: false
|
52
52
|
version_requirements: !ruby/object:Gem::Requirement
|
53
53
|
requirements:
|
54
|
-
- - ~>
|
54
|
+
- - "~>"
|
55
55
|
- !ruby/object:Gem::Version
|
56
|
-
version:
|
56
|
+
version: 4.2.5
|
57
57
|
- !ruby/object:Gem::Dependency
|
58
|
-
name:
|
58
|
+
name: activerecord-testcase
|
59
59
|
requirement: !ruby/object:Gem::Requirement
|
60
60
|
requirements:
|
61
|
-
- -
|
61
|
+
- - ">="
|
62
62
|
- !ruby/object:Gem::Version
|
63
|
-
version:
|
63
|
+
version: '0'
|
64
64
|
type: :development
|
65
65
|
prerelease: false
|
66
66
|
version_requirements: !ruby/object:Gem::Requirement
|
67
67
|
requirements:
|
68
|
-
- -
|
68
|
+
- - ">="
|
69
69
|
- !ruby/object:Gem::Version
|
70
|
-
version:
|
70
|
+
version: '0'
|
71
|
+
- !ruby/object:Gem::Dependency
|
72
|
+
name: activerecord-deprecated_finders
|
73
|
+
requirement: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
type: :development
|
79
|
+
prerelease: false
|
80
|
+
version_requirements: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
71
85
|
description: "Add simple versioning to ActiveRecord models (TISS version).\n\nEach
|
72
86
|
model has a to-many model named mymodel_h which records all changes \n(including
|
73
87
|
destroys but not deletes) made to the model. This is the version\nused by http://tiss.tuwien.ac.at
|
@@ -100,7 +114,7 @@ files:
|
|
100
114
|
- test/fixtures/locked_pages.yml
|
101
115
|
- test/fixtures/locked_pages_revisions.yml
|
102
116
|
- test/fixtures/locked_rolle.rb
|
103
|
-
- test/fixtures/migrations/
|
117
|
+
- test/fixtures/migrations/2_add_versioned_tables.rb
|
104
118
|
- test/fixtures/page.rb
|
105
119
|
- test/fixtures/pages.yml
|
106
120
|
- test/fixtures/pages_h.yml
|
@@ -115,17 +129,17 @@ licenses: []
|
|
115
129
|
metadata: {}
|
116
130
|
post_install_message:
|
117
131
|
rdoc_options:
|
118
|
-
- --charset=UTF-8
|
132
|
+
- "--charset=UTF-8"
|
119
133
|
require_paths:
|
120
134
|
- lib
|
121
135
|
required_ruby_version: !ruby/object:Gem::Requirement
|
122
136
|
requirements:
|
123
|
-
- -
|
137
|
+
- - ">="
|
124
138
|
- !ruby/object:Gem::Version
|
125
139
|
version: '0'
|
126
140
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
127
141
|
requirements:
|
128
|
-
- -
|
142
|
+
- - ">="
|
129
143
|
- !ruby/object:Gem::Version
|
130
144
|
version: '0'
|
131
145
|
requirements: []
|
@@ -135,3 +149,4 @@ signing_key:
|
|
135
149
|
specification_version: 4
|
136
150
|
summary: Add simple versioning to ActiveRecord models (TISS version).
|
137
151
|
test_files: []
|
152
|
+
has_rdoc:
|