convenient_service 0.3.1 → 0.5.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 (59) hide show
  1. checksums.yaml +4 -4
  2. data/.dev/.tmuxinator.yml +17 -0
  3. data/CHANGELOG.md +22 -0
  4. data/README.md +8 -8
  5. data/Taskfile.yml +30 -0
  6. data/convenient_service.gemspec +1 -1
  7. data/lib/convenient_service/aliases.rb +5 -0
  8. data/lib/convenient_service/rspec/matchers/custom/results/base.rb +245 -0
  9. data/lib/convenient_service/rspec/matchers/custom/results/be_error.rb +3 -139
  10. data/lib/convenient_service/rspec/matchers/custom/results/be_failure.rb +3 -106
  11. data/lib/convenient_service/rspec/matchers/custom/results/be_not_error.rb +20 -0
  12. data/lib/convenient_service/rspec/matchers/custom/results/be_not_failure.rb +20 -0
  13. data/lib/convenient_service/rspec/matchers/custom/results/be_not_success.rb +20 -0
  14. data/lib/convenient_service/rspec/matchers/custom/results/be_success.rb +3 -112
  15. data/lib/convenient_service/rspec/matchers/custom/results.rb +6 -0
  16. data/lib/convenient_service/rspec/matchers/results/be_not_error.rb +15 -0
  17. data/lib/convenient_service/rspec/matchers/results/be_not_failure.rb +15 -0
  18. data/lib/convenient_service/rspec/matchers/results/be_not_success.rb +15 -0
  19. data/lib/convenient_service/rspec/matchers/results.rb +8 -0
  20. data/lib/convenient_service/service/plugins/has_result/constants.rb +1 -4
  21. data/lib/convenient_service/service/plugins/has_result/entities/result/plugins/has_jsend_status_and_attributes/entities/data.rb +8 -0
  22. data/lib/convenient_service/service/plugins/has_result/entities/result/plugins/has_jsend_status_and_attributes/entities/status.rb +4 -0
  23. data/lib/convenient_service/service/plugins/has_result_method_steps/middleware.rb +1 -4
  24. data/lib/convenient_service/service/plugins/has_result_steps/concern.rb +8 -2
  25. data/lib/convenient_service/service/plugins/has_result_steps/entities/method/commands/cast_method_caller.rb +1 -1
  26. data/lib/convenient_service/service/plugins/has_result_steps/entities/method/commands/cast_method_key.rb +1 -1
  27. data/lib/convenient_service/service/plugins/has_result_steps/entities/method/commands/cast_method_name.rb +1 -1
  28. data/lib/convenient_service/service/plugins/has_result_steps/entities/method/commands/define_method_in_container.rb +15 -8
  29. data/lib/convenient_service/service/plugins/has_result_steps/entities/method/entities.rb +0 -1
  30. data/lib/convenient_service/service/plugins/has_result_steps/entities/method/errors.rb +15 -1
  31. data/lib/convenient_service/service/plugins/has_result_steps/entities/step/concern/instance_methods.rb +10 -0
  32. data/lib/convenient_service/support/dependency_container/commands/create_methods_module.rb +27 -0
  33. data/lib/convenient_service/support/dependency_container/commands/import_method.rb +111 -0
  34. data/lib/convenient_service/support/dependency_container/commands.rb +4 -0
  35. data/lib/convenient_service/support/dependency_container/constants.rb +15 -0
  36. data/lib/convenient_service/support/dependency_container/entities/method.rb +121 -0
  37. data/lib/convenient_service/support/dependency_container/entities/method_collection.rb +98 -0
  38. data/lib/convenient_service/support/dependency_container/entities/namespace.rb +69 -0
  39. data/lib/convenient_service/support/dependency_container/entities/namespace_collection.rb +103 -0
  40. data/lib/convenient_service/support/dependency_container/entities.rb +6 -0
  41. data/lib/convenient_service/support/dependency_container/errors.rb +49 -0
  42. data/lib/convenient_service/support/dependency_container/export.rb +30 -0
  43. data/lib/convenient_service/support/dependency_container/import.rb +30 -0
  44. data/lib/convenient_service/support/dependency_container.rb +9 -0
  45. data/lib/convenient_service/support/gems/rspec.rb +9 -2
  46. data/lib/convenient_service/support/not_passed.rb +7 -0
  47. data/lib/convenient_service/support/raw_value.rb +52 -0
  48. data/lib/convenient_service/support.rb +3 -0
  49. data/lib/convenient_service/utils/module/fetch_own_const.rb +88 -0
  50. data/lib/convenient_service/utils/module/include_module.rb +38 -0
  51. data/lib/convenient_service/utils/module.rb +10 -0
  52. data/lib/convenient_service/utils/proc/conjunct.rb +1 -1
  53. data/lib/convenient_service/utils/string/split.rb +41 -0
  54. data/lib/convenient_service/utils/string.rb +5 -0
  55. data/lib/convenient_service/version.rb +1 -1
  56. data/lib/convenient_service.rb +6 -0
  57. metadata +33 -8
  58. data/lib/convenient_service/service/plugins/has_result_steps/entities/method/entities/values/raw.rb +0 -48
  59. data/lib/convenient_service/service/plugins/has_result_steps/entities/method/entities/values.rb +0 -3
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ConvenientService
4
+ module RSpec
5
+ module Matchers
6
+ module Custom
7
+ module Results
8
+ class BeNotFailure < Results::Base
9
+ def statuses
10
+ [
11
+ Service::Plugins::HasResult::Constants::ERROR_STATUS,
12
+ Service::Plugins::HasResult::Constants::SUCCESS_STATUS
13
+ ]
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ConvenientService
4
+ module RSpec
5
+ module Matchers
6
+ module Custom
7
+ module Results
8
+ class BeNotSuccess < Results::Base
9
+ def statuses
10
+ [
11
+ Service::Plugins::HasResult::Constants::ERROR_STATUS,
12
+ Service::Plugins::HasResult::Constants::FAILURE_STATUS
13
+ ]
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -5,118 +5,9 @@ module ConvenientService
5
5
  module Matchers
6
6
  module Custom
7
7
  module Results
8
- class BeSuccess
9
- def matches?(result)
10
- @result = result
11
-
12
- rules = []
13
-
14
- rules << ->(result) { result.class.include?(ConvenientService::Service::Plugins::HasResult::Entities::Result::Concern) }
15
- rules << ->(result) { result.success? }
16
- rules << ->(result) { result.service.instance_of?(service_class) } if used_of?
17
- rules << ->(result) { result.data == data } if used_data?
18
-
19
- condition = ConvenientService::Utils::Proc.conjunct(rules)
20
-
21
- condition.call(result)
22
- end
23
-
24
- def with_data(data)
25
- chain[:data] = data
26
-
27
- self
28
- end
29
-
30
- def without_data
31
- chain[:data] = {}
32
-
33
- self
34
- end
35
-
36
- def of(service_class)
37
- chain[:service_class] = service_class
38
-
39
- self
40
- end
41
-
42
- def description
43
- ##
44
- # TODO: of
45
- #
46
- parts = []
47
-
48
- parts << "be a `success`"
49
- parts << "of `#{service_class}`" if used_of?
50
- parts << "with data `#{data}`" if used_data?
51
- parts << "\n\n"
52
- parts << "got `#{result.status}`"
53
- parts << "of `#{result.service.class}`" if used_of?
54
- parts << "with data `#{result.data.to_h}`" if used_data?
55
-
56
- parts.join(" ")
57
- end
58
-
59
- def failure_message
60
- ##
61
- # TODO: got text after expect text.
62
- #
63
- parts = []
64
-
65
- parts << "expected that `#{result}` would be a `success`"
66
- parts << "of `#{service_class}`" if used_of?
67
- parts << "with data `#{data}`" if used_data?
68
- parts << "\n\n"
69
- parts << "got `#{result.status}`"
70
- parts << "of `#{result.service.class}`" if used_of?
71
- parts << "with data `#{result.data.to_h}`" if used_data?
72
-
73
- parts.join(" ")
74
- end
75
-
76
- ##
77
- # https://relishapp.com/rspec/rspec-expectations/v/3-11/docs/custom-matchers/define-a-custom-matcher#overriding-the-failure-message-when-negated
78
- #
79
- def failure_message_when_negated
80
- ##
81
- # TODO: got text after expect text.
82
- #
83
- parts = []
84
-
85
- parts << "expected that #{result} would NOT be a `success`"
86
- parts << "of `#{service_class}`" if used_of?
87
- parts << "with data `#{data}`" if used_data?
88
- parts << "\n\n"
89
- parts << "got `#{result.status}`"
90
- parts << "of `#{result.service.class}`" if used_of?
91
- parts << "with data `#{result.data.to_h}`" if used_data?
92
-
93
- parts.join(" ")
94
- end
95
-
96
- private
97
-
98
- attr_reader :result
99
-
100
- def used_data?
101
- chain.key?(:data)
102
- end
103
-
104
- def used_of?
105
- chain.key?(:service_class)
106
- end
107
-
108
- def chain
109
- @chain ||= {}
110
- end
111
-
112
- def data
113
- @data ||= chain[:data] || {}
114
- end
115
-
116
- def service_class
117
- return @service_class if defined? @service_class
118
-
119
- @service_class = chain[:service_class]
8
+ class BeSuccess < Results::Base
9
+ def statuses
10
+ [Service::Plugins::HasResult::Constants::SUCCESS_STATUS]
120
11
  end
121
12
  end
122
13
  end
@@ -1,5 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "results/base"
4
+
3
5
  require_relative "results/be_error"
4
6
  require_relative "results/be_failure"
5
7
  require_relative "results/be_success"
8
+
9
+ require_relative "results/be_not_error"
10
+ require_relative "results/be_not_failure"
11
+ require_relative "results/be_not_success"
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ConvenientService
4
+ module RSpec
5
+ module Matchers
6
+ module Results
7
+ module BeNotError
8
+ def be_not_error(...)
9
+ Custom::Results::BeNotError.new(...)
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ConvenientService
4
+ module RSpec
5
+ module Matchers
6
+ module Results
7
+ module BeNotFailure
8
+ def be_not_failure(...)
9
+ Custom::Results::BeNotFailure.new(...)
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ConvenientService
4
+ module RSpec
5
+ module Matchers
6
+ module Results
7
+ module BeNotSuccess
8
+ def be_not_success(...)
9
+ Custom::Results::BeNotSuccess.new(...)
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -4,6 +4,10 @@ require_relative "results/be_error"
4
4
  require_relative "results/be_failure"
5
5
  require_relative "results/be_success"
6
6
 
7
+ require_relative "results/be_not_error"
8
+ require_relative "results/be_not_failure"
9
+ require_relative "results/be_not_success"
10
+
7
11
  module ConvenientService
8
12
  module RSpec
9
13
  module Matchers
@@ -14,6 +18,10 @@ module ConvenientService
14
18
  include Results::BeError
15
19
  include Results::BeFailure
16
20
  include Results::BeSuccess
21
+
22
+ include Results::BeNotError
23
+ include Results::BeNotFailure
24
+ include Results::BeNotSuccess
17
25
  end
18
26
  end
19
27
  end
@@ -5,10 +5,7 @@ module ConvenientService
5
5
  module Plugins
6
6
  module HasResult
7
7
  module Constants
8
- ##
9
- # TODO: Consider to include `::ConvenientService::Configs::Minimal`
10
- #
11
- DEFAULT_SERVICE_CLASS = ::Class.new { include ::ConvenientService::Core }
8
+ DEFAULT_SERVICE_CLASS = ::Class.new { include ::ConvenientService::Service::Plugins::HasResult::Concern }
12
9
  DEFAULT_SERVICE_INSTANCE = DEFAULT_SERVICE_CLASS.new
13
10
 
14
11
  SUCCESS_STATUS = :success
@@ -22,6 +22,14 @@ module ConvenientService
22
22
  @value = value
23
23
  end
24
24
 
25
+ ##
26
+ # @param key [String, Symbol]
27
+ # @return [Boolean]
28
+ #
29
+ def has_attribute?(key)
30
+ value.has_key?(key.to_sym)
31
+ end
32
+
25
33
  def ==(other)
26
34
  casted = cast(other)
27
35
 
@@ -54,6 +54,10 @@ module ConvenientService
54
54
  !error?
55
55
  end
56
56
 
57
+ def in?(statuses)
58
+ statuses.any? { |status| self == status }
59
+ end
60
+
57
61
  def to_s
58
62
  @to_s ||= value.to_s
59
63
  end
@@ -24,11 +24,8 @@ module ConvenientService
24
24
 
25
25
  private
26
26
 
27
- ##
28
- # TODO: `Plugins::HasResultSteps::Entities::Method.raw_value`.
29
- #
30
27
  def raw(object)
31
- Plugins::HasResultSteps::Entities::Method::Entities::Values::Raw.wrap(object)
28
+ Support::RawValue.wrap(object)
32
29
  end
33
30
  end
34
31
  end
@@ -33,10 +33,16 @@ module ConvenientService
33
33
  end
34
34
 
35
35
  ##
36
- # NOTE: Allows to pass a value to `in` method without processing it.
36
+ # Allows to pass a value to `in` method without its intermediate processing.
37
+ # @see https://marian13.github.io/convenient_service_docs/basics/step_to_result_translation_table
38
+ #
39
+ # @example `:chat_v2` is passed to `AssertFeatureEnabled` as it is.
40
+ # step AssertFeatureEnabled, in: {name: raw(:chat_v2)}
41
+ # # that is converted to the following service invocation:
42
+ # AssertFeatureEnabled.result(name: :chat_v2)
37
43
  #
38
44
  def raw(value)
39
- Entities::Method::Entities::Values::Raw.wrap(value)
45
+ Support::RawValue.wrap(value)
40
46
  end
41
47
 
42
48
  def steps
@@ -49,7 +49,7 @@ module ConvenientService
49
49
  Entities::Callers::Alias.new(value)
50
50
  when ::Proc
51
51
  Entities::Callers::Proc.new(value)
52
- when Entities::Values::Raw
52
+ when Support::RawValue
53
53
  Entities::Callers::Raw.new(value)
54
54
  end
55
55
  end
@@ -53,7 +53,7 @@ module ConvenientService
53
53
  Entities::Key.new(key)
54
54
  when ::Proc
55
55
  Entities::Key.new(key)
56
- when Entities::Values::Raw
56
+ when Support::RawValue
57
57
  Entities::Key.new(key)
58
58
  end
59
59
  end
@@ -53,7 +53,7 @@ module ConvenientService
53
53
  Entities::Name.new(value)
54
54
  when ::Proc
55
55
  Entities::Name.new(key)
56
- when Entities::Values::Raw
56
+ when Support::RawValue
57
57
  Entities::Name.new(key)
58
58
  end
59
59
  end
@@ -26,11 +26,13 @@ module ConvenientService
26
26
  #
27
27
  <<~RUBY.tap { |code| container.klass.class_eval(code, __FILE__, __LINE__ + 1) }
28
28
  def #{name}
29
- step, key, name, error = steps[#{index}], :#{key}, :#{name}, #{error}
29
+ step, key, method_name = steps[#{index}], :#{key}, :#{name}
30
30
 
31
- return step.result.data[key] if step.completed?
31
+ raise #{not_completed_step_error}.new(step: step, method_name: method_name) unless step.completed?
32
32
 
33
- raise ::#{error}.new(step: step, method_name: name)
33
+ raise #{not_existing_step_result_data_attribute_error}.new(step: step, key: key) unless step.result.data.has_attribute?(key)
34
+
35
+ step.result.data[key]
34
36
  end
35
37
  RUBY
36
38
 
@@ -39,11 +41,16 @@ module ConvenientService
39
41
 
40
42
  private
41
43
 
42
- def error
43
- @error ||=
44
- <<~RUBY.chomp
45
- ConvenientService::Service::Plugins::HasResultSteps::Entities::Method::Errors::NotCompletedStep
46
- RUBY
44
+ def not_completed_step_error
45
+ <<~RUBY.chomp
46
+ ::ConvenientService::Service::Plugins::HasResultSteps::Entities::Method::Errors::NotCompletedStep
47
+ RUBY
48
+ end
49
+
50
+ def not_existing_step_result_data_attribute_error
51
+ <<~RUBY.chomp
52
+ ::ConvenientService::Service::Plugins::HasResultSteps::Entities::Method::Errors::NotExistingStepResultDataAttribute
53
+ RUBY
47
54
  end
48
55
  end
49
56
  end
@@ -4,4 +4,3 @@ require_relative "entities/directions"
4
4
  require_relative "entities/callers"
5
5
  require_relative "entities/key"
6
6
  require_relative "entities/name"
7
- require_relative "entities/values"
@@ -110,7 +110,7 @@ module ConvenientService
110
110
  class NotCompletedStep < ConvenientService::Error
111
111
  def initialize(method_name:, step:)
112
112
  message = <<~TEXT
113
- `out` method `#{method_name}` is called before its corresponding step `#{step.service}` is completed.
113
+ `out` method `#{method_name}` is called before its corresponding step `#{step.printable_service}` is completed.
114
114
 
115
115
  Maybe it makes sense to change the steps order?
116
116
  TEXT
@@ -118,6 +118,20 @@ module ConvenientService
118
118
  super(message)
119
119
  end
120
120
  end
121
+
122
+ class NotExistingStepResultDataAttribute < ConvenientService::Error
123
+ def initialize(key:, step:)
124
+ message = <<~TEXT
125
+ Step `#{step.printable_service}` result does NOT return `#{key}` data attribute.
126
+
127
+ Maybe there is a typo in `out` definition?
128
+
129
+ Or `success` of `#{step.printable_service}` accepts a wrong key?
130
+ TEXT
131
+
132
+ super(message)
133
+ end
134
+ end
121
135
  end
122
136
  end
123
137
  end
@@ -70,6 +70,16 @@ module ConvenientService
70
70
  @result ||= calculate_result
71
71
  end
72
72
 
73
+ ##
74
+ # @return [String]
75
+ #
76
+ # @internal
77
+ # TODO: printable service for methods steps.
78
+ #
79
+ def printable_service
80
+ service.klass.to_s
81
+ end
82
+
73
83
  def validate!
74
84
  inputs.each { |input| input.validate_as_input_for_container!(container) }
75
85
 
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ConvenientService
4
+ module Support
5
+ module DependencyContainer
6
+ module Commands
7
+ class CreateMethodsModule < Support::Command
8
+ ##
9
+ # @return [Module]
10
+ #
11
+ def call
12
+ ::Module.new do
13
+ class << self
14
+ ##
15
+ # @return namespaces [ConvenientService::Support::DependencyContainer::Entities::NamespaceCollection]
16
+ #
17
+ def namespaces
18
+ @namespaces ||= Entities::NamespaceCollection.new
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ConvenientService
4
+ module Support
5
+ module DependencyContainer
6
+ module Commands
7
+ class ImportMethod < Support::Command
8
+ ##
9
+ # @!attribute [r] importing_module
10
+ # @return [Module]
11
+ #
12
+ attr_reader :importing_module
13
+
14
+ ##
15
+ # @!attribute [r] exporting_module
16
+ # @return [Module]
17
+ #
18
+ attr_reader :exporting_module
19
+
20
+ ##
21
+ # @!attribute [r] method
22
+ # @return [ConvenientService::Support::DependencyContainer::Method]
23
+ #
24
+ attr_reader :method
25
+
26
+ ##
27
+ # @!attribute [r] scope
28
+ # @return [Symbol]
29
+ #
30
+ attr_reader :scope
31
+
32
+ ##
33
+ # @!attribute [r] prepend
34
+ # @return [Boolean]
35
+ #
36
+ attr_reader :prepend
37
+
38
+ ##
39
+ # @param importing_module [Module]
40
+ # @param exporting_module [Module]
41
+ # @param method [ConvenientService::Support::DependencyContainer::Method]
42
+ # @param scope [:instance, :class]
43
+ # @param prepend [Boolean]
44
+ #
45
+ def initialize(importing_module:, exporting_module:, method:, scope:, prepend:)
46
+ @importing_module = importing_module
47
+ @exporting_module = exporting_module
48
+ @method = method
49
+ @scope = scope
50
+ @prepend = prepend
51
+ end
52
+
53
+ ##
54
+ # @return [ConvenientService::Support::DependencyContainer::Method]
55
+ #
56
+ def call
57
+ import imported_scoped_methods
58
+
59
+ method.define_in_module!(imported_scoped_methods)
60
+
61
+ method
62
+ end
63
+
64
+ private
65
+
66
+ ##
67
+ # @return [Module]
68
+ #
69
+ def imported_scoped_methods
70
+ @imported_scoped_methods ||= Utils::Module.fetch_own_const(importing_module, :"Imported#{imported_prefix}#{scoped_prefix}Methods") { Commands::CreateMethodsModule.call }
71
+ end
72
+
73
+ ##
74
+ # @return [String]
75
+ #
76
+ def imported_prefix
77
+ prepend ? "Prepended" : "Included"
78
+ end
79
+
80
+ ##
81
+ # @return [String]
82
+ #
83
+ def scoped_prefix
84
+ case scope
85
+ when Constants::INSTANCE_SCOPE then "Instance"
86
+ when Constants::CLASS_SCOPE then "Class"
87
+ end
88
+ end
89
+
90
+ ##
91
+ # @return [Module, Class]
92
+ #
93
+ def importer
94
+ case scope
95
+ when Constants::INSTANCE_SCOPE then importing_module
96
+ when Constants::CLASS_SCOPE then importing_module.singleton_class
97
+ end
98
+ end
99
+
100
+ ##
101
+ # @param mod [Module]
102
+ # @return [Module]
103
+ #
104
+ def import(mod)
105
+ prepend ? importer.prepend(mod) : importer.include(mod)
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "commands/create_methods_module"
4
+ require_relative "commands/import_method"
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ConvenientService
4
+ module Support
5
+ module DependencyContainer
6
+ module Constants
7
+ INSTANCE_SCOPE = :instance
8
+ CLASS_SCOPE = :class
9
+
10
+ DEFAULT_SCOPE = Constants::INSTANCE_SCOPE
11
+ DEFAULT_PREPEND = false
12
+ end
13
+ end
14
+ end
15
+ end