amazing-activist 0.3.0 → 0.4.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b5a9d6f3426a86d93d6affd8f54d19f7f071cb5142636c1b3b6fc2a12fbe87b9
4
- data.tar.gz: d53b13cc039dee609e0d2870c560932942d3aa38009b4e7a742f7ce7ad44e9df
3
+ metadata.gz: ccad58a6e900c0d926811f0f5520a807665c3966efff845ac4359c00493cf0cf
4
+ data.tar.gz: 79b51504d7c1bea9dc76bcefe0d78697d7a3e30f15bd21c3dac8684ebaf81dac
5
5
  SHA512:
6
- metadata.gz: '0549ced0fb0312fd5c4cca4cfc8ccaa0e359584c868497a5eea3caa7ad246958de12566d5f33525d555f6bbd9c3a77eb3536514d0e555b83a8a629048c3d58ff'
7
- data.tar.gz: de8d63d94501dc73c61cc626e899407846af44dc8e9cb1c603e7154d57a57720adaa0897a319782a458ed9d89eff474a510777f5083206b9da902143f89060bd
6
+ metadata.gz: 36d6f413e5a39dbde9bf7c0aa6ef40bb58f438096ba659963536c7a2c059c135a00f88f765058edfdb53bdc572352f48f5ac6ebd3d7e4444205b9c34c85ccf51
7
+ data.tar.gz: 56347f7ea9356a1edfdff9f41816b34036f25184ccc7e102ebb11524371b7e3e2e1f134d17bf6644c47ebc7ffd1f36fc369f12f438c62571837f9ae48e8684b2
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "./irresistible"
3
4
  require_relative "./outcome"
4
5
 
5
6
  module AmazingActivist
@@ -28,14 +29,7 @@ module AmazingActivist
28
29
  # end
29
30
  # ----
30
31
  class Base
31
- class << self
32
- # Convenience method to initialize and immediatelly call the activity.
33
- # @see #initialize
34
- # @see #call
35
- def call(...)
36
- new(...).call
37
- end
38
- end
32
+ extend Irresistible
39
33
 
40
34
  # @param params [Hash{Symbol => Object}]
41
35
  def initialize(**params)
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "./error"
4
+
5
+ module AmazingActivist
6
+ class BrokenContractError < Error; end
7
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "./broken_contract_error"
4
+
5
+ module AmazingActivist
6
+ module Contractable
7
+ DEFAULT_BROKEN_OUTCOME_HANDLER = lambda do |outcome|
8
+ raise BrokenContractError, "#{self.class}#call returned #{outcome.class} instead of Outcome"
9
+ end
10
+ private_constant :DEFAULT_BROKEN_OUTCOME_HANDLER
11
+
12
+ protected
13
+
14
+ # @api internal
15
+ def broken_contract_handler
16
+ return @broken_contract_handler if defined?(@broken_contract_handler)
17
+
18
+ ancestors.each do |klass|
19
+ next unless klass < Base && klass != self
20
+
21
+ return @broken_contract_handler = klass.broken_contract_handler
22
+ end
23
+
24
+ @broken_contract_handler = DEFAULT_BROKEN_OUTCOME_HANDLER
25
+ end
26
+
27
+ private
28
+
29
+ def on_broken_outcome(&block)
30
+ raise ArgumentError, "Handler block required." unless block
31
+
32
+ @broken_contract_handler = block
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "./broken_contract_error"
4
+ require_relative "./contractable"
5
+ require_relative "./rescuable"
6
+ require_relative "./unwrap_error"
7
+
8
+ module AmazingActivist
9
+ module Irresistible
10
+ include Contractable
11
+ include Rescuable
12
+
13
+ # Initialize and call activity.
14
+ #
15
+ # @see #initialize
16
+ # @see #call
17
+ def call(...)
18
+ activity = new(...)
19
+ outcome = irresistible_call(activity)
20
+
21
+ unless outcome.is_a?(Outcome::Failure) || outcome.is_a?(Outcome::Success)
22
+ return activity.instance_exec(outcome, &broken_contract_handler)
23
+ end
24
+
25
+ outcome
26
+ end
27
+
28
+ private
29
+
30
+ # @api internal
31
+ def irresistible_call(activity)
32
+ activity.call
33
+ rescue UnwrapError => e
34
+ e.failure
35
+ rescue Exception => e # rubocop:disable Lint/RescueException
36
+ handler = rescue_handler_for(e)
37
+ raise unless handler
38
+
39
+ activity.instance_exec(e, &handler)
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AmazingActivist
4
+ module Rescuable
5
+ protected
6
+
7
+ # @api internal
8
+ def rescue_handlers
9
+ return @rescue_handlers if defined?(@rescue_handlers)
10
+
11
+ ancestors.each do |klass|
12
+ next unless klass < Base && klass != self
13
+
14
+ return @rescue_handlers = klass.rescue_handlers
15
+ end
16
+
17
+ @rescue_handlers = [].freeze
18
+ end
19
+
20
+ # @api internal
21
+ def rescue_handlers=(new_handlers)
22
+ @rescue_handlers = new_handlers.freeze
23
+ end
24
+
25
+ private
26
+
27
+ def rescue_from(*klasses, &block)
28
+ raise ArgumentError, "Handler block required." unless block
29
+
30
+ klasses.each do |klass|
31
+ klass_name =
32
+ case klass
33
+ when Module then klass.name
34
+ when String then klass
35
+ else raise ArgumentError, "#{klass.inspect} must be an Exception class or a String referencing a class."
36
+ end
37
+
38
+ self.rescue_handlers += [[klass_name, block].freeze]
39
+ end
40
+ end
41
+
42
+ # @api internal
43
+ def rescue_handler_for(exception)
44
+ while exception
45
+ rescue_handlers.reverse_each do |klass, handler|
46
+ return handler if exception.is_a?(const_get(klass))
47
+ rescue StandardError
48
+ # do nothing
49
+ end
50
+
51
+ exception = exception.cause
52
+ end
53
+
54
+ nil
55
+ end
56
+ end
57
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AmazingActivist
4
- VERSION = "0.3.0"
4
+ VERSION = "0.4.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: amazing-activist
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexey Zapparov
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-02-19 00:00:00.000000000 Z
11
+ date: 2024-02-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -50,13 +50,17 @@ files:
50
50
  - lib/amazing-activist.rb
51
51
  - lib/amazing_activist.rb
52
52
  - lib/amazing_activist/base.rb
53
+ - lib/amazing_activist/broken_contract_error.rb
54
+ - lib/amazing_activist/contractable.rb
53
55
  - lib/amazing_activist/error.rb
56
+ - lib/amazing_activist/irresistible.rb
54
57
  - lib/amazing_activist/locale/en.yml
55
58
  - lib/amazing_activist/locale/gl.yml
56
59
  - lib/amazing_activist/outcome.rb
57
60
  - lib/amazing_activist/outcome/failure.rb
58
61
  - lib/amazing_activist/outcome/success.rb
59
62
  - lib/amazing_activist/polyglot.rb
63
+ - lib/amazing_activist/rescuable.rb
60
64
  - lib/amazing_activist/unwrap_error.rb
61
65
  - lib/amazing_activist/version.rb
62
66
  homepage: https://github.com/ixti/amazing-activist
@@ -64,9 +68,9 @@ licenses:
64
68
  - MIT
65
69
  metadata:
66
70
  homepage_uri: https://github.com/ixti/amazing-activist
67
- source_code_uri: https://github.com/ixti/amazing-activist/tree/v0.3.0
71
+ source_code_uri: https://github.com/ixti/amazing-activist/tree/v0.4.0
68
72
  bug_tracker_uri: https://github.com/ixti/amazing-activist/issues
69
- changelog_uri: https://github.com/ixti/amazing-activist/blob/v0.3.0/CHANGES.md
73
+ changelog_uri: https://github.com/ixti/amazing-activist/blob/v0.4.0/CHANGES.md
70
74
  rubygems_mfa_required: 'true'
71
75
  post_install_message:
72
76
  rdoc_options: []