servactory 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +116 -0
- data/Rakefile +12 -0
- data/lib/servactory/base.rb +11 -0
- data/lib/servactory/configuration.rb +18 -0
- data/lib/servactory/context/configuration.rb +23 -0
- data/lib/servactory/context/dsl.rb +58 -0
- data/lib/servactory/context/store.rb +51 -0
- data/lib/servactory/errors/base.rb +7 -0
- data/lib/servactory/errors/failure.rb +7 -0
- data/lib/servactory/errors/input_argument_error.rb +7 -0
- data/lib/servactory/errors/internal_argument_error.rb +7 -0
- data/lib/servactory/errors/output_argument_error.rb +7 -0
- data/lib/servactory/input_arguments/checks/base.rb +23 -0
- data/lib/servactory/input_arguments/checks/inclusion.rb +45 -0
- data/lib/servactory/input_arguments/checks/must.rb +75 -0
- data/lib/servactory/input_arguments/checks/required.rb +54 -0
- data/lib/servactory/input_arguments/checks/type.rb +84 -0
- data/lib/servactory/input_arguments/collection.rb +19 -0
- data/lib/servactory/input_arguments/dsl.rb +27 -0
- data/lib/servactory/input_arguments/input_argument.rb +79 -0
- data/lib/servactory/input_arguments/tools/check.rb +74 -0
- data/lib/servactory/input_arguments/tools/find_unnecessary.rb +32 -0
- data/lib/servactory/input_arguments/tools/prepare.rb +89 -0
- data/lib/servactory/input_arguments/tools/rules.rb +38 -0
- data/lib/servactory/input_arguments/workbench.rb +40 -0
- data/lib/servactory/inputs.rb +7 -0
- data/lib/servactory/internal_arguments/checks/base.rb +17 -0
- data/lib/servactory/internal_arguments/checks/type.rb +55 -0
- data/lib/servactory/internal_arguments/collection.rb +19 -0
- data/lib/servactory/internal_arguments/dsl.rb +27 -0
- data/lib/servactory/internal_arguments/internal_argument.rb +33 -0
- data/lib/servactory/internal_arguments/tools/prepare.rb +58 -0
- data/lib/servactory/internal_arguments/workbench.rb +27 -0
- data/lib/servactory/output_arguments/checks/base.rb +17 -0
- data/lib/servactory/output_arguments/checks/type.rb +55 -0
- data/lib/servactory/output_arguments/collection.rb +19 -0
- data/lib/servactory/output_arguments/dsl.rb +27 -0
- data/lib/servactory/output_arguments/output_argument.rb +40 -0
- data/lib/servactory/output_arguments/tools/conflicts.rb +34 -0
- data/lib/servactory/output_arguments/tools/prepare.rb +58 -0
- data/lib/servactory/output_arguments/workbench.rb +31 -0
- data/lib/servactory/result.rb +21 -0
- data/lib/servactory/stage/dsl.rb +29 -0
- data/lib/servactory/stage/factory.rb +15 -0
- data/lib/servactory/stage/handyman.rb +35 -0
- data/lib/servactory/stage/method.rb +21 -0
- data/lib/servactory/stage/methods.rb +15 -0
- data/lib/servactory/utils.rb +11 -0
- data/lib/servactory/version.rb +11 -0
- data/lib/servactory.rb +34 -0
- metadata +237 -0
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Servactory
|
4
|
+
module InputArguments
|
5
|
+
class InputArgument
|
6
|
+
attr_reader :name,
|
7
|
+
:types,
|
8
|
+
:inclusion,
|
9
|
+
:must,
|
10
|
+
:array,
|
11
|
+
:required,
|
12
|
+
:internal,
|
13
|
+
:default
|
14
|
+
|
15
|
+
def initialize(name, type:, **options)
|
16
|
+
@name = name
|
17
|
+
@types = Array(type)
|
18
|
+
|
19
|
+
@inclusion = options.fetch(:inclusion, nil)
|
20
|
+
@must = options.fetch(:must, nil)
|
21
|
+
@array = options.fetch(:array, false)
|
22
|
+
@required = options.fetch(:required, true)
|
23
|
+
@internal = options.fetch(:internal, false)
|
24
|
+
@default = options.fetch(:default, nil)
|
25
|
+
end
|
26
|
+
|
27
|
+
def options_for_checks
|
28
|
+
{
|
29
|
+
types:,
|
30
|
+
inclusion:,
|
31
|
+
must:,
|
32
|
+
required:,
|
33
|
+
# internal:,
|
34
|
+
default:
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
def conflict_code
|
39
|
+
return :required_vs_default if required? && default_value_present?
|
40
|
+
return :array_vs_array if array? && types.include?(Array)
|
41
|
+
return :array_vs_inclusion if array? && inclusion_present?
|
42
|
+
|
43
|
+
nil
|
44
|
+
end
|
45
|
+
|
46
|
+
def inclusion_present?
|
47
|
+
inclusion.is_a?(Array) && inclusion.present?
|
48
|
+
end
|
49
|
+
|
50
|
+
def must_present?
|
51
|
+
must.present?
|
52
|
+
end
|
53
|
+
|
54
|
+
def array?
|
55
|
+
Servactory::Utils.boolean?(array)
|
56
|
+
end
|
57
|
+
|
58
|
+
def required?
|
59
|
+
Servactory::Utils.boolean?(required)
|
60
|
+
end
|
61
|
+
|
62
|
+
def optional?
|
63
|
+
!required?
|
64
|
+
end
|
65
|
+
|
66
|
+
def internal?
|
67
|
+
Servactory::Utils.boolean?(internal)
|
68
|
+
end
|
69
|
+
|
70
|
+
def default_value_present?
|
71
|
+
!default.nil?
|
72
|
+
end
|
73
|
+
|
74
|
+
def with_conflicts?
|
75
|
+
conflict_code.present?
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Servactory
|
4
|
+
module InputArguments
|
5
|
+
module Tools
|
6
|
+
class Check
|
7
|
+
def self.check!(...)
|
8
|
+
new(...).check!
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(context, incoming_arguments, collection_of_input_arguments)
|
12
|
+
@context = context
|
13
|
+
@incoming_arguments = incoming_arguments
|
14
|
+
@collection_of_input_arguments = collection_of_input_arguments
|
15
|
+
|
16
|
+
@errors = []
|
17
|
+
end
|
18
|
+
|
19
|
+
def check!
|
20
|
+
@collection_of_input_arguments.each do |input|
|
21
|
+
process_input(input)
|
22
|
+
end
|
23
|
+
|
24
|
+
raise_errors
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def process_input(input)
|
30
|
+
input.options_for_checks.each do |check_key, check_options|
|
31
|
+
process_option(check_key, check_options, input:)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def process_option(check_key, check_options, input:)
|
36
|
+
check_classes.each do |check_class|
|
37
|
+
errors_from_checks = process_check_class(check_class, input:, check_key:, check_options:)
|
38
|
+
|
39
|
+
@errors.push(*errors_from_checks)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def process_check_class(check_class, input:, check_key:, check_options:)
|
44
|
+
check_class.check(
|
45
|
+
context: @context,
|
46
|
+
input:,
|
47
|
+
value: @incoming_arguments.fetch(input.name, nil),
|
48
|
+
check_key:,
|
49
|
+
check_options:
|
50
|
+
)
|
51
|
+
end
|
52
|
+
|
53
|
+
########################################################################
|
54
|
+
|
55
|
+
def check_classes
|
56
|
+
[
|
57
|
+
Servactory::InputArguments::Checks::Required,
|
58
|
+
Servactory::InputArguments::Checks::Type,
|
59
|
+
Servactory::InputArguments::Checks::Inclusion,
|
60
|
+
Servactory::InputArguments::Checks::Must
|
61
|
+
]
|
62
|
+
end
|
63
|
+
|
64
|
+
########################################################################
|
65
|
+
|
66
|
+
def raise_errors
|
67
|
+
return if @errors.empty?
|
68
|
+
|
69
|
+
raise Servactory.configuration.input_argument_error_class, @errors.first
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Servactory
|
4
|
+
module InputArguments
|
5
|
+
module Tools
|
6
|
+
class FindUnnecessary
|
7
|
+
def self.check!(...)
|
8
|
+
new(...).check!
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(context, incoming_arguments, collection_of_input_arguments)
|
12
|
+
@context = context
|
13
|
+
@incoming_arguments = incoming_arguments
|
14
|
+
@collection_of_input_arguments = collection_of_input_arguments
|
15
|
+
end
|
16
|
+
|
17
|
+
def check!
|
18
|
+
return if unnecessary_attributes.empty?
|
19
|
+
|
20
|
+
raise Servactory.configuration.input_argument_error_class,
|
21
|
+
"[#{@context.class.name}] Unexpected attributes: `#{unnecessary_attributes.join(', ')}`"
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def unnecessary_attributes
|
27
|
+
@unnecessary_attributes ||= @incoming_arguments.keys - @collection_of_input_arguments.names
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Servactory
|
4
|
+
module InputArguments
|
5
|
+
module Tools
|
6
|
+
class Prepare
|
7
|
+
def self.prepare(...)
|
8
|
+
new(...).prepare
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(context, incoming_arguments, collection_of_input_arguments)
|
12
|
+
@context = context
|
13
|
+
@incoming_arguments = incoming_arguments
|
14
|
+
@collection_of_input_arguments = collection_of_input_arguments
|
15
|
+
end
|
16
|
+
|
17
|
+
def prepare
|
18
|
+
@inputs_variables = {}
|
19
|
+
@internal_variables = {}
|
20
|
+
|
21
|
+
@collection_of_input_arguments.each do |input|
|
22
|
+
process_input(input)
|
23
|
+
end
|
24
|
+
|
25
|
+
create_instance_variables
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def process_input(input)
|
31
|
+
input_value = @incoming_arguments.fetch(input.name, nil)
|
32
|
+
input_value = input.default if input.optional? && input_value.blank?
|
33
|
+
|
34
|
+
@inputs_variables[input.name] = input_value
|
35
|
+
|
36
|
+
return unless input.internal?
|
37
|
+
|
38
|
+
@internal_variables[input.name] = input_value
|
39
|
+
end
|
40
|
+
|
41
|
+
def create_instance_variables
|
42
|
+
Servactory::Inputs.class_eval(class_inputs_template)
|
43
|
+
|
44
|
+
@context.assign_inputs(Servactory::Inputs.new(**@inputs_variables))
|
45
|
+
|
46
|
+
@context.class.class_eval(context_internal_variables_template)
|
47
|
+
|
48
|
+
@internal_variables.each do |input_name, input_value|
|
49
|
+
@context.instance_variable_set(:"@#{input_name}", input_value)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
########################################################################
|
54
|
+
|
55
|
+
# EXAMPLE:
|
56
|
+
#
|
57
|
+
# attr_reader(*[:attr_1]); def initialize(attr_1); @attr_1 = attr_1; end
|
58
|
+
#
|
59
|
+
# OR
|
60
|
+
#
|
61
|
+
# attr_reader(*[:attr_1, :attr_2, :attr_3])
|
62
|
+
#
|
63
|
+
# def initialize(attr_1:, attr_2:, attr_3:)
|
64
|
+
# @attr_1 = attr_1; @attr_2 = attr_2; @attr_3 = attr_3;
|
65
|
+
# end
|
66
|
+
#
|
67
|
+
def class_inputs_template
|
68
|
+
<<-RUBY.squish
|
69
|
+
attr_reader(*#{@inputs_variables.keys});
|
70
|
+
|
71
|
+
def initialize(#{@inputs_variables.keys.join(':, ')}:);
|
72
|
+
#{@inputs_variables.keys.map { |key| "@#{key} = #{key}" }.join('; ')};
|
73
|
+
end
|
74
|
+
RUBY
|
75
|
+
end
|
76
|
+
|
77
|
+
# EXAMPLE:
|
78
|
+
#
|
79
|
+
# private attr_reader(*[:attr_1]);
|
80
|
+
#
|
81
|
+
def context_internal_variables_template
|
82
|
+
<<-RUBY.squish
|
83
|
+
private attr_reader(*#{@internal_variables.keys});
|
84
|
+
RUBY
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Servactory
|
4
|
+
module InputArguments
|
5
|
+
module Tools
|
6
|
+
class Rules
|
7
|
+
def self.check!(...)
|
8
|
+
new(...).check!
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(context, collection_of_input_arguments)
|
12
|
+
@context = context
|
13
|
+
@collection_of_input_arguments = collection_of_input_arguments
|
14
|
+
end
|
15
|
+
|
16
|
+
def check!
|
17
|
+
@collection_of_input_arguments.each do |input_argument|
|
18
|
+
check_for!(input_argument)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def check_for!(input_argument)
|
25
|
+
return unless input_argument.with_conflicts?
|
26
|
+
|
27
|
+
raise_error_for(input_argument)
|
28
|
+
end
|
29
|
+
|
30
|
+
def raise_error_for(input_argument)
|
31
|
+
raise Servactory.configuration.input_argument_error_class,
|
32
|
+
"[#{@context.class.name}] Conflict in `#{input_argument.name}` input " \
|
33
|
+
"options: `#{input_argument.conflict_code}`"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Servactory
|
4
|
+
module InputArguments
|
5
|
+
class Workbench
|
6
|
+
def self.work_with(...)
|
7
|
+
new(...)
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(collection_of_input_arguments)
|
11
|
+
@collection_of_input_arguments = collection_of_input_arguments
|
12
|
+
end
|
13
|
+
|
14
|
+
def assign(context:, arguments:)
|
15
|
+
@context = context
|
16
|
+
@incoming_arguments = arguments
|
17
|
+
end
|
18
|
+
|
19
|
+
def find_unnecessary!
|
20
|
+
Tools::FindUnnecessary.check!(context, @incoming_arguments, collection_of_input_arguments)
|
21
|
+
end
|
22
|
+
|
23
|
+
def check_rules!
|
24
|
+
Tools::Rules.check!(context, collection_of_input_arguments)
|
25
|
+
end
|
26
|
+
|
27
|
+
def prepare
|
28
|
+
Tools::Prepare.prepare(context, @incoming_arguments, collection_of_input_arguments)
|
29
|
+
end
|
30
|
+
|
31
|
+
def check!
|
32
|
+
Tools::Check.check!(context, @incoming_arguments, collection_of_input_arguments)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
attr_reader :context, :collection_of_input_arguments
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Servactory
|
4
|
+
module InternalArguments
|
5
|
+
module Checks
|
6
|
+
class Base
|
7
|
+
protected
|
8
|
+
|
9
|
+
def raise_error_with(message, **arguments)
|
10
|
+
message = message.call(**arguments) if message.is_a?(Proc)
|
11
|
+
|
12
|
+
raise Servactory.configuration.internal_argument_error_class, message
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Servactory
|
4
|
+
module InternalArguments
|
5
|
+
module Checks
|
6
|
+
class Type < Base
|
7
|
+
DEFAULT_MESSAGE = lambda do |service_class_name:, internal_argument:, expected_type:, given_type:|
|
8
|
+
"The \"#{internal_argument.name}\" internal argument on \"#{service_class_name}\" must be of type " \
|
9
|
+
"\"#{expected_type}\" but was \"#{given_type}\""
|
10
|
+
end
|
11
|
+
|
12
|
+
private_constant :DEFAULT_MESSAGE
|
13
|
+
|
14
|
+
def self.check!(...)
|
15
|
+
new(...).check!
|
16
|
+
end
|
17
|
+
|
18
|
+
##########################################################################
|
19
|
+
|
20
|
+
def initialize(context:, internal_argument:, value:)
|
21
|
+
super()
|
22
|
+
|
23
|
+
@context = context
|
24
|
+
@internal_argument = internal_argument
|
25
|
+
@value = value
|
26
|
+
end
|
27
|
+
|
28
|
+
def check!
|
29
|
+
return if prepared_types.any? { |type| @value.is_a?(type) }
|
30
|
+
|
31
|
+
raise_error_with(
|
32
|
+
DEFAULT_MESSAGE,
|
33
|
+
service_class_name: @context.class.name,
|
34
|
+
internal_argument: @internal_argument,
|
35
|
+
expected_type: prepared_types.join(", "),
|
36
|
+
given_type: @value.class.name
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def prepared_types
|
43
|
+
@prepared_types ||=
|
44
|
+
Array(@internal_argument.types).map do |type|
|
45
|
+
if type.is_a?(String)
|
46
|
+
Object.const_get(type)
|
47
|
+
else
|
48
|
+
type
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Servactory
|
4
|
+
module InternalArguments
|
5
|
+
class Collection
|
6
|
+
# NOTE: http://words.steveklabnik.com/beware-subclassing-ruby-core-classes
|
7
|
+
extend Forwardable
|
8
|
+
def_delegators :@collection, :<<, :each, :map
|
9
|
+
|
10
|
+
def initialize(*)
|
11
|
+
@collection = []
|
12
|
+
end
|
13
|
+
|
14
|
+
def names
|
15
|
+
map(&:name)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Servactory
|
4
|
+
module InternalArguments
|
5
|
+
module DSL
|
6
|
+
def self.included(base)
|
7
|
+
base.extend(ClassMethods)
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
private
|
12
|
+
|
13
|
+
def internal(name, **options)
|
14
|
+
collection_of_internal_arguments << InternalArgument.new(name, **options)
|
15
|
+
end
|
16
|
+
|
17
|
+
def collection_of_internal_arguments
|
18
|
+
@collection_of_internal_arguments ||= Collection.new
|
19
|
+
end
|
20
|
+
|
21
|
+
def internal_arguments_workbench
|
22
|
+
@internal_arguments_workbench ||= Workbench.work_with(collection_of_internal_arguments)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Servactory
|
4
|
+
module InternalArguments
|
5
|
+
class InternalArgument
|
6
|
+
attr_reader :name,
|
7
|
+
:types,
|
8
|
+
:required
|
9
|
+
|
10
|
+
def initialize(name, type:, **options)
|
11
|
+
@name = name
|
12
|
+
@types = Array(type)
|
13
|
+
|
14
|
+
@required = options.fetch(:required, true)
|
15
|
+
end
|
16
|
+
|
17
|
+
def options_for_checks
|
18
|
+
{
|
19
|
+
types:,
|
20
|
+
required:
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
def required?
|
25
|
+
required
|
26
|
+
end
|
27
|
+
|
28
|
+
def optional?
|
29
|
+
!required
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Servactory
|
4
|
+
module InternalArguments
|
5
|
+
module Tools
|
6
|
+
class Prepare
|
7
|
+
def self.prepare(...)
|
8
|
+
new(...).prepare
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(context, collection_of_internal_arguments)
|
12
|
+
@context = context
|
13
|
+
@collection_of_internal_arguments = collection_of_internal_arguments
|
14
|
+
end
|
15
|
+
|
16
|
+
def prepare
|
17
|
+
@collection_of_internal_arguments.each do |internal_argument|
|
18
|
+
create_instance_variable_for(internal_argument)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def create_instance_variable_for(internal_argument)
|
25
|
+
@context.instance_variable_set(:"@#{internal_argument.name}", nil)
|
26
|
+
|
27
|
+
@context.class.class_eval(context_internal_argument_template_for(internal_argument))
|
28
|
+
end
|
29
|
+
|
30
|
+
# EXAMPLE:
|
31
|
+
#
|
32
|
+
# define_method(:user=) do |value|;
|
33
|
+
# Servactory::InternalArguments::Checks::Type.check!( context: self, internal_argument:, value: );
|
34
|
+
#
|
35
|
+
# instance_variable_set(:@user, value);
|
36
|
+
# end;
|
37
|
+
#
|
38
|
+
# private attr_reader :user;
|
39
|
+
#
|
40
|
+
def context_internal_argument_template_for(internal_argument)
|
41
|
+
<<-RUBY.squish
|
42
|
+
define_method(:#{internal_argument.name}=) do |value|;
|
43
|
+
Servactory::InternalArguments::Checks::Type.check!(
|
44
|
+
context: self,
|
45
|
+
internal_argument:,
|
46
|
+
value:
|
47
|
+
);
|
48
|
+
|
49
|
+
instance_variable_set(:@#{internal_argument.name}, value);
|
50
|
+
end;
|
51
|
+
|
52
|
+
private attr_reader :#{internal_argument.name};
|
53
|
+
RUBY
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Servactory
|
4
|
+
module InternalArguments
|
5
|
+
class Workbench
|
6
|
+
def self.work_with(...)
|
7
|
+
new(...)
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(collection_of_internal_arguments)
|
11
|
+
@collection_of_internal_arguments = collection_of_internal_arguments
|
12
|
+
end
|
13
|
+
|
14
|
+
def assign(context:)
|
15
|
+
@context = context
|
16
|
+
end
|
17
|
+
|
18
|
+
def prepare
|
19
|
+
Tools::Prepare.prepare(context, collection_of_internal_arguments)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
attr_reader :context, :collection_of_internal_arguments
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Servactory
|
4
|
+
module OutputArguments
|
5
|
+
module Checks
|
6
|
+
class Base
|
7
|
+
protected
|
8
|
+
|
9
|
+
def raise_error_with(message, **arguments)
|
10
|
+
message = message.call(**arguments) if message.is_a?(Proc)
|
11
|
+
|
12
|
+
raise Servactory.configuration.output_argument_error_class, message
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Servactory
|
4
|
+
module OutputArguments
|
5
|
+
module Checks
|
6
|
+
class Type < Base
|
7
|
+
DEFAULT_MESSAGE = lambda do |service_class_name:, output_argument:, expected_type:, given_type:|
|
8
|
+
"The \"#{output_argument.name}\" output argument on \"#{service_class_name}\" must be of type " \
|
9
|
+
"\"#{expected_type}\" but was \"#{given_type}\""
|
10
|
+
end
|
11
|
+
|
12
|
+
private_constant :DEFAULT_MESSAGE
|
13
|
+
|
14
|
+
def self.check!(...)
|
15
|
+
new(...).check!
|
16
|
+
end
|
17
|
+
|
18
|
+
##########################################################################
|
19
|
+
|
20
|
+
def initialize(context:, output_argument:, value:)
|
21
|
+
super()
|
22
|
+
|
23
|
+
@context = context
|
24
|
+
@output_argument = output_argument
|
25
|
+
@value = value
|
26
|
+
end
|
27
|
+
|
28
|
+
def check!
|
29
|
+
return if prepared_types.any? { |type| @value.is_a?(type) }
|
30
|
+
|
31
|
+
raise_error_with(
|
32
|
+
DEFAULT_MESSAGE,
|
33
|
+
service_class_name: @context.class.name,
|
34
|
+
output_argument: @output_argument,
|
35
|
+
expected_type: prepared_types.join(", "),
|
36
|
+
given_type: @value.class.name
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def prepared_types
|
43
|
+
@prepared_types ||=
|
44
|
+
Array(@output_argument.types).map do |type|
|
45
|
+
if type.is_a?(String)
|
46
|
+
Object.const_get(type)
|
47
|
+
else
|
48
|
+
type
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Servactory
|
4
|
+
module OutputArguments
|
5
|
+
class Collection
|
6
|
+
# NOTE: http://words.steveklabnik.com/beware-subclassing-ruby-core-classes
|
7
|
+
extend Forwardable
|
8
|
+
def_delegators :@collection, :<<, :each, :map
|
9
|
+
|
10
|
+
def initialize(*)
|
11
|
+
@collection = []
|
12
|
+
end
|
13
|
+
|
14
|
+
def names
|
15
|
+
map(&:name)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|