archival_record 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
+ #!/bin/sh
2
+ set -e
3
+ cd "`dirname \"$0\"`/.."
4
+
5
+ echo "\n---=== Bundling ===---"
6
+ bundle install
7
+
8
+ echo "\n---=== Setting up various rails versions for testing ===---"
9
+ bundle exec appraisal install
@@ -0,0 +1,16 @@
1
+ require_relative "test_helper"
2
+
3
+ class AmbiguousTableTest < ActiveSupport::TestCase
4
+
5
+ test "no ambiguous table problem" do
6
+ archival = Archival.create!
7
+ child = archival.archivals.create!
8
+ child.archive!
9
+
10
+ # this is a bug fix for a problem wherein table names weren't being
11
+ # namespaced, so if a table joined against itself, incorrect SQL was
12
+ # generated
13
+ assert_equal 1, Archival.unarchived.joins(:archivals).count
14
+ end
15
+
16
+ end
@@ -0,0 +1,20 @@
1
+ require_relative "test_helper"
2
+
3
+ # Rails 5 introduced a new base class, and this is gonna test that
4
+ if defined?(ApplicationRecord)
5
+ class ApplicationRecordTest < ActiveSupport::TestCase
6
+
7
+ test "archive archives the record" do
8
+ archival = ApplicationRecordRow.create!
9
+ archival.archive!
10
+ assert archival.reload.archived?
11
+ end
12
+
13
+ test "unarchive unarchives archival records" do
14
+ archival = ApplicationRecordRow.create!(archived_at: Time.now, archive_number: 1)
15
+ archival.unarchive!
16
+ assert_not archival.reload.archived?
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,104 @@
1
+ require_relative "test_helper"
2
+
3
+ class AssociationsTest < ActiveSupport::TestCase
4
+
5
+ test "archive archives 'has_' associated archival objects that are dependent destroy" do
6
+ archival = Archival.create!
7
+ child = archival.archivals.create!
8
+ archival.archive!
9
+
10
+ assert archival.reload.archived?
11
+ assert child.reload.archived?
12
+ end
13
+
14
+ test "archive acts on all objects in the 'has_' relationship" do
15
+ archival = Archival.create!
16
+ children = [archival.archivals.create!, archival.archivals.create!]
17
+ archival.archive!
18
+
19
+ assert archival.reload.archived?
20
+ assert children.map(&:reload).all?(&:archived?)
21
+ end
22
+
23
+ test "archive does not act on already archived objects" do
24
+ archival = Archival.create!
25
+ archival.archivals.create!
26
+ prearchived_child = archival.archivals.create!
27
+ prearchived_child.archive!
28
+ archival.archive!
29
+
30
+ assert_not_equal archival.archive_number, prearchived_child.reload.archive_number
31
+ end
32
+
33
+ test "archive does not archive 'has_' associated archival objects that are not dependent destroy" do
34
+ archival = Archival.create!
35
+ non_dependent_child = archival.independent_archivals.create!
36
+ archival.archive!
37
+
38
+ assert archival.reload.archived?
39
+ assert_not non_dependent_child.reload.archived?
40
+ end
41
+
42
+ test "archive doesn't do anything to associated dependent destroy models that are non-archival" do
43
+ archival = Archival.create!
44
+ plain = archival.plains.create!
45
+ archival.archive!
46
+
47
+ assert archival.archived?
48
+ assert plain.reload
49
+ end
50
+
51
+ test "archive sets the object hierarchy to all have the same archive_number" do
52
+ archival = Archival.create!
53
+ child = archival.archivals.create!
54
+ archival.archive!
55
+ expected_digest = Digest::MD5.hexdigest("Archival#{archival.id}")
56
+
57
+ assert_equal expected_digest, archival.archive_number
58
+ assert_equal expected_digest, child.reload.archive_number
59
+ end
60
+
61
+ test "unarchive acts on child objects" do
62
+ archival = Archival.create!
63
+ child = archival.archivals.create!
64
+ archival.archive!
65
+ archival.unarchive!
66
+
67
+ assert_not archival.archived?
68
+ assert_not child.reload.archived?
69
+ end
70
+
71
+ test "unarchive does not act on already archived objects" do
72
+ archival = Archival.create!
73
+ child = archival.archivals.create!
74
+ prearchived_child = archival.archivals.create!
75
+ prearchived_child.archive!
76
+ archival.archive!
77
+ archival.unarchive!
78
+
79
+ assert_not archival.archived?
80
+ assert_not child.reload.archived?
81
+ assert prearchived_child.reload.archived?
82
+ end
83
+
84
+ test "unarchive acts on 'has_' associated non-dependent_destroy objects" do
85
+ archival = Archival.create!
86
+ independent = archival.independent_archivals.create!
87
+ archival.archive!
88
+ independent.archive!(archival.archive_number)
89
+ archival.unarchive!
90
+
91
+ assert_not archival.reload.archived?
92
+ assert_not independent.reload.archived?
93
+ end
94
+
95
+ test "unarchive doesn't unarchive associated objects if the head object is already unarchived" do
96
+ archival = Archival.create!
97
+ prearchived_child = archival.archivals.create!
98
+ prearchived_child.archive!
99
+ archival.unarchive!
100
+
101
+ assert prearchived_child.reload.archived?
102
+ end
103
+
104
+ end
@@ -0,0 +1,66 @@
1
+ require_relative "test_helper"
2
+
3
+ class BasicTest < ActiveSupport::TestCase
4
+
5
+ test "archive archives the record" do
6
+ archival = Archival.create!
7
+ archival.archive!
8
+ assert_equal true, archival.reload.archived?
9
+ end
10
+
11
+ test "unarchive unarchives archival records" do
12
+ archival = Archival.create!(archived_at: Time.now, archive_number: 1)
13
+ archival.unarchive!
14
+ assert_equal false, archival.reload.archived?
15
+ end
16
+
17
+ test "archive returns true on success" do
18
+ normal = Archival.create!
19
+ assert_equal true, normal.archive!
20
+ end
21
+
22
+ test "archive returns false on failure" do
23
+ readonly = Archival.create!
24
+ readonly.readonly!
25
+ assert_equal false, readonly.archive!
26
+ end
27
+
28
+ test "unarchive returns true on success" do
29
+ normal = Archival.create!(archived_at: Time.now, archive_number: "1")
30
+ assert_equal true, normal.unarchive!
31
+ end
32
+
33
+ test "unarchive returns false on failure" do
34
+ readonly = Archival.create!(archived_at: Time.now, archive_number: "1")
35
+ readonly.readonly!
36
+ assert_equal false, readonly.unarchive!
37
+ end
38
+
39
+ test "archive sets archived_at to the time of archiving" do
40
+ archival = Archival.create!
41
+ before = DateTime.now
42
+ sleep(0.001)
43
+ archival.archive!
44
+ sleep(0.001)
45
+ after = DateTime.now
46
+ assert before < archival.archived_at.to_datetime
47
+ assert after > archival.archived_at.to_datetime
48
+ end
49
+
50
+ test "archive sets the archive number to the md5 hexdigest for the model and id that is archived" do
51
+ archival = Archival.create!
52
+ archival.archive!
53
+ expected_digest = Digest::MD5.hexdigest("#{archival.class.name}#{archival.id}")
54
+ assert_equal expected_digest, archival.archive_number
55
+ end
56
+
57
+ test "archive on archived object doesn't alter the archive_number" do
58
+ archived = Archival.create
59
+ archived.archive!
60
+ initial_number = archived.archive_number
61
+ archived.reload.archive!
62
+ second_number = archived.archive_number
63
+ assert_equal initial_number, second_number
64
+ end
65
+
66
+ end
@@ -0,0 +1,41 @@
1
+ require_relative "test_helper"
2
+
3
+ class CallbacksTest < ActiveSupport::TestCase
4
+
5
+ if defined?(ApplicationRecord)
6
+ test "can set a value as part of archiving" do
7
+ archival = CallbackArchival5.create
8
+ archival.set_this_value = "a test string"
9
+ assert_nil archival.settable_field
10
+ archival.archive!
11
+ assert_equal "a test string", archival.reload.settable_field
12
+ end
13
+
14
+ test "can be halted" do
15
+ archival = CallbackArchival5.create
16
+ archival.set_this_value = "a test string"
17
+ archival.pass_callback = false
18
+ assert_nil archival.settable_field
19
+ archival.archive!
20
+ assert_nil archival.reload.settable_field
21
+ end
22
+ else
23
+ test "can set a value as part of archiving" do
24
+ archival = CallbackArchival4.create
25
+ archival.set_this_value = "a test string"
26
+ assert_nil archival.settable_field
27
+ archival.archive!
28
+ assert_equal "a test string", archival.reload.settable_field
29
+ end
30
+
31
+ test "can be halted" do
32
+ archival = CallbackArchival4.create
33
+ archival.set_this_value = "a test string"
34
+ archival.pass_callback = false
35
+ assert_nil archival.settable_field
36
+ archival.archive!
37
+ assert_nil archival.reload.settable_field
38
+ end
39
+ end
40
+
41
+ end
@@ -0,0 +1,17 @@
1
+ require_relative "test_helper"
2
+
3
+ class ColumnTest < ActiveSupport::TestCase
4
+
5
+ test "archival_record raises during create if missing archived_at column" do
6
+ assert_raises(ArchivalRecordCore::ArchivalRecord::MissingArchivalColumnError) do
7
+ MissingArchivedAt.create!(name: "foo-foo")
8
+ end
9
+ end
10
+
11
+ test "archival_record raises during create if missing archive_number column" do
12
+ assert_raises(ArchivalRecordCore::ArchivalRecord::MissingArchivalColumnError) do
13
+ MissingArchiveNumber.create!(name: "rover")
14
+ end
15
+ end
16
+
17
+ end
@@ -0,0 +1,35 @@
1
+ require_relative "test_helper"
2
+
3
+ class DeepNestingTest < ActiveSupport::TestCase
4
+
5
+ test "archiving deeply nested items" do
6
+ archival = Archival.create!
7
+ child = archival.archivals.create!
8
+ grandchild = child.archivals.create!
9
+
10
+ archival.archive!
11
+
12
+ assert archival.reload.archived?
13
+ assert child.reload.archived?
14
+ assert grandchild.reload.archived?
15
+ assert_equal archival.archive_number, child.archive_number
16
+ assert_equal archival.archive_number, grandchild.archive_number
17
+ end
18
+
19
+ test "unarchiving deeply nested items doesn't blow up" do
20
+ archival_attributes = {
21
+ archived_at: Time.now,
22
+ archive_number: "test"
23
+ }
24
+ archival = Archival.create!(archival_attributes)
25
+ child = archival.archivals.create!(archival_attributes)
26
+ grandchild = child.archivals.create!(archival_attributes)
27
+
28
+ archival.unarchive!
29
+
30
+ assert_not archival.reload.archived?
31
+ assert_not child.reload.archived?
32
+ assert_not grandchild.reload.archived?
33
+ end
34
+
35
+ end
@@ -0,0 +1,11 @@
1
+ require_relative "test_helper"
2
+
3
+ class DeprecatedWarningArchivalTest < ActiveSupport::TestCase
4
+
5
+ test "models with 'acts_as_archival' instead of 'archival_record' can still archive a record" do
6
+ archival = DeprecatedWarningArchival.create!
7
+ archival.archive!
8
+ assert_equal true, archival.reload.archived?
9
+ end
10
+
11
+ end
@@ -0,0 +1,11 @@
1
+ # name - string
2
+ # archival_id - integer
3
+ # archive_number - string
4
+ # archived_at - datetime
5
+ class AnotherPolysHolder < ActiveRecord::Base
6
+
7
+ archival_record
8
+
9
+ has_many :polys, dependent: :destroy, as: :archiveable
10
+
11
+ end
@@ -0,0 +1,5 @@
1
+ class ApplicationRecord < ActiveRecord::Base
2
+
3
+ self.abstract_class = true
4
+
5
+ end
@@ -0,0 +1,8 @@
1
+ # Rails 5 introduced a new base class, and this is gonna be used in the tests of that
2
+ if defined?(ApplicationRecord)
3
+ class ApplicationRecordRow < ApplicationRecord
4
+
5
+ archival_record
6
+
7
+ end
8
+ end
@@ -0,0 +1,19 @@
1
+ # name - string
2
+ # archival_id - integer
3
+ # archive_number - string
4
+ # archived_at - datetime
5
+ class Archival < ActiveRecord::Base
6
+
7
+ archival_record
8
+
9
+ has_many :archivals, dependent: :destroy
10
+ has_many :archival_kids, dependent: :destroy
11
+ has_many :archival_grandkids, dependent: :destroy, through: :archival_kids
12
+ has_many :exploders, dependent: :destroy
13
+ has_many :plains, dependent: :destroy
14
+ has_many :polys, dependent: :destroy, as: :archiveable
15
+ has_many :independent_archivals
16
+
17
+ scope :bobs, -> { where(name: %w[Bob Bobby Robert]) }
18
+
19
+ end
@@ -0,0 +1,10 @@
1
+ # archival_kid_id - integer
2
+ # archive_number - string
3
+ # archived_at - datetime
4
+ class ArchivalGrandkid < ActiveRecord::Base
5
+
6
+ archival_record
7
+
8
+ belongs_to :archival_kid
9
+
10
+ end
@@ -0,0 +1,11 @@
1
+ # archival_id - integer
2
+ # archive_number - string
3
+ # archived_at - datetime
4
+ class ArchivalKid < ActiveRecord::Base
5
+
6
+ archival_record
7
+
8
+ belongs_to :archival
9
+ has_many :archival_grandkids, dependent: :destroy
10
+
11
+ end
@@ -0,0 +1,10 @@
1
+ # name - string
2
+ # archive_number - string
3
+ # archived_at - datetime
4
+ class ArchivalTableName < ActiveRecord::Base
5
+
6
+ self.table_name = "legacy"
7
+
8
+ archival_record
9
+
10
+ end
@@ -0,0 +1,19 @@
1
+ class CallbackArchival4 < ActiveRecord::Base
2
+
3
+ archival_record
4
+
5
+ attr_accessor :set_this_value,
6
+ :pass_callback
7
+
8
+ before_archive :set_value,
9
+ :conditional_callback_passer
10
+
11
+ private def set_value
12
+ self.settable_field = set_this_value
13
+ end
14
+
15
+ private def conditional_callback_passer
16
+ pass_callback || pass_callback.nil?
17
+ end
18
+
19
+ end
@@ -0,0 +1,23 @@
1
+ # necessary for ApplicationRecord
2
+ if defined?(ApplicationRecord)
3
+ class CallbackArchival5 < ApplicationRecord
4
+
5
+ archival_record
6
+
7
+ attr_accessor :set_this_value,
8
+ :pass_callback
9
+
10
+ before_archive :set_value,
11
+ :conditional_callback_passer
12
+
13
+ private def set_value
14
+ self.settable_field = set_this_value
15
+ end
16
+
17
+ private def conditional_callback_passer
18
+ # we want to throw only for the value false
19
+ throw(:abort) unless pass_callback || pass_callback.nil?
20
+ end
21
+
22
+ end
23
+ end