convenient_service 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +18 -0
  3. data/ROADMAP.md +2 -0
  4. data/lib/convenient_service/aliases.rb +9 -0
  5. data/lib/convenient_service/common/plugins/has_constructor_without_initialize/concern.rb +19 -0
  6. data/lib/convenient_service/configs/minimal.rb +176 -0
  7. data/lib/convenient_service/configs/standard.rb +16 -104
  8. data/lib/convenient_service/configs.rb +1 -0
  9. data/lib/convenient_service/dependencies.rb +8 -0
  10. data/lib/convenient_service/examples/dry/gemfile/dry_service/config.rb +5 -5
  11. data/lib/convenient_service/examples/rails/gemfile/rails_service/config.rb +7 -7
  12. data/lib/convenient_service/rspec/helpers/custom/ignoring_error.rb +3 -0
  13. data/lib/convenient_service/rspec/helpers/custom/wrap_method/entities/wrapped_method.rb +29 -3
  14. data/lib/convenient_service/rspec/matchers/custom/results/base.rb +5 -0
  15. data/lib/convenient_service/service/plugins/has_result/concern/class_methods.rb +3 -3
  16. data/lib/convenient_service/service/plugins/has_result/constants.rb +0 -3
  17. data/lib/convenient_service/service/plugins/has_result/entities/result/plugins/has_jsend_status_and_attributes/entities/data.rb +13 -0
  18. data/lib/convenient_service/service/plugins/raises_on_double_result/middleware.rb +37 -2
  19. data/lib/convenient_service/service/plugins/rescues_result_unhandled_exceptions/commands/format_backtrace.rb +80 -0
  20. data/lib/convenient_service/service/plugins/rescues_result_unhandled_exceptions/commands/format_cause.rb +78 -0
  21. data/lib/convenient_service/service/plugins/rescues_result_unhandled_exceptions/commands/format_exception.rb +169 -0
  22. data/lib/convenient_service/service/plugins/rescues_result_unhandled_exceptions/commands/format_line.rb +40 -0
  23. data/lib/convenient_service/service/plugins/rescues_result_unhandled_exceptions/commands.rb +7 -0
  24. data/lib/convenient_service/service/plugins/rescues_result_unhandled_exceptions/constants.rb +13 -0
  25. data/lib/convenient_service/service/plugins/rescues_result_unhandled_exceptions/middleware.rb +58 -0
  26. data/lib/convenient_service/service/plugins/rescues_result_unhandled_exceptions.rb +5 -0
  27. data/lib/convenient_service/support/undefined.rb +9 -0
  28. data/lib/convenient_service/support.rb +2 -0
  29. data/lib/convenient_service/version.rb +1 -1
  30. metadata +12 -2
@@ -22,7 +22,7 @@ module ConvenientService
22
22
  # NOTE: This method is internally used by custom RSpec helper `stub_service`. It should NOT be used in the client code.
23
23
  #
24
24
  def success(
25
- service: Constants::DEFAULT_SERVICE_INSTANCE,
25
+ service: create_without_initialize,
26
26
  data: Constants::DEFAULT_SUCCESS_DATA
27
27
  )
28
28
  result_class.create(
@@ -42,7 +42,7 @@ module ConvenientService
42
42
  # NOTE: This method is internally used by custom RSpec helper `stub_service`. It should NOT be used in the client code.
43
43
  #
44
44
  def failure(
45
- service: Constants::DEFAULT_SERVICE_INSTANCE,
45
+ service: create_without_initialize,
46
46
  data: Constants::DEFAULT_FAILURE_DATA,
47
47
  message: data.any? ? data.first.join(" ") : Constants::DEFAULT_FAILURE_MESSAGE
48
48
  )
@@ -63,7 +63,7 @@ module ConvenientService
63
63
  # NOTE: This method is internally used by custom RSpec helper `stub_service`. It should NOT be used in the client code.
64
64
  #
65
65
  def error(
66
- service: Constants::DEFAULT_SERVICE_INSTANCE,
66
+ service: create_without_initialize,
67
67
  message: Constants::DEFAULT_ERROR_MESSAGE,
68
68
  code: Constants::DEFAULT_ERROR_CODE
69
69
  )
@@ -5,9 +5,6 @@ module ConvenientService
5
5
  module Plugins
6
6
  module HasResult
7
7
  module Constants
8
- DEFAULT_SERVICE_CLASS = ::Class.new { include ::ConvenientService::Service::Plugins::HasResult::Concern }
9
- DEFAULT_SERVICE_INSTANCE = DEFAULT_SERVICE_CLASS.new
10
-
11
8
  SUCCESS_STATUS = :success
12
9
  FAILURE_STATUS = :failure
13
10
  ERROR_STATUS = :error
@@ -18,6 +18,19 @@ module ConvenientService
18
18
 
19
19
  attr_reader :value
20
20
 
21
+ ##
22
+ # @internal
23
+ # NOTE: Ruby hashes enumerate their values in the order that the corresponding keys were inserted.
24
+ # That is why the end-user can be 100% sure that the failure message is always generated from the first key/value pair.
25
+ # - https://ruby-doc.org/core-2.7.0/Hash.html
26
+ #
27
+ # TODO: A test that crashes when such behaviour is broken.
28
+ #
29
+ # NOTE: As a result, there is NO need to use any custom `OrderedHash` implementations.
30
+ # - https://api.rubyonrails.org/v5.1/classes/ActiveSupport/OrderedHash.html
31
+ # - https://github.com/rails/rails/issues/22681
32
+ # - https://api.rubyonrails.org/classes/ActiveSupport/OrderedOptions.html
33
+ #
21
34
  def initialize(value:)
22
35
  @value = value
23
36
  end
@@ -5,6 +5,26 @@ module ConvenientService
5
5
  module Plugins
6
6
  module RaisesOnDoubleResult
7
7
  class Middleware < Core::MethodChainMiddleware
8
+ ##
9
+ # @return [ConvenientService::Service::Plugins::HasResult::Entities::Result]
10
+ #
11
+ # @internal
12
+ # TODO: Rewrite `RaisesOnDoubleResult` to make it thread-safe.
13
+ #
14
+ # NOTE: Minimal reproducible example.
15
+ #
16
+ # class Service
17
+ # include ConvenientService::Standard::Config
18
+ #
19
+ # def result
20
+ # success
21
+ # end
22
+ # end
23
+ #
24
+ # service = Service.new
25
+ #
26
+ # 10.times.reduce([]) { |threads| threads << Thread.new { service.result } }.join
27
+ #
8
28
  def next(...)
9
29
  refute_has_result! || mark_as_has_result!
10
30
 
@@ -14,8 +34,14 @@ module ConvenientService
14
34
  private
15
35
 
16
36
  ##
17
- # NOTE: `refute` is `!assert`.
18
- # https://docs.seattlerb.org/minitest
37
+ # @return [Boolean]
38
+ # @raise [ConvenientService::Service::Plugins::RaisesOnDoubleResult::Errors::DoubleResult]
39
+ #
40
+ # @internal
41
+ # NOTE: `refute` is `!assert`.
42
+ # - https://docs.seattlerb.org/minitest
43
+ #
44
+ # NOTE: This method contains a trailing exclamation mark in its name since it is mutable.
19
45
  #
20
46
  def refute_has_result!
21
47
  return unless entity.internals.cache.exist?(:has_result)
@@ -23,6 +49,15 @@ module ConvenientService
23
49
  raise Errors::DoubleResult.new(service: entity)
24
50
  end
25
51
 
52
+ ##
53
+ # @return [Boolean]
54
+ #
55
+ # @internal
56
+ # NOTE: Name is inspired by `mark_as_read`.
57
+ # - https://github.com/ledermann/unread
58
+ #
59
+ # NOTE: This method contains a trailing exclamation mark in its name since it is mutable.
60
+ #
26
61
  def mark_as_has_result!
27
62
  entity.internals.cache.write(:has_result, true)
28
63
  end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ConvenientService
4
+ module Service
5
+ module Plugins
6
+ module RescuesResultUnhandledExceptions
7
+ module Commands
8
+ class FormatBacktrace < Support::Command
9
+ ##
10
+ # @!attribute [r] backtrace
11
+ # @return [Array, nil]
12
+ #
13
+ attr_reader :backtrace
14
+
15
+ ##
16
+ # @!attribute [r] max_size
17
+ # @return [Integer]
18
+ #
19
+ attr_reader :max_size
20
+
21
+ ##
22
+ # @param backtrace [Array, nil]
23
+ # @param max_size [Integer]
24
+ # @return [void]
25
+ #
26
+ # @internal
27
+ # IMPORTANT: Sometimes `exception.backtrace` can be `nil`.
28
+ # - https://blog.kalina.tech/2019/04/exception-without-backtrace-in-ruby.html
29
+ # - https://github.com/jruby/jruby/issues/4467
30
+ #
31
+ def initialize(backtrace:, max_size:)
32
+ @backtrace = backtrace.to_a
33
+ @max_size = max_size
34
+ end
35
+
36
+ ##
37
+ # @return [String]
38
+ #
39
+ # @note Exceptions formatting is inspired by RSpec. It has almost the same output (at least for RSpec 3).
40
+ #
41
+ # @example Backtrace with upto 10 lines.
42
+ #
43
+ # # /gem/lib/convenient_service/factories/services.rb:120:in `result'
44
+ # # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/caller/commands/define_method_middlewares_caller.rb:116:in `call'
45
+ # # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/caller/commands/define_method_middlewares_caller.rb:116:in `block in result'
46
+ # # /gem/lib/convenient_service/dependencies/extractions/ruby_middleware/middleware/runner.rb:67:in `block (2 levels) in build_call_chain'
47
+ # # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/chain.rb:35:in `next'
48
+ # # /gem/lib/convenient_service/common/plugins/caches_return_value/middleware.rb:17:in `block in next'
49
+ # # /gem/lib/convenient_service/support/cache.rb:110:in `fetch'
50
+ # # /gem/lib/convenient_service/common/plugins/caches_return_value/middleware.rb:17:in `next'
51
+ # # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/middleware.rb:73:in `call'
52
+ # # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/chain.rb:35:in `next'
53
+ #
54
+ # @example Backtrace with more than 10 lines.
55
+ #
56
+ # # /gem/lib/convenient_service/factories/services.rb:120:in `result'
57
+ # # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/caller/commands/define_method_middlewares_caller.rb:116:in `call'
58
+ # # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/caller/commands/define_method_middlewares_caller.rb:116:in `block in result'
59
+ # # /gem/lib/convenient_service/dependencies/extractions/ruby_middleware/middleware/runner.rb:67:in `block (2 levels) in build_call_chain'
60
+ # # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/chain.rb:35:in `next'
61
+ # # /gem/lib/convenient_service/common/plugins/caches_return_value/middleware.rb:17:in `block in next'
62
+ # # /gem/lib/convenient_service/support/cache.rb:110:in `fetch'
63
+ # # /gem/lib/convenient_service/common/plugins/caches_return_value/middleware.rb:17:in `next'
64
+ # # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/middleware.rb:73:in `call'
65
+ # # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/chain.rb:35:in `next'
66
+ # # ...
67
+ #
68
+ def call
69
+ message = backtrace.take(max_size).map { |line| Commands::FormatLine.call(line: line) }.join("\n")
70
+
71
+ message << "\n# ..." if backtrace.size > max_size
72
+
73
+ message
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ConvenientService
4
+ module Service
5
+ module Plugins
6
+ module RescuesResultUnhandledExceptions
7
+ module Commands
8
+ class FormatCause < Support::Command
9
+ ##
10
+ # @!attribute [r] exception
11
+ # @return [StandardError, nil]
12
+ #
13
+ attr_reader :cause
14
+
15
+ ##
16
+ # @param cause [StandardError]
17
+ # @return [void]
18
+ #
19
+ def initialize(cause:)
20
+ @cause = cause
21
+ end
22
+
23
+ ##
24
+ # @return [String]
25
+ #
26
+ # @note Cause formatting is inspired by RSpec. It has almost the same output (at least for RSpec 3).
27
+ #
28
+ # @example Cause.
29
+ #
30
+ # ------------------
31
+ # --- Caused by: ---
32
+ # StandardError:
33
+ # cause message
34
+ # # /gem/lib/convenient_service/factories/service/class.rb:41:in `result'
35
+ #
36
+ def call
37
+ return "" unless cause
38
+
39
+ <<~MESSAGE.chomp
40
+ ------------------
41
+ --- Caused by: ---
42
+ #{cause.class}:
43
+ #{cause.message}
44
+ #{formatted_cause_first_line}
45
+ MESSAGE
46
+ end
47
+
48
+ private
49
+
50
+ ##
51
+ # @return [String, nil]
52
+ #
53
+ # @internal
54
+ # IMPORTANT: Sometimes `exception.backtrace` can be `nil`.
55
+ # - https://blog.kalina.tech/2019/04/exception-without-backtrace-in-ruby.html
56
+ # - https://github.com/jruby/jruby/issues/4467
57
+ #
58
+ def cause_first_line
59
+ return "" unless cause
60
+ return "" unless cause.backtrace
61
+
62
+ cause.backtrace.first
63
+ end
64
+
65
+ ##
66
+ # @return [String, nil]
67
+ #
68
+ def formatted_cause_first_line
69
+ return "" unless cause_first_line
70
+
71
+ Commands::FormatLine.call(line: cause_first_line)
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,169 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ConvenientService
4
+ module Service
5
+ module Plugins
6
+ module RescuesResultUnhandledExceptions
7
+ module Commands
8
+ class FormatException < Support::Command
9
+ ##
10
+ # @!attribute [r] exception
11
+ # @return [StandardError]
12
+ #
13
+ attr_reader :exception
14
+
15
+ ##
16
+ # @!attribute [r] args
17
+ # @return [StandardError]
18
+ #
19
+ attr_reader :args
20
+
21
+ ##
22
+ # @!attribute [r] kwargs
23
+ # @return [StandardError]
24
+ #
25
+ attr_reader :kwargs
26
+
27
+ ##
28
+ # @!attribute [r] block
29
+ # @return [StandardError]
30
+ #
31
+ attr_reader :block
32
+
33
+ ##
34
+ # @param exception [StandardError]
35
+ # @param args [Array]
36
+ # @param kwargs [Hash]
37
+ # @param block [Proc, nil]
38
+ # @return [void]
39
+ #
40
+ def initialize(exception:, args:, kwargs:, block:)
41
+ @exception = exception
42
+ @args = args
43
+ @kwargs = kwargs
44
+ @block = block
45
+ end
46
+
47
+ ##
48
+ # @return [String]
49
+ #
50
+ # @note Exceptions formatting is inspired by RSpec. It has almost the same output (at least for RSpec 3).
51
+ #
52
+ # @example Simple exception.
53
+ #
54
+ # StandardError:
55
+ # exception message
56
+ # # /gem/lib/convenient_service/factories/services.rb:120:in `result'
57
+ # # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/caller/commands/define_method_middlewares_caller.rb:116:in `call'
58
+ # # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/caller/commands/define_method_middlewares_caller.rb:116:in `block in result'
59
+ # # /gem/lib/convenient_service/dependencies/extractions/ruby_middleware/middleware/runner.rb:67:in `block (2 levels) in build_call_chain'
60
+ # # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/chain.rb:35:in `next'
61
+ # # /gem/lib/convenient_service/common/plugins/caches_return_value/middleware.rb:17:in `block in next'
62
+ # # /gem/lib/convenient_service/support/cache.rb:110:in `fetch'
63
+ # # /gem/lib/convenient_service/common/plugins/caches_return_value/middleware.rb:17:in `next'
64
+ # # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/middleware.rb:73:in `call'
65
+ # # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/chain.rb:35:in `next'
66
+ #
67
+ # @example Exception with backtrace with more than 10 lines.
68
+ #
69
+ # StandardError:
70
+ # exception message
71
+ # # /gem/lib/convenient_service/factories/services.rb:120:in `result'
72
+ # # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/caller/commands/define_method_middlewares_caller.rb:116:in `call'
73
+ # # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/caller/commands/define_method_middlewares_caller.rb:116:in `block in result'
74
+ # # /gem/lib/convenient_service/dependencies/extractions/ruby_middleware/middleware/runner.rb:67:in `block (2 levels) in build_call_chain'
75
+ # # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/chain.rb:35:in `next'
76
+ # # /gem/lib/convenient_service/common/plugins/caches_return_value/middleware.rb:17:in `block in next'
77
+ # # /gem/lib/convenient_service/support/cache.rb:110:in `fetch'
78
+ # # /gem/lib/convenient_service/common/plugins/caches_return_value/middleware.rb:17:in `next'
79
+ # # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/middleware.rb:73:in `call'
80
+ # # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/chain.rb:35:in `next'
81
+ # # ...
82
+ #
83
+ # @example Exception with cause.
84
+ #
85
+ # StandardError:
86
+ # exception message
87
+ # # /gem/lib/convenient_service/factories/service/class.rb:43:in `rescue in result'
88
+ # # /gem/lib/convenient_service/factories/service/class.rb:40:in `result'
89
+ # # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/caller/commands/define_method_middlewares_caller.rb:116:in `call'
90
+ # # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/caller/commands/define_method_middlewares_caller.rb:116:in `block in result'
91
+ # # /gem/lib/convenient_service/dependencies/extractions/ruby_middleware/middleware/runner.rb:67:in `block (2 levels) in build_call_chain'
92
+ # # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/chain.rb:35:in `next'
93
+ # # /gem/lib/convenient_service/common/plugins/caches_return_value/middleware.rb:17:in `block in next'
94
+ # # /gem/lib/convenient_service/support/cache.rb:110:in `fetch'
95
+ # # /gem/lib/convenient_service/common/plugins/caches_return_value/middleware.rb:17:in `next'
96
+ # # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/middleware.rb:73:in `call'
97
+ # ------------------
98
+ # --- Caused by: ---
99
+ # StandardError:
100
+ # cause message
101
+ # # /gem/lib/convenient_service/factories/service/class.rb:41:in `result'
102
+ #
103
+ # @internal
104
+ # TODO: Think about the following questions:
105
+ # - How to format args, kwargs and block?
106
+ # - Who should format them? The end-user or this plugin?
107
+ #
108
+ def call
109
+ <<~MESSAGE.rstrip
110
+ #{formatted_exception}
111
+ #{formatted_exception_backtrace}
112
+ #{formatted_exception_cause}
113
+ MESSAGE
114
+ end
115
+
116
+ private
117
+
118
+ ##
119
+ # @return [String]
120
+ #
121
+ def formatted_exception
122
+ <<~MESSAGE.chomp
123
+ #{exception.class}:
124
+ #{exception.message}
125
+ MESSAGE
126
+ end
127
+
128
+ ##
129
+ # Formats exception backtrace. When backtrace has more then `max_backtrace_size` lines, the extra lines are trimmed.
130
+ # That is especially important for the monitoring system with the limited amount of memory, since it may too expensive to store the full backtrace all the time.
131
+ #
132
+ # @return [String]
133
+ #
134
+ # @internal
135
+ # TODO: Add an ability to set `max_backtrace_size` while configuring the middleware. For example:
136
+ #
137
+ # class Service
138
+ # include ConvenientService::Standard::Config
139
+ #
140
+ # middlewares :result, scope: :class do
141
+ # use ConvenientService::Service::Plugins::RescuesResultUnhandledExceptions::Middleware, max_backtrace_size: 1_000
142
+ # end
143
+ #
144
+ # # ...
145
+ # end
146
+ #
147
+ def formatted_exception_backtrace
148
+ Commands::FormatBacktrace.call(backtrace: exception.backtrace, max_size: max_backtrace_size)
149
+ end
150
+
151
+ ##
152
+ # @return [String]
153
+ #
154
+ def formatted_exception_cause
155
+ Commands::FormatCause.call(cause: exception.cause)
156
+ end
157
+
158
+ ##
159
+ # @return [Integer]
160
+ #
161
+ def max_backtrace_size
162
+ Constants::DEFAULT_MAX_BACKTRACE_SIZE
163
+ end
164
+ end
165
+ end
166
+ end
167
+ end
168
+ end
169
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ConvenientService
4
+ module Service
5
+ module Plugins
6
+ module RescuesResultUnhandledExceptions
7
+ module Commands
8
+ class FormatLine < Support::Command
9
+ ##
10
+ # @!attribute [r] line
11
+ # @return [String]
12
+ #
13
+ attr_reader :line
14
+
15
+ ##
16
+ # @param line [String]
17
+ # @return [void]
18
+ #
19
+ def initialize(line:)
20
+ @line = line
21
+ end
22
+
23
+ ##
24
+ # @return [String]
25
+ #
26
+ # @note Exceptions formatting is inspired by RSpec. It has almost the same output (at least for RSpec 3).
27
+ #
28
+ # @example Line.
29
+ #
30
+ # # /gem/lib/convenient_service/factories/services.rb:120:in `result'
31
+ #
32
+ def call
33
+ "# #{line}"
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "commands/format_backtrace"
4
+ require_relative "commands/format_cause"
5
+ require_relative "commands/format_line"
6
+
7
+ require_relative "commands/format_exception"
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ConvenientService
4
+ module Service
5
+ module Plugins
6
+ module RescuesResultUnhandledExceptions
7
+ module Constants
8
+ DEFAULT_MAX_BACKTRACE_SIZE = 10
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ConvenientService
4
+ module Service
5
+ module Plugins
6
+ module RescuesResultUnhandledExceptions
7
+ class Middleware < Core::MethodChainMiddleware
8
+ ##
9
+ # @param args [Array]
10
+ # @param kwargs [Hash]
11
+ # @param block [Proc, nil]
12
+ # @return [ConvenientService::Service::Plugins::HasResult::Entities::Result]
13
+ #
14
+ # @internal
15
+ # NOTE: `rescue => exception` is the same as `rescue ::StandardError => exception`.
16
+ #
17
+ # IMPORTANT: Never rescue `Exception` since its direct descendants are used internally by Ruby, rescue `StandardError` instead.
18
+ # - https://thoughtbot.com/blog/rescue-standarderror-not-exception
19
+ # - https://stackoverflow.com/questions/10048173/why-is-it-bad-style-to-rescue-exception-e-in-ruby
20
+ # - https://ruby-doc.org/core-2.7.0/Exception.html
21
+ #
22
+ def next(*args, **kwargs, &block)
23
+ chain.next(*args, **kwargs, &block)
24
+ rescue => exception
25
+ failure_result_from(exception, *args, **kwargs, &block)
26
+ end
27
+
28
+ private
29
+
30
+ ##
31
+ # @param exception [StandardError]
32
+ # @param args [Array]
33
+ # @param kwargs [Hash]
34
+ # @param block [Proc, nil]
35
+ # @return [ConvenientService::Service::Plugins::HasResult::Entities::Result]
36
+ #
37
+ def failure_result_from(exception, *args, **kwargs, &block)
38
+ entity.failure(
39
+ data: {exception: exception},
40
+ message: format_exception(exception, *args, **kwargs, &block)
41
+ )
42
+ end
43
+
44
+ ##
45
+ # @param exception [StandardError]
46
+ # @param args [Array]
47
+ # @param kwargs [Hash]
48
+ # @param block [Proc, nil]
49
+ # @return [String]
50
+ #
51
+ def format_exception(exception, *args, **kwargs, &block)
52
+ Commands::FormatException.call(exception: exception, args: args, kwargs: kwargs, block: block)
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "rescues_result_unhandled_exceptions/commands"
4
+ require_relative "rescues_result_unhandled_exceptions/constants"
5
+ require_relative "rescues_result_unhandled_exceptions/middleware"
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ConvenientService
4
+ module Support
5
+ UNDEFINED = ::Object.new.tap do |object|
6
+ object.define_singleton_method(:inspect) { "undefined" }
7
+ end
8
+ end
9
+ end
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "support/not_passed"
4
+ require_relative "support/undefined"
5
+
4
6
  require_relative "support/concern"
5
7
 
6
8
  require_relative "support/abstract_method"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ConvenientService
4
- VERSION = "0.7.0"
4
+ VERSION = "0.8.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: convenient_service
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marian Kostyk
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-02-13 00:00:00.000000000 Z
11
+ date: 2023-02-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: appraisal
@@ -427,6 +427,7 @@ files:
427
427
  - lib/convenient_service/common/plugins/normalizes_env/middleware.rb
428
428
  - lib/convenient_service/configs.rb
429
429
  - lib/convenient_service/configs/aliases.rb
430
+ - lib/convenient_service/configs/minimal.rb
430
431
  - lib/convenient_service/configs/standard.rb
431
432
  - lib/convenient_service/core.rb
432
433
  - lib/convenient_service/core/aliases.rb
@@ -825,6 +826,14 @@ files:
825
826
  - lib/convenient_service/service/plugins/raises_on_double_result.rb
826
827
  - lib/convenient_service/service/plugins/raises_on_double_result/errors.rb
827
828
  - lib/convenient_service/service/plugins/raises_on_double_result/middleware.rb
829
+ - lib/convenient_service/service/plugins/rescues_result_unhandled_exceptions.rb
830
+ - lib/convenient_service/service/plugins/rescues_result_unhandled_exceptions/commands.rb
831
+ - lib/convenient_service/service/plugins/rescues_result_unhandled_exceptions/commands/format_backtrace.rb
832
+ - lib/convenient_service/service/plugins/rescues_result_unhandled_exceptions/commands/format_cause.rb
833
+ - lib/convenient_service/service/plugins/rescues_result_unhandled_exceptions/commands/format_exception.rb
834
+ - lib/convenient_service/service/plugins/rescues_result_unhandled_exceptions/commands/format_line.rb
835
+ - lib/convenient_service/service/plugins/rescues_result_unhandled_exceptions/constants.rb
836
+ - lib/convenient_service/service/plugins/rescues_result_unhandled_exceptions/middleware.rb
828
837
  - lib/convenient_service/service/plugins/wraps_result_in_db_transaction.rb
829
838
  - lib/convenient_service/service/plugins/wraps_result_in_db_transaction/middleware.rb
830
839
  - lib/convenient_service/services.rb
@@ -867,6 +876,7 @@ files:
867
876
  - lib/convenient_service/support/not_passed.rb
868
877
  - lib/convenient_service/support/raw_value.rb
869
878
  - lib/convenient_service/support/ruby.rb
879
+ - lib/convenient_service/support/undefined.rb
870
880
  - lib/convenient_service/support/version.rb
871
881
  - lib/convenient_service/support/version/null_version.rb
872
882
  - lib/convenient_service/utils.rb