acts_as_archival 1.1.1 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +81 -0
  3. data/.rubocop_todo.yml +7 -0
  4. data/.travis.yml +34 -0
  5. data/Appraisals +5 -2
  6. data/CHANGELOG.md +8 -0
  7. data/README.md +14 -7
  8. data/Rakefile +6 -3
  9. data/acts_as_archival.gemspec +3 -4
  10. data/gemfiles/rails_4.1.gemfile +0 -1
  11. data/gemfiles/rails_5.0.gemfile +1 -1
  12. data/gemfiles/rails_5.1.beta.gemfile +7 -0
  13. data/lib/acts_as_archival/version.rb +3 -1
  14. data/lib/expected_behavior/acts_as_archival.rb +115 -77
  15. data/lib/expected_behavior/acts_as_archival_active_record_methods.rb +22 -2
  16. data/lib/expected_behavior/association_operation/base.rb +7 -8
  17. data/lib/expected_behavior/association_operation/unarchive.rb +1 -1
  18. data/script/setup +0 -3
  19. data/test/ambiguous_table_test.rb +2 -0
  20. data/test/application_record_test.rb +3 -1
  21. data/test/associations_test.rb +2 -0
  22. data/test/basic_test.rb +6 -4
  23. data/test/callbacks_test.rb +4 -2
  24. data/test/column_test.rb +8 -6
  25. data/test/deep_nesting_test.rb +4 -2
  26. data/test/fixtures/application_record.rb +2 -0
  27. data/test/fixtures/application_record_row.rb +2 -0
  28. data/test/fixtures/archival.rb +9 -7
  29. data/test/fixtures/archival_grandkid.rb +2 -0
  30. data/test/fixtures/archival_kid.rb +3 -1
  31. data/test/fixtures/archival_table_name.rb +2 -0
  32. data/test/fixtures/callback_archival_4.rb +2 -0
  33. data/test/fixtures/callback_archival_5.rb +4 -1
  34. data/test/fixtures/exploder.rb +2 -0
  35. data/test/fixtures/independent_archival.rb +2 -0
  36. data/test/fixtures/missing_archive_number.rb +2 -0
  37. data/test/fixtures/missing_archived_at.rb +2 -0
  38. data/test/fixtures/plain.rb +2 -0
  39. data/test/fixtures/poly.rb +3 -1
  40. data/test/fixtures/readonly_when_archived.rb +3 -1
  41. data/test/polymorphic_test.rb +4 -2
  42. data/test/readonly_when_archived_test.rb +4 -2
  43. data/test/responds_test.rb +22 -4
  44. data/test/schema.rb +59 -79
  45. data/test/scope_test.rb +10 -6
  46. data/test/test_helper.rb +46 -40
  47. data/test/through_association_test.rb +3 -1
  48. data/test/transaction_test.rb +2 -53
  49. metadata +16 -41
  50. data/script/db_setup +0 -51
  51. data/test/database.yml +0 -26
  52. data/test/fixtures/mass_attribute_protected.rb +0 -7
  53. data/test/fixtures/mysql_archival.rb +0 -10
  54. data/test/fixtures/mysql_exploder.rb +0 -9
  55. data/test/fixtures/pg_archival.rb +0 -10
  56. data/test/fixtures/pg_exploder.rb +0 -9
  57. data/test/mass_attribute_test.rb +0 -20
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6a53308c0484db785c8114be2103ada7b0844fe2
4
- data.tar.gz: c52734e4fa86de33fcdfc162cb40ac21b99bedcd
3
+ metadata.gz: e65cd1c6413e55892031258572cc4ca7e9730cd2
4
+ data.tar.gz: 671ceee75185386dd88546f5d31415005cba818b
5
5
  SHA512:
6
- metadata.gz: 414a8242172fa875dbe4c2387103e4e48461894271b0dd49487ab8397301261ea1da012435c63fec2056138646df5b0d74a7eb9fb5f429083aa389081989c09e
7
- data.tar.gz: be3195952d4aa822ee9cfa73fa80e521d7607728dd8fca65f246177329bde01fb6d6c54b540d49e05d78130c7cdb7daee0579f8849ec9eed67b0b410cc0ee318
6
+ metadata.gz: ebc7ccc3c16ca1f0b13361e5c94763ef57ebc4399061bacadb4c1fbff032da8ab7f5e29dca1cc8f4241f7ebf00f797ad890ae29246dd19e5d5bfb9efd4e7936f
7
+ data.tar.gz: f6966a53472207bc16ca83b6e2c5cd990b8200249c0780abd85e1fe19682d9c77c27dcd89014d0b1bc561f6ee1ad4856bdd93c8fb5f171155b5dae34f548132a
data/.rubocop.yml ADDED
@@ -0,0 +1,81 @@
1
+ inherit_from: .rubocop_todo.yml
2
+
3
+ AllCops:
4
+ Exclude:
5
+ - vendor/**/*
6
+ - gemfiles/**/*
7
+
8
+
9
+ ################
10
+ # Code Metrics #
11
+ ################
12
+ Metrics/BlockLength:
13
+ Exclude:
14
+ - 'test/schema.rb'
15
+ - '*.gemspec'
16
+
17
+ Metrics/AbcSize:
18
+ Max: 25
19
+
20
+ Metrics/LineLength:
21
+ Max: 140
22
+
23
+ Metrics/MethodLength:
24
+ Max: 10
25
+ CountComments: false
26
+
27
+
28
+ ###############
29
+ # Style Rules #
30
+ ###############
31
+ Style/Alias:
32
+ EnforcedStyle: prefer_alias_method
33
+
34
+ # ¯\_(ツ)_/¯
35
+ # ʕノ•ᴥ•ʔノ ︵ ┻━┻
36
+ # ( ͡° ͜ʖ ͡°)
37
+ Style/AsciiComments:
38
+ Enabled: false
39
+
40
+ Style/Documentation:
41
+ Enabled: false
42
+
43
+ Style/DoubleNegation:
44
+ Enabled: false
45
+
46
+ Style/EmptyLinesAroundClassBody:
47
+ EnforcedStyle: empty_lines_except_namespace
48
+
49
+ Style/EmptyLinesAroundModuleBody:
50
+ EnforcedStyle: empty_lines_except_namespace
51
+
52
+ Style/FrozenStringLiteralComment:
53
+ EnforcedStyle: never
54
+
55
+ Style/HashSyntax:
56
+ EnforcedStyle: ruby19
57
+
58
+ # TODO: replace the [] below with default once a new version of
59
+ # rubocop comes out, since there is a PR for it:
60
+ # https://github.com/bbatsov/rubocop/pull/4038
61
+ Style/PercentLiteralDelimiters:
62
+ PreferredDelimiters:
63
+ '%': '{}'
64
+ '%i': '[]'
65
+ '%I': '[]'
66
+ '%q': '{}'
67
+ '%Q': '{}'
68
+ '%r': '{}'
69
+ '%s': '[]'
70
+ '%w': '[]'
71
+ '%W': '[]'
72
+ '%x': '[]'
73
+
74
+ Style/RaiseArgs:
75
+ EnforcedStyle: compact
76
+
77
+ Style/SpaceInsideHashLiteralBraces:
78
+ EnforcedStyle: space
79
+
80
+ Style/StringLiterals:
81
+ EnforcedStyle: double_quotes
data/.rubocop_todo.yml ADDED
@@ -0,0 +1,7 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2017-03-19 11:19:20 -0400 using RuboCop version 0.47.1.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
data/.travis.yml ADDED
@@ -0,0 +1,34 @@
1
+ language: ruby
2
+ sudo: false
3
+ dist: trusty
4
+ cache: bundler
5
+ script: "bundle exec rake"
6
+
7
+ rvm:
8
+ - 2.1.10
9
+ - 2.2.6
10
+ - 2.3.3
11
+ - 2.4.0
12
+
13
+ gemfile:
14
+ - gemfiles/rails_4.1.gemfile
15
+ - gemfiles/rails_4.2.gemfile
16
+ - gemfiles/rails_5.0.gemfile
17
+ - gemfiles/rails_5.1.beta.gemfile
18
+
19
+ before_install:
20
+ - gem update --system
21
+ - gem update bundler
22
+ - gem cleanup bundler
23
+
24
+ matrix:
25
+ fast_finish: true
26
+ allow_failures:
27
+ - gemfile: gemfiles/rails_5.1.beta.gemfile
28
+ exclude:
29
+ - rvm: 2.1.10
30
+ gemfile: gemfiles/rails_5.0.gemfile
31
+ - rvm: 2.1.10
32
+ gemfile: gemfiles/rails_5.1.beta.gemfile
33
+ - rvm: 2.4.0
34
+ gemfile: gemfiles/rails_4.1.gemfile
data/Appraisals CHANGED
@@ -1,6 +1,5 @@
1
1
  appraise "rails-4.1" do
2
2
  gem "rails", "~> 4.1.0"
3
- gem "mysql2", ">= 0.3.13", "< 0.4"
4
3
  end
5
4
 
6
5
  appraise "rails-4.2" do
@@ -8,5 +7,9 @@ appraise "rails-4.2" do
8
7
  end
9
8
 
10
9
  appraise "rails-5.0" do
11
- gem "rails", "~> 5.0.0.beta3"
10
+ gem "rails", "~> 5.0", ">= 5.0.2"
11
+ end
12
+
13
+ appraise "rails-5.1.beta" do
14
+ gem 'rails', '~> 5.1.0.beta1'
12
15
  end
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 1.2.0 - March 19, 2017
4
+ * **BREAKING CHANGE** the utility instance and class method `is_archival?` is now `archival?`. `is_archival?` is deprecated and will be removed
5
+ * hard dependency on rails 4.1+ – this shouldn't break anything since it was de facto before, but worth mentioning
6
+ * minor refactoring through most code
7
+ * much work done to make automatic checks worthwhile (travis/rubocop)
8
+ * general test cleanup
9
+ * drop hard dependency on mysql and postresql in tests
10
+
3
11
  ## 1.1.1 - April 10, 2016
4
12
  * Update the way the `::unarchived` scope is generated using `::not` instead of manually building SQL, which should be better for complex queries
5
13
 
data/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # ActsAsArchival
2
2
 
3
+ [![Build Status](https://travis-ci.org/expectedbehavior/acts_as_archival.svg?branch=master)](https://travis-ci.org/expectedbehavior/acts_as_archival)
4
+ [![Gem Version](https://badge.fury.io/rb/acts_as_archival.svg)](https://badge.fury.io/rb/acts_as_archival)
5
+
3
6
  Atomically archive object trees in your activerecord models.
4
7
 
5
8
  We had the problem that acts_as_paranoid and similar plugins/gems
@@ -68,11 +71,11 @@ h = Hole.create #
68
71
  r = h.rats.create #
69
72
  h.archive # => true
70
73
  h.archive_number # => "b56876de48a5dcfe71b2c13eec15e4a2"
71
- r.archive_number # => "b56876de48a5dcfe71b2c13eec15e4a2"
74
+ r.archived_at # => Thu, 01 Jan 2012 01:52:12 -0400
72
75
  r.archived? # => true
73
76
  h.unarchive # => true
74
77
  h.archive_number # => nil
75
- r.archive_number # => nil
78
+ r.archived_at # => nil
76
79
  r.archived? # => false
77
80
  ```
78
81
 
@@ -91,8 +94,10 @@ Hole.unarchived.size # => 0
91
94
 
92
95
  ``` ruby
93
96
  h = Hole.create #
94
- h.is_archival? # => true
95
- Hole.is_archival? # => true
97
+ h.archival? # => true
98
+ h.is_archival? # => true # deprecated
99
+ Hole.archival? # => true
100
+ Hole.is_archival? # => true # deprecated
96
101
  ```
97
102
 
98
103
  ### Options
@@ -127,7 +132,7 @@ class Hole < ActiveRecord::Base
127
132
 
128
133
  before_unarchive :some_method_before_unarchiving
129
134
 
130
- after_unarchive :some_method_before_unarchiving
135
+ after_unarchive :some_method_after_unarchiving
131
136
 
132
137
  # ... implement those methods
133
138
  end
@@ -142,7 +147,7 @@ end
142
147
 
143
148
  1. This will only work on associations that are dependent destroy. It
144
149
  should be trival to change that or make it optional.
145
- 1. If you would like to work on this, you will need to setup sqlite, postgres, and mysql on your development machine. Alternately, you can disable specific dev dependencies in the gemspec and test_helper and ask for help.
150
+ 1. If you would like to work on this, you will need to setup sqlite on your development machine. Alternately, you can disable specific dev dependencies in the gemspec and test_helper and ask for help.
146
151
 
147
152
  ## Testing
148
153
 
@@ -178,8 +183,10 @@ ActsAsParanoid and PermanentRecords were both inspirations for this:
178
183
  * Miles Sterrett
179
184
  * James Hill
180
185
  * Maarten Claes
186
+ * Anthony Panozzo
181
187
  * Aaron Milam
188
+ * Anton Rieder
182
189
 
183
190
  Thanks!
184
191
 
185
- *Copyright (c) 2009-2016 Expected Behavior, LLC, released under the MIT license*
192
+ *Copyright (c) 2009-2017 Expected Behavior, LLC, released under the MIT license*
data/Rakefile CHANGED
@@ -1,13 +1,16 @@
1
1
  #!/usr/bin/env rake
2
2
  require "bundler/gem_tasks"
3
3
  require "rake/testtask"
4
+ require "rubocop/rake_task"
4
5
 
5
- desc "Default: run unit tests."
6
- task :default => :test
6
+ RuboCop::RakeTask.new
7
+
8
+ desc "Default: run all available test suites."
9
+ task default: [:rubocop, :test]
7
10
 
8
11
  desc "Test the acts_as_archival plugin."
9
12
  Rake::TestTask.new(:test) do |t|
10
- t.libs << "test"
13
+ t.libs << "test"
11
14
  t.pattern = "test/**/*_test.rb"
12
15
  t.verbose = true
13
16
  end
@@ -4,7 +4,7 @@ require "acts_as_archival/version"
4
4
 
5
5
  Gem::Specification.new do |gem|
6
6
  gem.name = "acts_as_archival"
7
- gem.summary = %q{Atomic archiving/unarchiving for ActiveRecord-based apps}
7
+ gem.summary = "Atomic archiving/unarchiving for ActiveRecord-based apps"
8
8
  gem.version = ActsAsArchival::VERSION
9
9
  gem.authors = ["Joel Meador",
10
10
  "Michael Kuehl",
@@ -25,16 +25,15 @@ Gem::Specification.new do |gem|
25
25
  gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
26
26
  gem.require_paths = ["lib"]
27
27
 
28
- gem.add_dependency "activerecord"
28
+ gem.add_dependency "activerecord", ">= 4.1"
29
29
 
30
30
  gem.add_development_dependency "appraisal"
31
31
  gem.add_development_dependency "assertions-eb"
32
32
  gem.add_development_dependency "database_cleaner"
33
- gem.add_development_dependency "mysql2"
34
- gem.add_development_dependency "pg"
35
33
  gem.add_development_dependency "rake"
36
34
  gem.add_development_dependency "rr"
37
35
  gem.add_development_dependency "sqlite3"
36
+ gem.add_development_dependency "rubocop", "~> 0.47.1"
38
37
 
39
38
  gem.description = <<-END
40
39
  *Atomic archiving/unarchiving for ActiveRecord-based apps*
@@ -3,6 +3,5 @@
3
3
  source "https://rubygems.org"
4
4
 
5
5
  gem "rails", "~> 4.1.0"
6
- gem "mysql2", ">= 0.3.13", "< 0.4"
7
6
 
8
7
  gemspec :path => "../"
@@ -2,6 +2,6 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "rails", "~> 5.0.0.beta3"
5
+ gem "rails", "~> 5.0", ">= 5.0.2"
6
6
 
7
7
  gemspec :path => "../"
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "~> 5.1.0.beta1"
6
+
7
+ gemspec :path => "../"
@@ -1,3 +1,5 @@
1
1
  module ActsAsArchival
2
- VERSION = "1.1.1"
2
+
3
+ VERSION = "1.2.0".freeze
4
+
3
5
  end
@@ -1,113 +1,131 @@
1
1
  module ExpectedBehavior
2
2
  module ActsAsArchival
3
- require 'digest/md5'
4
3
 
5
- MissingArchivalColumnError = Class.new(ActiveRecord::ActiveRecordError) unless defined?(MissingArchivalColumnError) == 'constant' && MissingArchivalColumnError.class == Class
6
- CouldNotArchiveError = Class.new(ActiveRecord::ActiveRecordError) unless defined?(CouldNotArchiveError) == 'constant' && CouldNotArchiveError.class == Class
7
- CouldNotUnarchiveError = Class.new(ActiveRecord::ActiveRecordError) unless defined?(CouldNotUnarchiveError) == 'constant' && CouldNotUnarchiveError.class == Class
4
+ require "digest/md5"
5
+
6
+ unless defined?(MissingArchivalColumnError) == "constant" && MissingArchivalColumnError.class == Class
7
+ MissingArchivalColumnError = Class.new(ActiveRecord::ActiveRecordError)
8
+ end
9
+ unless defined?(CouldNotArchiveError) == "constant" && CouldNotArchiveError.class == Class
10
+ CouldNotArchiveError = Class.new(ActiveRecord::ActiveRecordError)
11
+ end
12
+ unless defined?(CouldNotUnarchiveError) == "constant" && CouldNotUnarchiveError.class == Class
13
+ CouldNotUnarchiveError = Class.new(ActiveRecord::ActiveRecordError)
14
+ end
8
15
 
9
16
  def self.included(base)
10
17
  base.extend ActMethods
11
18
  end
12
19
 
13
20
  module ActMethods
14
- def acts_as_archival(options = { })
15
- unless included_modules.include? InstanceMethods
16
- include InstanceMethods
17
-
18
- before_validation :raise_if_not_archival
19
- validate :readonly_when_archived if options[:readonly_when_archived]
20
-
21
- scope :archived, lambda { where.not(:archived_at => nil, :archive_number => nil) }
22
- scope :unarchived, lambda { where(:archived_at => nil, :archive_number => nil) }
23
- scope :archived_from_archive_number, lambda { |head_archive_number| where(['archived_at IS NOT NULL AND archive_number = ?', head_archive_number]) }
24
-
25
- callbacks = ['archive','unarchive']
26
- if ActiveSupport::VERSION::STRING >= '5'
27
- define_callbacks(*[callbacks].flatten)
28
- elsif ActiveSupport::VERSION::STRING >= '4'
29
- define_callbacks(*[callbacks, {:terminator => -> (_, result) { result == false }}].flatten)
30
- end
31
- callbacks.each do |callback|
32
- eval <<-end_callbacks
33
- unless defined?(before_#{callback})
34
- def before_#{callback}(*args, &blk)
35
- set_callback(:#{callback}, :before, *args, &blk)
36
- end
37
- end
38
- unless defined?(after_#{callback})
39
- def after_#{callback}(*args, &blk)
40
- set_callback(:#{callback}, :after, *args, &blk)
41
- end
42
- end
43
- end_callbacks
21
+
22
+ def acts_as_archival(options = {})
23
+ return if included_modules.include?(InstanceMethods)
24
+
25
+ include InstanceMethods
26
+
27
+ setup_validations(options)
28
+
29
+ setup_scopes
30
+
31
+ setup_callbacks
32
+ end
33
+
34
+ private def setup_validations(options)
35
+ before_validation :raise_if_not_archival
36
+ validate :readonly_when_archived if options[:readonly_when_archived]
37
+ end
38
+
39
+ private def setup_scopes
40
+ scope :archived, -> { where.not(archived_at: nil, archive_number: nil) }
41
+ scope :unarchived, -> { where(archived_at: nil, archive_number: nil) }
42
+ scope :archived_from_archive_number, (lambda do |head_archive_number|
43
+ where(["archived_at IS NOT NULL AND archive_number = ?", head_archive_number])
44
+ end)
45
+ end
46
+
47
+ private def setup_callbacks
48
+ callbackable_actions = %w[archive unarchive]
49
+
50
+ setup_activerecord_callbacks(callbackable_actions)
51
+
52
+ define_callback_dsl_methods(callbackable_actions)
53
+ end
54
+
55
+ private def setup_activerecord_callbacks(callbackable_actions)
56
+ if ActiveSupport::VERSION::MAJOR >= 5
57
+ define_callbacks(*[callbackable_actions].flatten)
58
+ elsif ActiveSupport::VERSION::MAJOR >= 4
59
+ define_callbacks(*[callbackable_actions, { terminator: ->(_, result) { result == false } }].flatten)
60
+ end
61
+ end
62
+
63
+ private def define_callback_dsl_methods(callbackable_actions)
64
+ callbackable_actions.each do |action|
65
+ %w[before after].each do |callbackable_type|
66
+ define_callback_dsl_method(callbackable_type, action)
44
67
  end
45
68
  end
46
69
  end
47
70
 
71
+ private def define_callback_dsl_method(callbackable_type, action)
72
+ # rubocop:disable Security/Eval
73
+ eval <<-end_callbacks
74
+ unless defined?(#{callbackable_type}_#{action})
75
+ def #{callbackable_type}_#{action}(*args, &blk)
76
+ set_callback(:#{action}, :#{callbackable_type}, *args, &blk)
77
+ end
78
+ end
79
+ end_callbacks
80
+ # rubocop:enable Security/Eval
81
+ end
82
+
48
83
  end
49
84
 
50
85
  module InstanceMethods
51
86
 
52
87
  def readonly_when_archived
53
- if self.archived? && self.changed? && !self.archived_at_changed? && !self.archive_number_changed?
54
- self.errors.add(:base, "Cannot modify an archived record.")
55
- end
88
+ readonly_attributes_changed = archived? && changed? && !archived_at_changed? && !archive_number_changed?
89
+ return unless readonly_attributes_changed
90
+
91
+ errors.add(:base, "Cannot modify an archived record.")
56
92
  end
57
93
 
58
94
  def raise_if_not_archival
59
95
  missing_columns = []
60
- missing_columns << "archive_number" unless self.respond_to?(:archive_number)
61
- missing_columns << "archived_at" unless self.respond_to?(:archived_at)
62
- raise MissingArchivalColumnError.new("Add '#{missing_columns.join "', '"}' column(s) to '#{self.class.name}' to make it archival") unless missing_columns.blank?
96
+ missing_columns << "archive_number" unless respond_to?(:archive_number)
97
+ missing_columns << "archived_at" unless respond_to?(:archived_at)
98
+ return if missing_columns.blank?
99
+
100
+ raise MissingArchivalColumnError.new("Add '#{missing_columns.join "', '"}' column(s) to '#{self.class.name}' to make it archival")
63
101
  end
64
102
 
65
103
  def archived?
66
- !!(self.archived_at? && self.archive_number)
104
+ !!(archived_at? && archive_number)
67
105
  end
68
106
 
69
- def archive(head_archive_number=nil)
70
- self.class.transaction do
71
- begin
72
- success = run_callbacks(:archive) do
73
- unless self.archived?
74
- head_archive_number ||= Digest::MD5.hexdigest("#{self.class.name}#{self.id}")
75
- self.archive_associations(head_archive_number)
76
- self.archived_at = DateTime.now
77
- self.archive_number = head_archive_number
78
- self.save!
79
- end
80
- end
81
- return !!success
82
- rescue => e
83
- ActiveRecord::Base.logger.try(:debug, e.message)
84
- ActiveRecord::Base.logger.try(:debug, e.backtrace)
85
- raise ActiveRecord::Rollback
107
+ def archive(head_archive_number = nil)
108
+ execute_archival_action(:archive) do
109
+ unless archived?
110
+ head_archive_number ||= Digest::MD5.hexdigest("#{self.class.name}#{id}")
111
+ archive_associations(head_archive_number)
112
+ self.archived_at = DateTime.now
113
+ self.archive_number = head_archive_number
114
+ save!
86
115
  end
87
116
  end
88
- false
89
117
  end
90
118
 
91
- def unarchive(head_archive_number=nil)
92
- self.class.transaction do
93
- begin
94
- success = run_callbacks(:unarchive) do
95
- if self.archived?
96
- head_archive_number ||= self.archive_number
97
- self.archived_at = nil
98
- self.archive_number = nil
99
- self.save!
100
- self.unarchive_associations(head_archive_number)
101
- end
102
- end
103
- return !!success
104
- rescue => e
105
- ActiveRecord::Base.logger.try(:debug, e.message)
106
- ActiveRecord::Base.logger.try(:debug, e.backtrace)
107
- raise ActiveRecord::Rollback
119
+ def unarchive(head_archive_number = nil)
120
+ execute_archival_action(:unarchive) do
121
+ if archived?
122
+ head_archive_number ||= archive_number
123
+ self.archived_at = nil
124
+ self.archive_number = nil
125
+ save!
126
+ unarchive_associations(head_archive_number)
108
127
  end
109
128
  end
110
- false
111
129
  end
112
130
 
113
131
  def archive_associations(head_archive_number)
@@ -117,6 +135,26 @@ module ExpectedBehavior
117
135
  def unarchive_associations(head_archive_number)
118
136
  AssociationOperation::Unarchive.new(self, head_archive_number).execute
119
137
  end
138
+
139
+ private def execute_archival_action(action)
140
+ self.class.transaction do
141
+ begin
142
+ success = run_callbacks(action) { yield }
143
+ return !!success
144
+ rescue => e
145
+ handle_archival_action_exception(e)
146
+ end
147
+ end
148
+ false
149
+ end
150
+
151
+ private def handle_archival_action_exception(exception)
152
+ ActiveRecord::Base.logger.try(:debug, exception.message)
153
+ ActiveRecord::Base.logger.try(:debug, exception.backtrace)
154
+ raise ActiveRecord::Rollback
155
+ end
156
+
120
157
  end
158
+
121
159
  end
122
160
  end