archival_record 2.0.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.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.rubocop.yml +74 -0
  4. data/.rubocop_todo.yml +14 -0
  5. data/.travis.yml +23 -0
  6. data/Appraisals +18 -0
  7. data/CHANGELOG.md +96 -0
  8. data/Gemfile +2 -0
  9. data/Gemfile.lock +69 -0
  10. data/LICENSE +56 -0
  11. data/README.md +209 -0
  12. data/Rakefile +16 -0
  13. data/archival_record.gemspec +51 -0
  14. data/gemfiles/rails_5.0.gemfile +8 -0
  15. data/gemfiles/rails_5.1.gemfile +8 -0
  16. data/gemfiles/rails_5.2.gemfile +8 -0
  17. data/gemfiles/rails_6.0.gemfile +7 -0
  18. data/init.rb +3 -0
  19. data/lib/archival_record.rb +19 -0
  20. data/lib/archival_record/version.rb +5 -0
  21. data/lib/archival_record_core/archival_record.rb +164 -0
  22. data/lib/archival_record_core/archival_record_active_record_methods.rb +45 -0
  23. data/lib/archival_record_core/association_operation/archive.rb +21 -0
  24. data/lib/archival_record_core/association_operation/base.rb +54 -0
  25. data/lib/archival_record_core/association_operation/unarchive.rb +17 -0
  26. data/script/setup +9 -0
  27. data/test/ambiguous_table_test.rb +16 -0
  28. data/test/application_record_test.rb +20 -0
  29. data/test/associations_test.rb +104 -0
  30. data/test/basic_test.rb +66 -0
  31. data/test/callbacks_test.rb +41 -0
  32. data/test/column_test.rb +17 -0
  33. data/test/deep_nesting_test.rb +35 -0
  34. data/test/deprecated_warning_archival_test.rb +11 -0
  35. data/test/fixtures/another_polys_holder.rb +11 -0
  36. data/test/fixtures/application_record.rb +5 -0
  37. data/test/fixtures/application_record_row.rb +8 -0
  38. data/test/fixtures/archival.rb +19 -0
  39. data/test/fixtures/archival_grandkid.rb +10 -0
  40. data/test/fixtures/archival_kid.rb +11 -0
  41. data/test/fixtures/archival_table_name.rb +10 -0
  42. data/test/fixtures/callback_archival_4.rb +19 -0
  43. data/test/fixtures/callback_archival_5.rb +23 -0
  44. data/test/fixtures/deprecated_warning_archival.rb +9 -0
  45. data/test/fixtures/exploder.rb +10 -0
  46. data/test/fixtures/independent_archival.rb +11 -0
  47. data/test/fixtures/missing_archive_number.rb +7 -0
  48. data/test/fixtures/missing_archived_at.rb +7 -0
  49. data/test/fixtures/plain.rb +7 -0
  50. data/test/fixtures/poly.rb +11 -0
  51. data/test/fixtures/readonly_when_archived.rb +8 -0
  52. data/test/polymorphic_test.rb +50 -0
  53. data/test/readonly_when_archived_test.rb +24 -0
  54. data/test/relations_test.rb +63 -0
  55. data/test/responds_test.rb +15 -0
  56. data/test/schema.rb +96 -0
  57. data/test/scope_test.rb +92 -0
  58. data/test/test_helper.rb +91 -0
  59. data/test/through_association_test.rb +27 -0
  60. data/test/transaction_test.rb +31 -0
  61. metadata +254 -0
@@ -0,0 +1,9 @@
1
+ # archival_id - integer
2
+ # archive_number - string
3
+ # archived_at - datetime
4
+ class DeprecatedWarningArchival < ActiveRecord::Base
5
+
6
+ # This should throw a deprecation warning
7
+ acts_as_archival
8
+
9
+ end
@@ -0,0 +1,10 @@
1
+ # archival_id - integer
2
+ # archive_number - string
3
+ # archived_at - datetime
4
+ class Exploder < ActiveRecord::Base
5
+
6
+ archival_record
7
+
8
+ belongs_to :archival
9
+
10
+ end
@@ -0,0 +1,11 @@
1
+ # name - string
2
+ # archival_id - integer
3
+ # archive_number - string
4
+ # archived_at - datetime
5
+ class IndependentArchival < ActiveRecord::Base
6
+
7
+ archival_record
8
+
9
+ belongs_to :archival
10
+
11
+ end
@@ -0,0 +1,7 @@
1
+ # name - string
2
+ # archived_at - datetime
3
+ class MissingArchiveNumber < ActiveRecord::Base
4
+
5
+ archival_record
6
+
7
+ end
@@ -0,0 +1,7 @@
1
+ # name - string
2
+ # archive_number - string
3
+ class MissingArchivedAt < ActiveRecord::Base
4
+
5
+ archival_record
6
+
7
+ end
@@ -0,0 +1,7 @@
1
+ # name - string
2
+ # archival_id - integer
3
+ class Plain < ActiveRecord::Base
4
+
5
+ belongs_to :archival
6
+
7
+ end
@@ -0,0 +1,11 @@
1
+ # archiveable_id - integer
2
+ # archiveable_type - string
3
+ # archive_number - string
4
+ # archived_at - datetime
5
+ class Poly < ActiveRecord::Base
6
+
7
+ archival_record
8
+
9
+ belongs_to :archiveable, polymorphic: true
10
+
11
+ end
@@ -0,0 +1,8 @@
1
+ # name - string
2
+ # archive_number - string
3
+ # archived_at - datetime
4
+ class ReadonlyWhenArchived < ActiveRecord::Base
5
+
6
+ archival_record readonly_when_archived: true
7
+
8
+ end
@@ -0,0 +1,50 @@
1
+ require_relative "test_helper"
2
+
3
+ class PolymorphicTest < ActiveSupport::TestCase
4
+
5
+ test "archive item with polymorphic association" do
6
+ archival = Archival.create!
7
+ poly = archival.polys.create!
8
+ archival.archive!
9
+
10
+ assert archival.reload.archived?
11
+ assert poly.reload.archived?
12
+ end
13
+
14
+ test "does not archive polymorphic association of different item with same id" do
15
+ archival = Archival.create!
16
+ another_polys_holder = AnotherPolysHolder.create!(id: archival.id)
17
+ poly = another_polys_holder.polys.create!
18
+ archival.archive!
19
+
20
+ assert_not poly.reload.archived?
21
+ end
22
+
23
+ test "unarchive item with polymorphic association" do
24
+ archive_attributes = {
25
+ archive_number: "test",
26
+ archived_at: Time.now
27
+ }
28
+ archival = Archival.create!(archive_attributes)
29
+ poly = archival.polys.create!(archive_attributes)
30
+ archival.unarchive!
31
+
32
+ assert_not archival.reload.archived?
33
+ assert_not poly.reload.archived?
34
+ end
35
+
36
+ test "does not unarchive polymorphic association of different item with same id" do
37
+ archive_attributes = {
38
+ archive_number: "test",
39
+ archived_at: Time.now
40
+ }
41
+
42
+ archival = Archival.create!(archive_attributes)
43
+ another_polys_holder = AnotherPolysHolder.create!(archive_attributes.merge(id: archival.id))
44
+ poly = another_polys_holder.polys.create!(archive_attributes)
45
+ archival.unarchive!
46
+
47
+ assert poly.reload.archived?
48
+ end
49
+
50
+ end
@@ -0,0 +1,24 @@
1
+ require_relative "test_helper"
2
+
3
+ class ReadonlyWhenArchivedTest < ActiveSupport::TestCase
4
+
5
+ test "archival_record objects can normally be altered after archive" do
6
+ archival = Archival.create!(name: "original")
7
+ archival.archive!
8
+ archival.name = "updated"
9
+ archival.save!
10
+
11
+ assert_equal "updated", archival.reload.name
12
+ end
13
+
14
+ test "archival_record marked as readonly_when_archived cannot be updated after archive" do
15
+ archival = ReadonlyWhenArchived.create!(name: "original")
16
+ archival.archive!
17
+ archival.name = "updated"
18
+
19
+ assert_not archival.save
20
+ assert_equal "Cannot modify an archived record.",
21
+ archival.errors.full_messages.first
22
+ end
23
+
24
+ end
@@ -0,0 +1,63 @@
1
+ require_relative "test_helper"
2
+
3
+ class RelationsTest < ActiveSupport::TestCase
4
+
5
+ test "archive_all! archives all records in an AR Association" do
6
+ 3.times { Archival.create! }
7
+
8
+ archivals = Archival.all
9
+ archivals.archive_all!
10
+ assert archivals.first.archived?
11
+ assert archivals.last.archived?
12
+ end
13
+
14
+ test "archive_all! archives all records with the same archival number" do
15
+ 3.times { Archival.create! }
16
+
17
+ archivals = Archival.all
18
+ archivals.archive_all!
19
+ assert_equal archivals.first.archive_number, archivals.last.archive_number
20
+ end
21
+
22
+ test "archive_all! archives children records" do
23
+ 3.times do
24
+ parent = Archival.create!
25
+ 2.times do
26
+ parent.archivals.create!
27
+ end
28
+ end
29
+
30
+ parents = Archival.all
31
+ parents.archive_all!
32
+
33
+ assert parents.first.archivals.first.archived?
34
+ assert parents.first.archivals.last.archived?
35
+ end
36
+
37
+ test "unarchive_all! unarchives all records in an AR Assocation" do
38
+ 3.times { Archival.create! }
39
+
40
+ archivals = Archival.all
41
+ archivals.archive_all!
42
+ archivals.unarchive_all!
43
+ assert_not archivals.first.archived?
44
+ assert_not archivals.last.archived?
45
+ end
46
+
47
+ test "unarchive_all! unarchives children records" do
48
+ 3.times do
49
+ parent = Archival.create!
50
+ 2.times do
51
+ parent.archivals.create!
52
+ end
53
+ end
54
+
55
+ parents = Archival.all
56
+ parents.archive_all!
57
+ parents.unarchive_all!
58
+
59
+ assert_not parents.first.archivals.first.archived?
60
+ assert_not parents.first.archivals.last.archived?
61
+ end
62
+
63
+ end
@@ -0,0 +1,15 @@
1
+ require_relative "test_helper"
2
+
3
+ class RespondsTest < ActiveSupport::TestCase
4
+
5
+ test "archival class responds correctly to 'archival?'" do
6
+ assert Archival.archival?
7
+ assert_not Plain.archival?
8
+ end
9
+
10
+ test "archival object responds correctly to 'archival?'" do
11
+ assert Archival.new.archival?
12
+ assert_not Plain.new.archival?
13
+ end
14
+
15
+ end
@@ -0,0 +1,96 @@
1
+ ActiveRecord::Schema.define(version: 1) do
2
+ create_table :another_polys_holders, force: true do |t|
3
+ t.column :name, :string
4
+ t.column :archival_id, :integer
5
+ t.column :archive_number, :string
6
+ t.column :archived_at, :datetime
7
+ end
8
+
9
+ create_table :archivals, force: true do |t|
10
+ t.column :name, :string
11
+ t.column :archival_id, :integer
12
+ t.column :archive_number, :string
13
+ t.column :archived_at, :datetime
14
+ end
15
+
16
+ create_table :exploders, force: true do |t|
17
+ t.column :archival_id, :integer
18
+ t.column :archive_number, :string
19
+ t.column :archived_at, :datetime
20
+ end
21
+
22
+ create_table :archival_kids, force: true do |t|
23
+ t.column :archival_id, :integer
24
+ t.column :archive_number, :string
25
+ t.column :archived_at, :datetime
26
+ end
27
+
28
+ create_table :archival_grandkids, force: true do |t|
29
+ t.column :archival_kid_id, :integer
30
+ t.column :archive_number, :string
31
+ t.column :archived_at, :datetime
32
+ end
33
+
34
+ create_table :independent_archivals, force: true do |t|
35
+ t.column :name, :string
36
+ t.column :archival_id, :integer
37
+ t.column :archive_number, :string
38
+ t.column :archived_at, :datetime
39
+ end
40
+
41
+ create_table :plains, force: true do |t|
42
+ t.column :name, :string
43
+ t.column :archival_id, :integer
44
+ end
45
+
46
+ create_table :readonly_when_archiveds, force: true do |t|
47
+ t.column :name, :string
48
+ t.column :archive_number, :string
49
+ t.column :archived_at, :datetime
50
+ end
51
+
52
+ create_table :missing_archived_ats, force: true do |t|
53
+ t.column :name, :string
54
+ t.column :archive_number, :string
55
+ end
56
+
57
+ create_table :missing_archive_numbers, force: true do |t|
58
+ t.column :name, :string
59
+ t.column :archived_at, :datetime
60
+ end
61
+
62
+ create_table :polys, force: true do |t|
63
+ t.references :archiveable, polymorphic: true
64
+ t.column :archive_number, :string
65
+ t.column :archived_at, :datetime
66
+ end
67
+
68
+ create_table :legacy, force: true do |t|
69
+ t.column :name, :string
70
+ t.column :archive_number, :string
71
+ t.column :archived_at, :datetime
72
+ end
73
+
74
+ create_table :application_record_rows, force: true do |t|
75
+ t.column :archive_number, :string
76
+ t.column :archived_at, :datetime
77
+ end
78
+
79
+ create_table :callback_archival4s, force: true do |t|
80
+ t.column :settable_field, :string
81
+ t.column :archive_number, :string
82
+ t.column :archived_at, :datetime
83
+ end
84
+
85
+ create_table :callback_archival5s, force: true do |t|
86
+ t.column :settable_field, :string
87
+ t.column :archive_number, :string
88
+ t.column :archived_at, :datetime
89
+ end
90
+
91
+ create_table :deprecated_warning_archivals, force: true do |t|
92
+ t.column :archival_id, :integer
93
+ t.column :archive_number, :string
94
+ t.column :archived_at, :datetime
95
+ end
96
+ end
@@ -0,0 +1,92 @@
1
+ require_relative "test_helper"
2
+
3
+ class ScopeTest < ActiveSupport::TestCase
4
+
5
+ test "simple unarchived scope" do
6
+ Archival.create!
7
+ Archival.create!
8
+
9
+ assert_equal 2, Archival.unarchived.count
10
+ end
11
+
12
+ test "simple archived scope" do
13
+ Archival.create!.archive!
14
+ Archival.create!.archive!
15
+
16
+ assert_equal 2, Archival.archived.count
17
+ end
18
+
19
+ test "mixed scopes" do
20
+ Archival.create!
21
+ Archival.create!.archive!
22
+
23
+ assert_equal 1, Archival.archived.count
24
+ assert_equal 1, Archival.unarchived.count
25
+ end
26
+
27
+ test "simple archived_from_archive_number" do
28
+ archive_number = "TEST-IT"
29
+ Archival.create!.archive!(archive_number)
30
+ Archival.create!.archive!(archive_number)
31
+
32
+ assert_equal 2, Archival.archived_from_archive_number(archive_number).count
33
+ end
34
+
35
+ test "negative archived_from_archive_number" do
36
+ archive_number = "TEST-IT"
37
+ bogus_number = "BROKE-IT"
38
+ Archival.create!.archive!(archive_number)
39
+ Archival.create!.archive!(archive_number)
40
+
41
+ assert_equal 0, Archival.archived_from_archive_number(bogus_number).count
42
+ end
43
+
44
+ test "mixed archived_from_archive_number" do
45
+ archive_number = "TEST-IT"
46
+ Archival.create!.archive!(archive_number)
47
+ Archival.create!.archive!
48
+
49
+ assert_equal 1, Archival.archived_from_archive_number(archive_number).count
50
+ end
51
+
52
+ test "table_name is set to 'legacy'" do
53
+ archived_sql =
54
+ if ActiveRecord.version >= Gem::Version.new("5.2.0")
55
+ "SELECT \"legacy\".* FROM \"legacy\" " \
56
+ 'WHERE "legacy"."archived_at" IS NOT NULL AND "legacy"."archive_number" IS NOT NULL'
57
+ else
58
+ "SELECT \"legacy\".* FROM \"legacy\" " \
59
+ 'WHERE ("legacy"."archived_at" IS NOT NULL) AND ("legacy"."archive_number" IS NOT NULL)'
60
+ end
61
+ unarchived_sql = "SELECT \"legacy\".* FROM \"legacy\" " \
62
+ 'WHERE "legacy"."archived_at" IS NULL AND "legacy"."archive_number" IS NULL'
63
+ assert_equal archived_sql, ArchivalTableName.archived.to_sql
64
+ assert_equal unarchived_sql, ArchivalTableName.unarchived.to_sql
65
+ end
66
+
67
+ test "combines with other scope properly" do
68
+ Archival.create!(name: "Robert")
69
+ Archival.create!(name: "Bobby")
70
+ Archival.create!(name: "Sue")
71
+ bob = Archival.create!(name: "Bob")
72
+ bob.archive!
73
+ assert_equal 3, Archival.bobs.count
74
+ assert_equal 3, Archival.unarchived.count
75
+ assert_equal 2, Archival.bobs.unarchived.count
76
+ assert_equal 2, Archival.unarchived.bobs.count
77
+ assert_equal 1, Archival.bobs.archived.count
78
+ assert_equal 1, Archival.archived.bobs.count
79
+ end
80
+
81
+ test "scopes combine with relations correctly" do
82
+ parent = Archival.create!
83
+ parent.archivals.create!
84
+ parent.archivals.create!
85
+ child = parent.archivals.create!
86
+ child.archive!
87
+ assert_equal 3, parent.archivals.count
88
+ assert_equal 1, parent.archivals.archived.count
89
+ assert_equal 2, parent.archivals.unarchived.count
90
+ end
91
+
92
+ end
@@ -0,0 +1,91 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + "/../lib")
2
+
3
+ require "bundler/setup"
4
+ require "minitest/autorun"
5
+ require "minitest/pride"
6
+
7
+ require "active_record"
8
+ require "database_cleaner"
9
+
10
+ require "archival_record"
11
+
12
+ ActiveSupport::TestCase.test_order = :random if ActiveSupport::TestCase.respond_to?(:test_order=)
13
+
14
+ def prepare_for_tests
15
+ setup_logging
16
+ setup_database_cleaner
17
+ create_test_tables
18
+ require_test_classes
19
+ end
20
+
21
+ def setup_logging
22
+ require "logger"
23
+ logfile = File.dirname(__FILE__) + "/debug.log"
24
+ ActiveRecord::Base.logger = Logger.new(logfile)
25
+ end
26
+
27
+ def setup_database_cleaner
28
+ DatabaseCleaner.strategy = :truncation
29
+ ActiveSupport::TestCase.send(:setup) do
30
+ DatabaseCleaner.clean
31
+ end
32
+ end
33
+
34
+ def sqlite_config
35
+ {
36
+ adapter: "sqlite3",
37
+ database: "archival_record_test.sqlite3",
38
+ pool: 5,
39
+ timeout: 5000
40
+ }
41
+ end
42
+
43
+ def create_test_tables
44
+ schema_file = File.dirname(__FILE__) + "/schema.rb"
45
+ puts "** Loading schema for SQLite"
46
+ ActiveRecord::Base.establish_connection(sqlite_config)
47
+ load(schema_file) if File.exist?(schema_file)
48
+ end
49
+
50
+ BASE_FIXTURE_CLASSES = %I[
51
+ another_polys_holder
52
+ archival
53
+ archival_kid
54
+ archival_grandkid
55
+ archival_table_name
56
+ exploder
57
+ independent_archival
58
+ missing_archived_at
59
+ missing_archive_number
60
+ plain
61
+ poly
62
+ readonly_when_archived
63
+ deprecated_warning_archival
64
+ ].freeze
65
+
66
+ RAILS_4_FIXTURE_CLASSES = %I[
67
+ callback_archival_4
68
+ ].freeze
69
+
70
+ RAILS_5_FIXTURE_CLASSES = %I[
71
+ application_record
72
+ application_record_row
73
+ callback_archival_5
74
+ ].freeze
75
+
76
+ def require_test_classes
77
+ ActiveSupport::Inflector.inflections do |inflect|
78
+ inflect.irregular "poly", "polys"
79
+ end
80
+
81
+ fixtures = if ActiveRecord::VERSION::MAJOR >= 4
82
+ RAILS_5_FIXTURE_CLASSES
83
+ else
84
+ RAILS_4_FIXTURE_CLASSES
85
+ end
86
+
87
+ fixtures += BASE_FIXTURE_CLASSES
88
+ fixtures.each { |test_class_file| require_relative "fixtures/#{test_class_file}" }
89
+ end
90
+
91
+ prepare_for_tests