convenient_service 0.1.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gem_release.yml +0 -12
- data/.github/issue_template.md +35 -0
- data/.github/pull_request_template.md +31 -0
- data/.github/workflows/cd.yml +15 -2
- data/.github/workflows/ci.yml +6 -6
- data/CHANGELOG.md +27 -0
- data/README.md +12 -3
- data/ROADMAP.md +22 -8
- data/Taskfile.yml +5 -13
- data/env.rb +4 -0
- data/lib/convenient_service/common/plugins/caches_return_value/middleware.rb +17 -2
- data/lib/convenient_service/common/plugins/caches_return_value.rb +0 -1
- data/lib/convenient_service/common/plugins/has_constructor/concern.rb +13 -0
- data/lib/convenient_service/common/plugins/has_constructor_without_initialize/concern.rb +27 -0
- data/lib/convenient_service/common/plugins/has_constructor_without_initialize.rb +3 -0
- data/lib/convenient_service/common/plugins/has_internals/entities/internals/plugins/has_cache/concern.rb +8 -4
- data/lib/convenient_service/common/plugins/has_internals/entities/internals/plugins/has_cache.rb +0 -1
- data/lib/convenient_service/common/plugins.rb +1 -0
- data/lib/convenient_service/configs/standard.rb +16 -0
- data/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/container/commands/cast_container.rb +0 -2
- data/lib/convenient_service/dependencies.rb +1 -0
- data/lib/convenient_service/examples/dry/gemfile/dry_service/config.rb +3 -1
- data/lib/convenient_service/examples/dry/gemfile/services/assert_file_exists.rb +1 -1
- data/lib/convenient_service/examples/dry/gemfile/services/assert_file_not_empty.rb +1 -1
- data/lib/convenient_service/examples/dry/gemfile/services/assert_npm_package_available.rb +1 -1
- data/lib/convenient_service/examples/dry/gemfile/services/parse_content.rb +1 -1
- data/lib/convenient_service/examples/dry/gemfile/services/print_shell_command.rb +1 -1
- data/lib/convenient_service/examples/dry/gemfile/services/read_file_content.rb +1 -1
- data/lib/convenient_service/examples/dry/gemfile/services/run_shell.rb +1 -1
- data/lib/convenient_service/examples/dry/gemfile/services/strip_comments.rb +1 -1
- data/lib/convenient_service/examples/dry/gemfile.rb +5 -4
- data/lib/convenient_service/examples/rails/gemfile/rails_service/config.rb +3 -1
- data/lib/convenient_service/examples/rails/gemfile.rb +5 -4
- data/lib/convenient_service/examples/standard/cowsay/services/build_cloud.rb +42 -0
- data/lib/convenient_service/examples/standard/cowsay/services/build_cow.rb +38 -0
- data/lib/convenient_service/examples/standard/cowsay/services/print.rb +32 -0
- data/lib/convenient_service/examples/standard/cowsay/services.rb +5 -0
- data/lib/convenient_service/examples/standard/cowsay.rb +24 -0
- data/lib/convenient_service/examples/standard/gemfile/services/format.rb +2 -0
- data/lib/convenient_service/examples/standard/gemfile.rb +5 -4
- data/lib/convenient_service/rspec/helpers/custom/stub_service/entities/result_spec.rb +96 -7
- data/lib/convenient_service/rspec/helpers/custom/wrap_method/entities/wrapped_method.rb +44 -8
- data/lib/convenient_service/rspec/helpers/custom/wrap_method/errors.rb +11 -9
- data/lib/convenient_service/rspec/matchers/custom/cache_its_value.rb +7 -7
- data/lib/convenient_service/rspec/matchers/custom/call_chain_next.rb +2 -0
- data/lib/convenient_service/rspec/matchers/custom/delegate_to.rb +50 -12
- data/lib/convenient_service/rspec/matchers/custom/results/be_success.rb +6 -0
- data/lib/convenient_service/service/plugins/aliases.rb +1 -0
- data/lib/convenient_service/service/plugins/has_inspect/concern.rb +23 -0
- data/lib/convenient_service/service/plugins/has_inspect.rb +3 -0
- data/lib/convenient_service/service/plugins/has_result/commands/create_result_class.rb +10 -0
- data/lib/convenient_service/service/plugins/has_result/concern/class_methods.rb +23 -14
- data/lib/convenient_service/service/plugins/has_result/concern/instance_methods.rb +17 -1
- data/lib/convenient_service/service/plugins/has_result/entities/result/concern.rb +4 -3
- data/lib/convenient_service/service/plugins/has_result/entities/result/plugins/has_inspect/concern.rb +31 -0
- data/lib/convenient_service/service/plugins/has_result/entities/result/plugins/has_inspect.rb +3 -0
- data/lib/convenient_service/service/plugins/has_result/entities/result/plugins/has_jsend_status_and_attributes/commands/cast_jsend_attributes.rb +37 -0
- data/lib/convenient_service/service/plugins/has_result/entities/result/plugins/has_jsend_status_and_attributes/commands.rb +3 -0
- data/lib/convenient_service/service/plugins/has_result/entities/result/plugins/has_jsend_status_and_attributes/concern/instance_methods.rb +127 -0
- data/lib/convenient_service/service/plugins/has_result/entities/result/plugins/has_jsend_status_and_attributes/concern.rb +27 -0
- data/lib/convenient_service/service/plugins/has_result/entities/result/plugins/has_jsend_status_and_attributes/entities/code/class_methods.rb +34 -0
- data/lib/convenient_service/service/plugins/has_result/entities/result/plugins/has_jsend_status_and_attributes/entities/code.rb +49 -0
- data/lib/convenient_service/service/plugins/has_result/entities/result/plugins/has_jsend_status_and_attributes/entities/data/class_methods.rb +32 -0
- data/lib/convenient_service/service/plugins/has_result/entities/result/plugins/has_jsend_status_and_attributes/entities/data.rb +49 -0
- data/lib/convenient_service/service/plugins/has_result/entities/result/plugins/has_jsend_status_and_attributes/entities/message/class_methods.rb +34 -0
- data/lib/convenient_service/service/plugins/has_result/entities/result/plugins/has_jsend_status_and_attributes/entities/message.rb +45 -0
- data/lib/convenient_service/service/plugins/has_result/entities/result/plugins/has_jsend_status_and_attributes/entities/status/class_methods.rb +34 -0
- data/lib/convenient_service/service/plugins/has_result/entities/result/plugins/has_jsend_status_and_attributes/entities/status.rb +73 -0
- data/lib/convenient_service/service/plugins/has_result/entities/result/{entities.rb → plugins/has_jsend_status_and_attributes/entities.rb} +0 -0
- data/lib/convenient_service/service/plugins/has_result/entities/result/plugins/has_jsend_status_and_attributes/errors.rb +29 -0
- data/lib/convenient_service/service/plugins/has_result/entities/result/plugins/has_jsend_status_and_attributes/middleware.rb +31 -0
- data/lib/convenient_service/service/plugins/has_result/entities/result/plugins/has_jsend_status_and_attributes/structs/jsend_attributes.rb +21 -0
- data/lib/convenient_service/service/plugins/has_result/entities/result/plugins/has_jsend_status_and_attributes/structs.rb +3 -0
- data/lib/convenient_service/service/plugins/has_result/entities/result/plugins/has_jsend_status_and_attributes.rb +8 -0
- data/lib/convenient_service/service/plugins/has_result/entities/result/plugins.rb +2 -0
- data/lib/convenient_service/service/plugins/has_result/entities/result.rb +0 -4
- data/lib/convenient_service/service/plugins/has_result_method_steps/middleware.rb +1 -1
- data/lib/convenient_service/service/plugins/has_result_method_steps/services/method_step_config.rb +30 -4
- data/lib/convenient_service/service/plugins/has_result_params_validations/using_dry_validation/middleware.rb +19 -9
- data/lib/convenient_service/service/plugins/has_result_status_check_short_syntax/concern.rb +63 -0
- data/lib/convenient_service/service/plugins/has_result_status_check_short_syntax.rb +3 -0
- data/lib/convenient_service/service/plugins/has_result_steps/concern.rb +2 -1
- data/lib/convenient_service/service/plugins/has_result_steps/entities/step/plugins/has_inspect/concern.rb +31 -0
- data/lib/convenient_service/service/plugins/has_result_steps/entities/step/plugins/has_inspect.rb +3 -0
- data/lib/convenient_service/service/plugins/has_result_steps/entities/step/plugins.rb +3 -0
- data/lib/convenient_service/service/plugins/has_result_steps/entities/step.rb +1 -0
- data/lib/convenient_service/service/plugins/has_result_steps/middleware.rb +1 -1
- data/lib/convenient_service/service/plugins.rb +2 -0
- data/lib/convenient_service/support/cache/key.rb +100 -0
- data/lib/convenient_service/support/cache.rb +131 -0
- data/lib/convenient_service/support/copyable.rb +3 -2
- data/lib/convenient_service/support/delegate.rb +3 -2
- data/lib/convenient_service/support.rb +1 -0
- data/lib/convenient_service/version.rb +1 -1
- data/logo.png +0 -0
- metadata +40 -21
- data/lib/convenient_service/common/plugins/caches_return_value/entities/key.rb +0 -79
- data/lib/convenient_service/common/plugins/caches_return_value/entities.rb +0 -3
- data/lib/convenient_service/common/plugins/has_internals/entities/internals/plugins/has_cache/entities/cache.rb +0 -81
- data/lib/convenient_service/common/plugins/has_internals/entities/internals/plugins/has_cache/entities.rb +0 -3
- data/lib/convenient_service/service/plugins/has_result/entities/result/commands/cast_result_params.rb +0 -33
- data/lib/convenient_service/service/plugins/has_result/entities/result/commands.rb +0 -3
- data/lib/convenient_service/service/plugins/has_result/entities/result/concern/instance_methods.rb +0 -64
- data/lib/convenient_service/service/plugins/has_result/entities/result/entities/code/class_methods.rb +0 -30
- data/lib/convenient_service/service/plugins/has_result/entities/result/entities/code.rb +0 -45
- data/lib/convenient_service/service/plugins/has_result/entities/result/entities/data/class_methods.rb +0 -28
- data/lib/convenient_service/service/plugins/has_result/entities/result/entities/data.rb +0 -45
- data/lib/convenient_service/service/plugins/has_result/entities/result/entities/message/class_methods.rb +0 -30
- data/lib/convenient_service/service/plugins/has_result/entities/result/entities/message.rb +0 -41
- data/lib/convenient_service/service/plugins/has_result/entities/result/entities/status/class_methods.rb +0 -30
- data/lib/convenient_service/service/plugins/has_result/entities/result/entities/status.rb +0 -69
- data/lib/convenient_service/service/plugins/has_result/entities/result/errors.rb +0 -25
- data/lib/convenient_service/service/plugins/has_result/entities/result/structs/result_params.rb +0 -17
- data/lib/convenient_service/service/plugins/has_result/entities/result/structs.rb +0 -3
@@ -4,17 +4,18 @@ require_relative "gemfile/rails_service"
|
|
4
4
|
require_relative "gemfile/services"
|
5
5
|
|
6
6
|
##
|
7
|
-
#
|
7
|
+
# @internal
|
8
|
+
# Usage example:
|
8
9
|
#
|
9
|
-
#
|
10
|
-
#
|
10
|
+
# result = ConvenientService::Examples::Rails::Gemfile.format("Gemfile")
|
11
|
+
# result = ConvenientService::Examples::Rails::Gemfile.format("spec/cli/gemfile/format/fixtures/Gemfile")
|
11
12
|
#
|
12
13
|
module ConvenientService
|
13
14
|
module Examples
|
14
15
|
module Rails
|
15
16
|
module Gemfile
|
16
17
|
class << self
|
17
|
-
def format
|
18
|
+
def format(path)
|
18
19
|
Services::Format[path: path]
|
19
20
|
end
|
20
21
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ConvenientService
|
4
|
+
module Examples
|
5
|
+
module Standard
|
6
|
+
module Cowsay
|
7
|
+
module Services
|
8
|
+
class BuildCloud
|
9
|
+
include ConvenientService::Standard::Config
|
10
|
+
|
11
|
+
attr_reader :text
|
12
|
+
|
13
|
+
def initialize(text: "Hello World!")
|
14
|
+
@text = text
|
15
|
+
end
|
16
|
+
|
17
|
+
def result
|
18
|
+
success(cloud: cloud)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
##
|
24
|
+
# Copied with ❤️ from https://github.com/gaborbata/rosetta-cow
|
25
|
+
#
|
26
|
+
def cloud
|
27
|
+
<<~HEREDOC
|
28
|
+
#{border(text, "_")}
|
29
|
+
< #{text} >
|
30
|
+
#{border(text, "-")}
|
31
|
+
HEREDOC
|
32
|
+
end
|
33
|
+
|
34
|
+
def border(text, char)
|
35
|
+
char * (text.length + 2)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ConvenientService
|
4
|
+
module Examples
|
5
|
+
module Standard
|
6
|
+
module Cowsay
|
7
|
+
module Services
|
8
|
+
class BuildCow
|
9
|
+
include ConvenientService::Standard::Config
|
10
|
+
|
11
|
+
def result
|
12
|
+
success(cow: cow)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
##
|
18
|
+
# Copied with ❤️ from https://github.com/gaborbata/rosetta-cow
|
19
|
+
#
|
20
|
+
def cow
|
21
|
+
<<~'HEREDOC'.split("\n").map { |line| offset(line) }.join("\n")
|
22
|
+
\ ^__^
|
23
|
+
\ (oo)\_______
|
24
|
+
(__)\ )\/\
|
25
|
+
||----w |
|
26
|
+
|| ||
|
27
|
+
HEREDOC
|
28
|
+
end
|
29
|
+
|
30
|
+
def offset(line)
|
31
|
+
" " * 10 + line
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ConvenientService
|
4
|
+
module Examples
|
5
|
+
module Standard
|
6
|
+
module Cowsay
|
7
|
+
module Services
|
8
|
+
class Print
|
9
|
+
include ConvenientService::Standard::Config
|
10
|
+
|
11
|
+
attr_reader :text, :out
|
12
|
+
|
13
|
+
step Services::BuildCloud, in: :text, out: :cloud
|
14
|
+
step Services::BuildCow, out: :cow
|
15
|
+
step :result
|
16
|
+
|
17
|
+
def initialize(text: "Hello World!", out: $stdout)
|
18
|
+
@text = text
|
19
|
+
@out = out
|
20
|
+
end
|
21
|
+
|
22
|
+
def result
|
23
|
+
out.puts cloud + cow
|
24
|
+
|
25
|
+
success
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "cowsay/services"
|
4
|
+
|
5
|
+
##
|
6
|
+
# @internal
|
7
|
+
# Usage examples:
|
8
|
+
#
|
9
|
+
# result = ConvenientService::Examples::Standard::Cowsay.print("Hello")
|
10
|
+
# result = ConvenientService::Examples::Standard::Cowsay.print("Hi")
|
11
|
+
#
|
12
|
+
module ConvenientService
|
13
|
+
module Examples
|
14
|
+
module Standard
|
15
|
+
module Cowsay
|
16
|
+
class << self
|
17
|
+
def print(text = "Hello World!", out: $stdout)
|
18
|
+
Services::Print[text: text, out: out]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -14,6 +14,8 @@ module ConvenientService
|
|
14
14
|
class Format
|
15
15
|
include ConvenientService::Standard::Config
|
16
16
|
|
17
|
+
attr_reader :path
|
18
|
+
|
17
19
|
step Services::ReadFileContent, in: :path, out: :content
|
18
20
|
step Services::StripComments, in: :content, out: :content_without_comments
|
19
21
|
step Services::ParseContent, in: {content: :content_without_comments}, out: :parsed_content
|
@@ -3,17 +3,18 @@
|
|
3
3
|
require_relative "gemfile/services"
|
4
4
|
|
5
5
|
##
|
6
|
-
#
|
6
|
+
# @internal
|
7
|
+
# Usage example:
|
7
8
|
#
|
8
|
-
#
|
9
|
-
#
|
9
|
+
# result = ConvenientService::Examples::Standard::Gemfile.format("Gemfile")
|
10
|
+
# result = ConvenientService::Examples::Standard::Gemfile.format("spec/cli/gemfile/format/fixtures/Gemfile")
|
10
11
|
#
|
11
12
|
module ConvenientService
|
12
13
|
module Examples
|
13
14
|
module Standard
|
14
15
|
module Gemfile
|
15
16
|
class << self
|
16
|
-
def format
|
17
|
+
def format(path)
|
17
18
|
Services::Format[path: path]
|
18
19
|
end
|
19
20
|
end
|
@@ -5,72 +5,140 @@ module ConvenientService
|
|
5
5
|
module Helpers
|
6
6
|
module Custom
|
7
7
|
##
|
8
|
-
#
|
8
|
+
# @internal
|
9
|
+
# TODO: Specs.
|
9
10
|
#
|
10
11
|
class StubService < Support::Command
|
11
12
|
module Entities
|
12
13
|
class ResultSpec
|
14
|
+
##
|
15
|
+
# @param status [Symbol]
|
16
|
+
# @param service_class [Class]
|
17
|
+
# @param chain [Hash]
|
18
|
+
# @return [void]
|
19
|
+
# @since 0.1.0
|
20
|
+
#
|
13
21
|
def initialize(status:, service_class: nil, chain: {})
|
14
22
|
@status = status
|
15
23
|
@service_class = service_class
|
16
24
|
@chain = chain
|
17
25
|
end
|
18
26
|
|
27
|
+
##
|
28
|
+
# @param service_class [Class]
|
29
|
+
# @return [ConvenientService::RSpec::Helpers::Custom::StubService::Entities::ResultSpec]
|
30
|
+
# @since 0.1.0
|
31
|
+
#
|
19
32
|
def for(service_class)
|
20
33
|
self.class.new(status: status, service_class: service_class, chain: chain)
|
21
34
|
end
|
22
35
|
|
36
|
+
##
|
37
|
+
# @param data [Hash]
|
38
|
+
# @return [ConvenientService::RSpec::Helpers::Custom::StubService::Entities::ResultSpec]
|
39
|
+
# @since 0.1.0
|
40
|
+
#
|
23
41
|
def with_data(data)
|
24
42
|
chain[:data] = data
|
25
43
|
|
26
44
|
self
|
27
45
|
end
|
28
46
|
|
47
|
+
##
|
48
|
+
# @param message [String]
|
49
|
+
# @return [ConvenientService::RSpec::Helpers::Custom::StubService::Entities::ResultSpec]
|
50
|
+
# @since 0.1.0
|
51
|
+
#
|
29
52
|
def with_message(message)
|
30
53
|
chain[:message] = message
|
31
54
|
|
32
55
|
self
|
33
56
|
end
|
34
57
|
|
58
|
+
##
|
59
|
+
# @param code [String]
|
60
|
+
# @return [ConvenientService::RSpec::Helpers::Custom::StubService::Entities::ResultSpec]
|
61
|
+
# @since 0.1.0
|
62
|
+
#
|
35
63
|
def with_code(code)
|
36
64
|
chain[:code] = code
|
37
65
|
|
38
66
|
self
|
39
67
|
end
|
40
68
|
|
69
|
+
##
|
70
|
+
# @param data [Hash]
|
71
|
+
# @return [ConvenientService::RSpec::Helpers::Custom::StubService::Entities::ResultSpec]
|
72
|
+
# @since 0.1.0
|
73
|
+
#
|
41
74
|
def and_data(data)
|
42
75
|
chain[:data] = data
|
43
76
|
|
44
77
|
self
|
45
78
|
end
|
46
79
|
|
80
|
+
##
|
81
|
+
# @param message [String]
|
82
|
+
# @return [ConvenientService::RSpec::Helpers::Custom::StubService::Entities::ResultSpec]
|
83
|
+
# @since 0.1.0
|
84
|
+
#
|
47
85
|
def and_message(message)
|
48
86
|
chain[:message] = message
|
49
87
|
|
50
88
|
self
|
51
89
|
end
|
52
90
|
|
91
|
+
##
|
92
|
+
# @param code [String]
|
93
|
+
# @return [ConvenientService::RSpec::Helpers::Custom::StubService::Entities::ResultSpec]
|
94
|
+
# @since 0.1.0
|
95
|
+
#
|
53
96
|
def and_code(code)
|
54
97
|
chain[:code] = code
|
55
98
|
|
56
99
|
self
|
57
100
|
end
|
58
101
|
|
102
|
+
##
|
103
|
+
# @return [Object]
|
104
|
+
#
|
105
|
+
# @internal
|
106
|
+
# TODO: Assert.
|
107
|
+
#
|
59
108
|
def calculate_value
|
60
|
-
##
|
61
|
-
# TODO: Assert.
|
62
|
-
#
|
63
109
|
service_class.__send__(status, **kwargs)
|
64
110
|
end
|
65
111
|
|
66
112
|
private
|
67
113
|
|
68
|
-
|
69
|
-
|
114
|
+
##
|
115
|
+
# @!attribute [r] status
|
116
|
+
# @return [Symbol]
|
117
|
+
#
|
118
|
+
attr_reader :status
|
119
|
+
|
120
|
+
##
|
121
|
+
# @!attribute [r] service_class
|
122
|
+
# @return [Class]
|
123
|
+
#
|
124
|
+
attr_reader :service_class
|
125
|
+
|
126
|
+
##
|
127
|
+
# @!attribute [r] chain
|
128
|
+
# @return [Hash]
|
129
|
+
#
|
130
|
+
attr_reader :chain
|
131
|
+
|
132
|
+
##
|
133
|
+
# @return [Hash]
|
134
|
+
#
|
70
135
|
def kwargs
|
71
136
|
@kwargs ||= calculate_kwargs
|
72
137
|
end
|
73
138
|
|
139
|
+
##
|
140
|
+
# @return [Hash]
|
141
|
+
#
|
74
142
|
def calculate_kwargs
|
75
143
|
kwargs = {}
|
76
144
|
|
@@ -83,32 +151,53 @@ module ConvenientService
|
|
83
151
|
kwargs
|
84
152
|
end
|
85
153
|
|
154
|
+
##
|
155
|
+
# @return [Boolean]
|
156
|
+
#
|
86
157
|
def used_data?
|
87
158
|
chain.key?(:data)
|
88
159
|
end
|
89
160
|
|
161
|
+
##
|
162
|
+
# @return [Boolean]
|
163
|
+
#
|
90
164
|
def used_message?
|
91
165
|
chain.key?(:message)
|
92
166
|
end
|
93
167
|
|
168
|
+
##
|
169
|
+
# @return [Boolean]
|
170
|
+
#
|
94
171
|
def used_code?
|
95
172
|
chain.key?(:code)
|
96
173
|
end
|
97
174
|
|
175
|
+
##
|
176
|
+
# @return [Hash]
|
177
|
+
#
|
98
178
|
def data
|
99
179
|
@data ||= chain[:data] || {}
|
100
180
|
end
|
101
181
|
|
182
|
+
##
|
183
|
+
# @return [String]
|
184
|
+
#
|
102
185
|
def message
|
103
186
|
@message ||= chain[:message] || ""
|
104
187
|
end
|
105
188
|
|
189
|
+
##
|
190
|
+
# @return [String]
|
191
|
+
#
|
106
192
|
def code
|
107
193
|
@code ||= chain[:code] || ""
|
108
194
|
end
|
109
195
|
|
196
|
+
##
|
197
|
+
# @return [Object]
|
198
|
+
#
|
110
199
|
def service_instance
|
111
|
-
@service_instance ||= service_class.
|
200
|
+
@service_instance ||= service_class.create_without_initialize
|
112
201
|
end
|
113
202
|
end
|
114
203
|
end
|
@@ -4,17 +4,23 @@ module ConvenientService
|
|
4
4
|
module RSpec
|
5
5
|
module Helpers
|
6
6
|
module Custom
|
7
|
-
##
|
8
|
-
# TODO: Specs.
|
9
|
-
#
|
10
7
|
class WrapMethod < Support::Command
|
11
8
|
module Entities
|
12
9
|
##
|
13
|
-
#
|
10
|
+
# @internal
|
11
|
+
# TODO: A better name.
|
12
|
+
#
|
13
|
+
# NOTE: Do NOT pollute the interface of this class until really needed. Avoid even pollution of private methods.
|
14
14
|
#
|
15
15
|
class WrappedMethod
|
16
16
|
##
|
17
|
-
#
|
17
|
+
# @param entity [Object, Class]
|
18
|
+
# @param method [String]
|
19
|
+
# @param middlewares [Array<ConvenientService::Core::MethodChainMiddleware>]
|
20
|
+
# @return [void]
|
21
|
+
#
|
22
|
+
# @internal
|
23
|
+
# NOTE: `middlewares` are `MethodChainMiddleware` classes.
|
18
24
|
#
|
19
25
|
def initialize(entity:, method:, middlewares:)
|
20
26
|
@entity = entity
|
@@ -29,9 +35,6 @@ module ConvenientService
|
|
29
35
|
#
|
30
36
|
stack.use(
|
31
37
|
proc do |env|
|
32
|
-
##
|
33
|
-
# TODO: Enforce to always pass args, kwargs, block.
|
34
|
-
#
|
35
38
|
entity.__send__(method, *env[:args], **env[:kwargs], &env[:block])
|
36
39
|
.tap { |value| @chain_value = value }
|
37
40
|
.tap { @chain_arguments = {args: env[:args], kwargs: env[:kwargs], block: env[:block]} }
|
@@ -40,32 +43,65 @@ module ConvenientService
|
|
40
43
|
end
|
41
44
|
end
|
42
45
|
|
46
|
+
##
|
47
|
+
# @param args [Array]
|
48
|
+
# @param kwargs [Hash]
|
49
|
+
# @param block [Proc]
|
50
|
+
# @return [Object] Can be any type.
|
51
|
+
#
|
43
52
|
def call(*args, **kwargs, &block)
|
44
53
|
@stack.call(entity: @entity, method: @method, args: args, kwargs: kwargs, block: block)
|
45
54
|
end
|
46
55
|
|
56
|
+
##
|
57
|
+
# @return [void]
|
58
|
+
#
|
59
|
+
def reset!
|
60
|
+
remove_instance_variable(:@chain_value) if defined? @chain_value
|
61
|
+
remove_instance_variable(:@chain_arguments) if defined? @chain_arguments
|
62
|
+
end
|
63
|
+
|
64
|
+
##
|
65
|
+
# @return [Boolean]
|
66
|
+
#
|
47
67
|
def chain_called?
|
48
68
|
Utils::Bool.to_bool(defined? @chain_value)
|
49
69
|
end
|
50
70
|
|
71
|
+
##
|
72
|
+
# @return [Object] Can be any type.
|
73
|
+
# @raise [ConvenientService::RSpec::Helpers::Custom::WrapMethod::Errors::ChainAttributePreliminaryAccess]
|
74
|
+
#
|
51
75
|
def chain_value
|
52
76
|
raise Errors::ChainAttributePreliminaryAccess.new(attribute: :value) unless chain_called?
|
53
77
|
|
54
78
|
@chain_value
|
55
79
|
end
|
56
80
|
|
81
|
+
##
|
82
|
+
# @return [Array]
|
83
|
+
# @raise [ConvenientService::RSpec::Helpers::Custom::WrapMethod::Errors::ChainAttributePreliminaryAccess]
|
84
|
+
#
|
57
85
|
def chain_args
|
58
86
|
raise Errors::ChainAttributePreliminaryAccess.new(attribute: :args) unless chain_called?
|
59
87
|
|
60
88
|
@chain_arguments[:args]
|
61
89
|
end
|
62
90
|
|
91
|
+
##
|
92
|
+
# @return [Hash]
|
93
|
+
# @raise [ConvenientService::RSpec::Helpers::Custom::WrapMethod::Errors::ChainAttributePreliminaryAccess]
|
94
|
+
#
|
63
95
|
def chain_kwargs
|
64
96
|
raise Errors::ChainAttributePreliminaryAccess.new(attribute: :kwargs) unless chain_called?
|
65
97
|
|
66
98
|
@chain_arguments[:kwargs]
|
67
99
|
end
|
68
100
|
|
101
|
+
##
|
102
|
+
# @return [Proc, nil]
|
103
|
+
# @raise [ConvenientService::RSpec::Helpers::Custom::WrapMethod::Errors::ChainAttributePreliminaryAccess]
|
104
|
+
#
|
69
105
|
def chain_block
|
70
106
|
raise Errors::ChainAttributePreliminaryAccess.new(attribute: :block) unless chain_called?
|
71
107
|
|
@@ -5,16 +5,18 @@ module ConvenientService
|
|
5
5
|
module Helpers
|
6
6
|
module Custom
|
7
7
|
class WrapMethod < Support::Command
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
8
|
+
module Errors
|
9
|
+
class ChainAttributePreliminaryAccess < ConvenientService::Error
|
10
|
+
##
|
11
|
+
# @param attribute [Symbol]
|
12
|
+
# @return [void]
|
13
|
+
#
|
14
|
+
def initialize(attribute:)
|
15
|
+
message = <<~TEXT
|
16
|
+
Chain attribute `#{attribute}` is accessed before the chain is called.
|
17
|
+
TEXT
|
15
18
|
|
16
|
-
|
17
|
-
end
|
19
|
+
super(message)
|
18
20
|
end
|
19
21
|
end
|
20
22
|
end
|
@@ -23,26 +23,26 @@ module ConvenientService
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def failure_message
|
26
|
-
"expected #{
|
26
|
+
"expected #{printable_block_expectation} to cache its value"
|
27
27
|
end
|
28
28
|
|
29
29
|
def failure_message_when_negated
|
30
|
-
"expected #{
|
30
|
+
"expected #{printable_block_expectation} NOT to cache its value"
|
31
31
|
end
|
32
32
|
|
33
33
|
##
|
34
34
|
# NOTE: An example of how RSpec extracts block source, but they marked it as private.
|
35
35
|
# https://github.com/rspec/rspec-expectations/blob/311aaf245f2c5493572bf683b8c441cb5f7e44c8/lib/rspec/matchers/built_in/change.rb#L437
|
36
36
|
#
|
37
|
-
# TODO: `
|
37
|
+
# TODO: `printable_block_expectation` when `method_source` is available.
|
38
38
|
# https://github.com/banister/method_source
|
39
39
|
#
|
40
|
-
# def
|
41
|
-
# @
|
40
|
+
# def printable_block_expectation
|
41
|
+
# @printable_block_expectation ||= block_expectation.source
|
42
42
|
# end
|
43
43
|
#
|
44
|
-
def
|
45
|
-
@
|
44
|
+
def printable_block_expectation
|
45
|
+
@printable_block_expectation ||= "{ ... }"
|
46
46
|
end
|
47
47
|
|
48
48
|
private
|
@@ -1,5 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
##
|
4
|
+
# IMPORTANT: This matcher has a dedicated end-user doc. Do NOT forget to update it when needed.
|
5
|
+
# https://github.com/marian13/convenient_service_docs/blob/main/docs/api/tests/rspec/matchers/delegate_to.mdx
|
6
|
+
#
|
7
|
+
# TODO: Refactor into composition:
|
8
|
+
# - Ability to compose when `delegate_to` is used `without_arguments`.
|
9
|
+
# - Ability to compose when `delegate_to` is used `with_arguments`.
|
10
|
+
# - Ability to compose when `delegate_to` is used `and_return_its_value`.
|
11
|
+
#
|
12
|
+
# TODO: Refactor to NOT use `expect` inside this matcher.
|
13
|
+
# This way the matcher will return true or false, but never raise exceptions (descendant of Exception, not StandardError).
|
14
|
+
# Then it will be easier to developer a fully comprehensive spec suite for `delegate_to`.
|
15
|
+
#
|
3
16
|
module ConvenientService
|
4
17
|
module RSpec
|
5
18
|
module Matchers
|
@@ -81,15 +94,7 @@ module ConvenientService
|
|
81
94
|
# https://relishapp.com/rspec/rspec-mocks/docs/configuring-responses/wrapping-the-original-implementation
|
82
95
|
#
|
83
96
|
allow(object).to receive(method).and_wrap_original do |original, *actual_args, **actual_kwargs, &actual_block|
|
84
|
-
|
85
|
-
# TODO: Provide customized error messages?
|
86
|
-
# https://relishapp.com/rspec/rspec-expectations/docs/customized-message
|
87
|
-
#
|
88
|
-
# NOTE: `delegate_to` expects that delegation is executed only once during `block_expectation`.
|
89
|
-
#
|
90
|
-
expect(actual_args).to eq(expected_args)
|
91
|
-
expect(actual_kwargs).to eq(expected_kwargs)
|
92
|
-
expect(actual_block).to eq(expected_block)
|
97
|
+
actual_arguments_collection << [actual_args, actual_kwargs, actual_block]
|
93
98
|
|
94
99
|
##
|
95
100
|
# NOTE: Imitates `and_call_original`.
|
@@ -108,7 +113,7 @@ module ConvenientService
|
|
108
113
|
##
|
109
114
|
# NOTE: If this expectation fails, it means `delegate_to` is NOT met.
|
110
115
|
#
|
111
|
-
expect(object).to have_received(method)
|
116
|
+
expect(object).to have_received(method).at_least(1) unless used_with_arguments?
|
112
117
|
|
113
118
|
##
|
114
119
|
# IMPORTANT: `and_return_its_value` works only when `delegate_to` checks a pure function.
|
@@ -166,7 +171,13 @@ module ConvenientService
|
|
166
171
|
# NOTE: RSpec raises exception when any `expect` is NOT satisfied.
|
167
172
|
# So, this `true` is returned only when all `expect` are successful.
|
168
173
|
#
|
169
|
-
|
174
|
+
if used_with_arguments?
|
175
|
+
actual_arguments_collection.any? do |(actual_args, actual_kwargs, actual_block)|
|
176
|
+
actual_args == expected_args && actual_kwargs == expected_kwargs && actual_block == expected_block
|
177
|
+
end
|
178
|
+
else
|
179
|
+
true
|
180
|
+
end
|
170
181
|
end
|
171
182
|
|
172
183
|
##
|
@@ -184,8 +195,16 @@ module ConvenientService
|
|
184
195
|
"delegate to `#{printable_method}`"
|
185
196
|
end
|
186
197
|
|
198
|
+
def failure_message
|
199
|
+
if used_with_arguments?
|
200
|
+
"expected `#{printable_block_expectation}` to delegate to `#{printable_method}` with expected arguments at least once, but it didn't."
|
201
|
+
else
|
202
|
+
"expected `#{printable_block_expectation}` to delegate to `#{printable_method}` at least once, but it didn't."
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
187
206
|
##
|
188
|
-
# IMPORTANT: `
|
207
|
+
# IMPORTANT: `failure_message_when_negated` is NOT supported yet.
|
189
208
|
#
|
190
209
|
|
191
210
|
def with_arguments(*args, **kwargs, &block)
|
@@ -248,6 +267,25 @@ module ConvenientService
|
|
248
267
|
end
|
249
268
|
|
250
269
|
alias_method :expected_block, :block
|
270
|
+
|
271
|
+
def actual_arguments_collection
|
272
|
+
@actual_arguments_collection ||= []
|
273
|
+
end
|
274
|
+
|
275
|
+
##
|
276
|
+
# NOTE: An example of how RSpec extracts block source, but they marked it as private.
|
277
|
+
# https://github.com/rspec/rspec-expectations/blob/311aaf245f2c5493572bf683b8c441cb5f7e44c8/lib/rspec/matchers/built_in/change.rb#L437
|
278
|
+
#
|
279
|
+
# TODO: `printable_block_expectation` when `method_source` is available.
|
280
|
+
# https://github.com/banister/method_source
|
281
|
+
#
|
282
|
+
# def printable_block_expectation
|
283
|
+
# @printable_block_expectation ||= block_expectation.source
|
284
|
+
# end
|
285
|
+
#
|
286
|
+
def printable_block_expectation
|
287
|
+
@printable_block_expectation ||= "{ ... }"
|
288
|
+
end
|
251
289
|
end
|
252
290
|
end
|
253
291
|
end
|