convenient_service 0.3.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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