servactory 3.1.0.rc2 → 3.1.0.rc4
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.
- checksums.yaml +4 -4
- data/LICENSE +21 -0
- data/README.md +7 -2
- data/config/locales/ja.yml +134 -0
- data/lib/generators/README.md +2 -2
- data/lib/generators/servactory/extension/USAGE +1 -1
- data/lib/generators/servactory/install/USAGE +2 -2
- data/lib/generators/servactory/rspec/USAGE +4 -4
- data/lib/generators/servactory/rspec/rspec_generator.rb +2 -2
- data/lib/generators/servactory/service/USAGE +5 -5
- data/lib/servactory/actions/collection.rb +21 -5
- data/lib/servactory/actions/stages/collection.rb +19 -1
- data/lib/servactory/actions/tools/rules.rb +1 -1
- data/lib/servactory/actions/tools/runner.rb +1 -1
- data/lib/servactory/configuration/collection_mode/class_names_collection.rb +1 -1
- data/lib/servactory/configuration/config.rb +16 -0
- data/lib/servactory/configuration/configurable.rb +7 -4
- data/lib/servactory/configuration/factory.rb +30 -3
- data/lib/servactory/configuration/hash_mode/class_names_collection.rb +5 -1
- data/lib/servactory/configuration/option_helpers/option_helpers_collection.rb +156 -29
- data/lib/servactory/context/warehouse/inputs.rb +1 -1
- data/lib/servactory/context/workspace/inputs.rb +2 -2
- data/lib/servactory/context/workspace/internals.rb +2 -2
- data/lib/servactory/context/workspace/outputs.rb +2 -2
- data/lib/servactory/context/workspace.rb +7 -7
- data/lib/servactory/info/builder.rb +4 -3
- data/lib/servactory/inputs/dsl.rb +5 -1
- data/lib/servactory/inputs/input.rb +1 -2
- data/lib/servactory/inputs/tools/validation.rb +10 -18
- data/lib/servactory/internals/dsl.rb +7 -1
- data/lib/servactory/maintenance/attributes/base.rb +4 -1
- data/lib/servactory/maintenance/attributes/collection.rb +61 -6
- data/lib/servactory/maintenance/options/collection.rb +71 -30
- data/lib/servactory/maintenance/options/option.rb +3 -12
- data/lib/servactory/maintenance/options/registrar.rb +3 -13
- data/lib/servactory/maintenance/validations/checkers/type.rb +23 -5
- data/lib/servactory/maintenance/validations/performer.rb +12 -23
- data/lib/servactory/outputs/dsl.rb +7 -1
- data/lib/servactory/result.rb +21 -8
- data/lib/servactory/test_kit/rspec/helpers/exception_validator.rb +112 -0
- data/lib/servactory/test_kit/rspec/helpers/input_validator.rb +3 -1
- data/lib/servactory/test_kit/rspec/helpers/mock_executor.rb +125 -125
- data/lib/servactory/test_kit/rspec/helpers/service_inputs_guard.rb +98 -0
- data/lib/servactory/test_kit/rspec/helpers/service_inputs_matcher.rb +75 -0
- data/lib/servactory/test_kit/rspec/helpers/service_mock_builder.rb +185 -50
- data/lib/servactory/test_kit/rspec/helpers/service_mock_config.rb +45 -10
- data/lib/servactory/test_kit/rspec/helpers/wrap_block_adapter.rb +74 -0
- data/lib/servactory/test_kit/rspec/helpers.rb +4 -0
- data/lib/servactory/test_kit/rspec/matchers/base/attribute_matcher.rb +72 -16
- data/lib/servactory/test_kit/rspec/matchers/base/message_expectation.rb +194 -0
- data/lib/servactory/test_kit/rspec/matchers/base/submatcher.rb +8 -0
- data/lib/servactory/test_kit/rspec/matchers/concerns/option_helper_rules.rb +148 -0
- data/lib/servactory/test_kit/rspec/matchers/concerns/proc_message.rb +117 -0
- data/lib/servactory/test_kit/rspec/matchers/concerns/required_message.rb +92 -0
- data/lib/servactory/test_kit/rspec/matchers/have_service_input_matcher.rb +27 -4
- data/lib/servactory/test_kit/rspec/matchers/have_service_internal_matcher.rb +10 -3
- data/lib/servactory/test_kit/rspec/matchers/submatchers/input/required_submatcher.rb +58 -23
- data/lib/servactory/test_kit/rspec/matchers/submatchers/input/valid_with_submatcher.rb +124 -59
- data/lib/servactory/test_kit/rspec/matchers/submatchers/shared/message_submatcher.rb +133 -39
- data/lib/servactory/test_kit/rspec/matchers/submatchers/shared/must_submatcher.rb +192 -17
- data/lib/servactory/test_kit/rspec/matchers/submatchers/shared/target_submatcher.rb +4 -2
- data/lib/servactory/test_kit/rspec/matchers/submatchers/shared/types_submatcher.rb +6 -0
- data/lib/servactory/test_kit/rspec/matchers.rb +15 -0
- data/lib/servactory/tool_kit/dynamic_options/consists_of.rb +34 -11
- data/lib/servactory/tool_kit/dynamic_options/format.rb +3 -4
- data/lib/servactory/tool_kit/dynamic_options/inclusion.rb +3 -3
- data/lib/servactory/tool_kit/dynamic_options/max.rb +3 -3
- data/lib/servactory/tool_kit/dynamic_options/min.rb +3 -3
- data/lib/servactory/tool_kit/dynamic_options/multiple_of.rb +35 -7
- data/lib/servactory/tool_kit/dynamic_options/must.rb +2 -3
- data/lib/servactory/tool_kit/dynamic_options/schema.rb +40 -25
- data/lib/servactory/tool_kit/dynamic_options/target.rb +4 -4
- data/lib/servactory/utils.rb +13 -3
- data/lib/servactory/version.rb +1 -1
- data/lib/servactory.rb +3 -4
- metadata +20 -4
|
@@ -72,7 +72,7 @@ module Servactory
|
|
|
72
72
|
# Specify format directly as the option value:
|
|
73
73
|
#
|
|
74
74
|
# ```ruby
|
|
75
|
-
# class
|
|
75
|
+
# class Users::Validate < ApplicationService::Base
|
|
76
76
|
# input :uuid, type: String, format: :uuid
|
|
77
77
|
# input :email, type: String, format: :email
|
|
78
78
|
# input :password, type: String, format: :password
|
|
@@ -179,7 +179,7 @@ module Servactory
|
|
|
179
179
|
#
|
|
180
180
|
# @param option_name [Symbol] The option name (default: :format)
|
|
181
181
|
# @param formats [Hash] Custom format definitions to merge with defaults
|
|
182
|
-
# @return [Servactory::Maintenance::
|
|
182
|
+
# @return [Servactory::Maintenance::Options::Helper]
|
|
183
183
|
def self.use(option_name = :format, formats: {})
|
|
184
184
|
instance = new(option_name)
|
|
185
185
|
instance.assign(formats)
|
|
@@ -232,7 +232,7 @@ module Servactory
|
|
|
232
232
|
# @param internal [Object, nil] Internal attribute if applicable
|
|
233
233
|
# @param output [Object, nil] Output attribute if applicable
|
|
234
234
|
# @return [Boolean, Array] true if valid, or [false, reason]
|
|
235
|
-
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
235
|
+
# rubocop:disable-next Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
236
236
|
def common_condition_with(value:, option:, input: nil, internal: nil, output: nil)
|
|
237
237
|
option_value = option.value&.to_sym
|
|
238
238
|
|
|
@@ -269,7 +269,6 @@ module Servactory
|
|
|
269
269
|
# Run validator callback.
|
|
270
270
|
option.properties.fetch(:validator, format_options.fetch(:validator)).call(value:)
|
|
271
271
|
end
|
|
272
|
-
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
273
272
|
|
|
274
273
|
########################################################################
|
|
275
274
|
|
|
@@ -20,7 +20,7 @@ module Servactory
|
|
|
20
20
|
# Use in your service definition:
|
|
21
21
|
#
|
|
22
22
|
# ```ruby
|
|
23
|
-
# class
|
|
23
|
+
# class Users::Create < ApplicationService::Base
|
|
24
24
|
# input :role, type: String, inclusion: { in: %w[admin user guest] }
|
|
25
25
|
# input :status, type: Symbol, inclusion: { in: [:active, :inactive] }
|
|
26
26
|
# input :level, type: Integer, inclusion: { in: [1, 2, 3, 4, 5] }
|
|
@@ -32,7 +32,7 @@ module Servactory
|
|
|
32
32
|
# Specify inclusion values directly:
|
|
33
33
|
#
|
|
34
34
|
# ```ruby
|
|
35
|
-
# class
|
|
35
|
+
# class Users::Create < ApplicationService::Base
|
|
36
36
|
# input :role, type: String, inclusion: %w[admin user guest]
|
|
37
37
|
# input :status, type: Symbol, inclusion: [:active, :inactive]
|
|
38
38
|
# input :level, type: Integer, inclusion: 1..10
|
|
@@ -87,7 +87,7 @@ module Servactory
|
|
|
87
87
|
# Creates an Inclusion validator instance.
|
|
88
88
|
#
|
|
89
89
|
# @param option_name [Symbol] The option name (default: :inclusion)
|
|
90
|
-
# @return [Servactory::Maintenance::
|
|
90
|
+
# @return [Servactory::Maintenance::Options::Helper]
|
|
91
91
|
def self.use(option_name = :inclusion)
|
|
92
92
|
instance = new(option_name, :in)
|
|
93
93
|
instance.must(:be_inclusion)
|
|
@@ -35,7 +35,7 @@ module Servactory
|
|
|
35
35
|
# Use in your service definition:
|
|
36
36
|
#
|
|
37
37
|
# ```ruby
|
|
38
|
-
# class
|
|
38
|
+
# class Data::Process < ApplicationService::Base
|
|
39
39
|
# input :count, type: Integer, max: 100
|
|
40
40
|
# input :name, type: String, max: 255
|
|
41
41
|
# input :items, type: Array, max: 50
|
|
@@ -47,7 +47,7 @@ module Servactory
|
|
|
47
47
|
# Specify maximum value directly:
|
|
48
48
|
#
|
|
49
49
|
# ```ruby
|
|
50
|
-
# class
|
|
50
|
+
# class Data::Process < ApplicationService::Base
|
|
51
51
|
# input :count, type: Integer, max: 100
|
|
52
52
|
# input :name, type: String, max: 255
|
|
53
53
|
# input :items, type: Array, max: 50
|
|
@@ -97,7 +97,7 @@ module Servactory
|
|
|
97
97
|
# Creates a Max validator instance.
|
|
98
98
|
#
|
|
99
99
|
# @param option_name [Symbol] The option name (default: :max)
|
|
100
|
-
# @return [Servactory::Maintenance::
|
|
100
|
+
# @return [Servactory::Maintenance::Options::Helper]
|
|
101
101
|
def self.use(option_name = :max)
|
|
102
102
|
new(option_name).must(:be_less_than_or_equal_to)
|
|
103
103
|
end
|
|
@@ -35,7 +35,7 @@ module Servactory
|
|
|
35
35
|
# Use in your service definition:
|
|
36
36
|
#
|
|
37
37
|
# ```ruby
|
|
38
|
-
# class
|
|
38
|
+
# class Data::Process < ApplicationService::Base
|
|
39
39
|
# input :age, type: Integer, min: 18
|
|
40
40
|
# input :password, type: String, min: 8
|
|
41
41
|
# input :tags, type: Array, min: 1
|
|
@@ -47,7 +47,7 @@ module Servactory
|
|
|
47
47
|
# Specify minimum value directly:
|
|
48
48
|
#
|
|
49
49
|
# ```ruby
|
|
50
|
-
# class
|
|
50
|
+
# class Data::Process < ApplicationService::Base
|
|
51
51
|
# input :age, type: Integer, min: 18
|
|
52
52
|
# input :password, type: String, min: 8
|
|
53
53
|
# input :tags, type: Array, min: 1
|
|
@@ -97,7 +97,7 @@ module Servactory
|
|
|
97
97
|
# Creates a Min validator instance.
|
|
98
98
|
#
|
|
99
99
|
# @param option_name [Symbol] The option name (default: :min)
|
|
100
|
-
# @return [Servactory::Maintenance::
|
|
100
|
+
# @return [Servactory::Maintenance::Options::Helper]
|
|
101
101
|
def self.use(option_name = :min)
|
|
102
102
|
new(option_name).must(:be_greater_than_or_equal_to)
|
|
103
103
|
end
|
|
@@ -35,7 +35,7 @@ module Servactory
|
|
|
35
35
|
# Use in your service definition:
|
|
36
36
|
#
|
|
37
37
|
# ```ruby
|
|
38
|
-
# class
|
|
38
|
+
# class Orders::Process < ApplicationService::Base
|
|
39
39
|
# input :quantity, type: Integer, multiple_of: 5
|
|
40
40
|
# input :price, type: Float, multiple_of: 0.25
|
|
41
41
|
# input :batch_size, type: Integer, multiple_of: 100
|
|
@@ -47,7 +47,7 @@ module Servactory
|
|
|
47
47
|
# Specify divisor directly:
|
|
48
48
|
#
|
|
49
49
|
# ```ruby
|
|
50
|
-
# class
|
|
50
|
+
# class Orders::Process < ApplicationService::Base
|
|
51
51
|
# input :quantity, type: Integer, multiple_of: 5
|
|
52
52
|
# input :price, type: Float, multiple_of: 0.25
|
|
53
53
|
# input :batch_size, type: Integer, multiple_of: 100
|
|
@@ -93,14 +93,22 @@ module Servactory
|
|
|
93
93
|
# ## Important Notes
|
|
94
94
|
#
|
|
95
95
|
# - Divisor must be a non-zero Numeric
|
|
96
|
-
# -
|
|
96
|
+
# - Integer, Rational and BigDecimal operands are checked exactly
|
|
97
|
+
# - Float operands are accepted when the remainder is within an epsilon
|
|
98
|
+
# tolerance of zero or of the divisor, scaled by the absolute value
|
|
99
|
+
# of the checked value
|
|
97
100
|
# - Returns false for non-numeric values
|
|
98
101
|
# - Provides specific error messages for blank and zero divisors
|
|
99
102
|
class MultipleOf < Must
|
|
103
|
+
# Relative tolerance for Float remainders, scaled by the absolute
|
|
104
|
+
# value of the checked value.
|
|
105
|
+
FLOAT_TOLERANCE = Float::EPSILON * 2
|
|
106
|
+
private_constant :FLOAT_TOLERANCE
|
|
107
|
+
|
|
100
108
|
# Creates a MultipleOf validator instance.
|
|
101
109
|
#
|
|
102
110
|
# @param option_name [Symbol] The option name (default: :multiple_of)
|
|
103
|
-
# @return [Servactory::Maintenance::
|
|
111
|
+
# @return [Servactory::Maintenance::Options::Helper]
|
|
104
112
|
def self.use(option_name = :multiple_of)
|
|
105
113
|
new(option_name).must(:be_multiple_of)
|
|
106
114
|
end
|
|
@@ -148,14 +156,34 @@ module Servactory
|
|
|
148
156
|
return false unless option.value.is_a?(Numeric)
|
|
149
157
|
return false if option.value.zero?
|
|
150
158
|
|
|
151
|
-
|
|
152
|
-
remainder = value % option.value
|
|
153
|
-
remainder.zero? || remainder.abs < Float::EPSILON * [value.abs, option.value.abs].max
|
|
159
|
+
multiple_of?(value, option.value)
|
|
154
160
|
else
|
|
155
161
|
false
|
|
156
162
|
end
|
|
157
163
|
end
|
|
158
164
|
|
|
165
|
+
# Checks whether value is a multiple of divisor.
|
|
166
|
+
#
|
|
167
|
+
# Exact for Integer, Rational and BigDecimal operands. When either
|
|
168
|
+
# operand is a Float, the remainder of the absolute operands counts
|
|
169
|
+
# as a multiple when it is within the tolerance of zero or of the
|
|
170
|
+
# divisor, with the tolerance scaled by the absolute value of the
|
|
171
|
+
# checked value.
|
|
172
|
+
#
|
|
173
|
+
# @param value [Numeric] Value to check
|
|
174
|
+
# @param divisor [Numeric] Non-zero divisor
|
|
175
|
+
# @return [Boolean] true if value is multiple of divisor
|
|
176
|
+
def multiple_of?(value, divisor)
|
|
177
|
+
return (value % divisor).zero? unless value.is_a?(Float) || divisor.is_a?(Float)
|
|
178
|
+
|
|
179
|
+
remainder = value.abs % divisor.abs
|
|
180
|
+
return true if remainder.zero?
|
|
181
|
+
return false unless remainder.finite? && divisor.finite?
|
|
182
|
+
|
|
183
|
+
tolerance = FLOAT_TOLERANCE * value.abs
|
|
184
|
+
remainder <= tolerance || divisor.abs - remainder <= tolerance
|
|
185
|
+
end
|
|
186
|
+
|
|
159
187
|
########################################################################
|
|
160
188
|
|
|
161
189
|
# Generates error message for input validation failure.
|
|
@@ -152,7 +152,7 @@ module Servactory
|
|
|
152
152
|
@body_fallback = body_fallback
|
|
153
153
|
end
|
|
154
154
|
|
|
155
|
-
# Creates an
|
|
155
|
+
# Creates an option helper for registration with Servactory.
|
|
156
156
|
#
|
|
157
157
|
# @param name [Symbol] Internal validation name
|
|
158
158
|
# @return [Servactory::Maintenance::Options::Helper]
|
|
@@ -221,7 +221,7 @@ module Servactory
|
|
|
221
221
|
#
|
|
222
222
|
# @param option [WorkOption] Parsed option data
|
|
223
223
|
# @return [Proc] Lambda that generates error message
|
|
224
|
-
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
224
|
+
# rubocop:disable-next Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
225
225
|
def must_content_message_with(option)
|
|
226
226
|
is_option_message_present = option.message.present?
|
|
227
227
|
is_option_message_proc = option.message.is_a?(Proc) if is_option_message_present
|
|
@@ -274,7 +274,6 @@ module Servactory
|
|
|
274
274
|
end
|
|
275
275
|
end
|
|
276
276
|
end
|
|
277
|
-
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
278
277
|
|
|
279
278
|
########################################################################
|
|
280
279
|
|
|
@@ -29,7 +29,7 @@ module Servactory
|
|
|
29
29
|
# Define schema in your service:
|
|
30
30
|
#
|
|
31
31
|
# ```ruby
|
|
32
|
-
# class
|
|
32
|
+
# class Users::Create < ApplicationService::Base
|
|
33
33
|
# input :user_data,
|
|
34
34
|
# type: Hash,
|
|
35
35
|
# schema: {
|
|
@@ -49,7 +49,7 @@ module Servactory
|
|
|
49
49
|
# Specify schema definition directly:
|
|
50
50
|
#
|
|
51
51
|
# ```ruby
|
|
52
|
-
# class
|
|
52
|
+
# class Users::Create < ApplicationService::Base
|
|
53
53
|
# input :user_data,
|
|
54
54
|
# type: Hash,
|
|
55
55
|
# schema: {
|
|
@@ -127,8 +127,9 @@ module Servactory
|
|
|
127
127
|
# Creates a Schema validator instance.
|
|
128
128
|
#
|
|
129
129
|
# @param option_name [Symbol] The option name (default: :schema)
|
|
130
|
-
# @param default_hash_mode_class_names [
|
|
131
|
-
#
|
|
130
|
+
# @param default_hash_mode_class_names [Servactory::Configuration::HashMode::ClassNamesCollection]
|
|
131
|
+
# Valid Hash-like types
|
|
132
|
+
# @return [Servactory::Maintenance::Options::Helper]
|
|
132
133
|
def self.use(option_name = :schema, default_hash_mode_class_names:)
|
|
133
134
|
instance = new(option_name, :is, false)
|
|
134
135
|
instance.assign(default_hash_mode_class_names)
|
|
@@ -137,7 +138,8 @@ module Servactory
|
|
|
137
138
|
|
|
138
139
|
# Assigns the list of valid Hash-compatible class names.
|
|
139
140
|
#
|
|
140
|
-
# @param default_hash_mode_class_names [
|
|
141
|
+
# @param default_hash_mode_class_names [Servactory::Configuration::HashMode::ClassNamesCollection]
|
|
142
|
+
# Hash-like types to accept
|
|
141
143
|
# @return [void]
|
|
142
144
|
def assign(default_hash_mode_class_names)
|
|
143
145
|
@default_hash_mode_class_names = default_hash_mode_class_names
|
|
@@ -179,13 +181,15 @@ module Servactory
|
|
|
179
181
|
# @param value [Object] Hash value to validate
|
|
180
182
|
# @param option [WorkOption] Schema configuration
|
|
181
183
|
# @return [Boolean, Array] true if valid, or [false, reason, meta]
|
|
182
|
-
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
184
|
+
# rubocop:disable-next Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
183
185
|
def common_condition_with(attribute:, value:, option:)
|
|
184
186
|
# Schema disabled, skip validation.
|
|
185
187
|
return true if option.value == false
|
|
186
188
|
|
|
187
189
|
# Attribute type must be Hash-compatible.
|
|
188
|
-
|
|
190
|
+
unless @default_hash_mode_class_names.intersect?(attribute.types)
|
|
191
|
+
return [false, :wrong_type, wrong_type_meta_for(attribute:)]
|
|
192
|
+
end
|
|
189
193
|
|
|
190
194
|
# Skip validation for blank optional values.
|
|
191
195
|
if value.blank? && ((attribute.input? && attribute.optional?) || attribute.internal? || attribute.output?)
|
|
@@ -206,7 +210,19 @@ module Servactory
|
|
|
206
210
|
|
|
207
211
|
[is_success, reason, meta]
|
|
208
212
|
end
|
|
209
|
-
|
|
213
|
+
|
|
214
|
+
# Builds failure metadata for an attribute whose type is not Hash-compatible.
|
|
215
|
+
#
|
|
216
|
+
# @param attribute [Object] The attribute being validated
|
|
217
|
+
# @return [Hash] Metadata with the Hash-compatible types as expected
|
|
218
|
+
# and the declared attribute types as given
|
|
219
|
+
def wrong_type_meta_for(attribute:)
|
|
220
|
+
{
|
|
221
|
+
key_name: nil,
|
|
222
|
+
expected_type: @default_hash_mode_class_names.to_a.join(", "),
|
|
223
|
+
given_type: attribute.types.join(", ")
|
|
224
|
+
}
|
|
225
|
+
end
|
|
210
226
|
|
|
211
227
|
# Recursively validates object against schema definition.
|
|
212
228
|
#
|
|
@@ -229,16 +245,18 @@ module Servactory
|
|
|
229
245
|
end
|
|
230
246
|
|
|
231
247
|
# Validate each schema field.
|
|
232
|
-
|
|
248
|
+
schema.each do |schema_key, schema_value|
|
|
233
249
|
attribute_type = schema_value.fetch(:type, String)
|
|
234
250
|
|
|
235
251
|
if attribute_type == Hash
|
|
236
252
|
# Recursively validate nested Hash.
|
|
237
|
-
validate_for!(
|
|
253
|
+
result = validate_for!(
|
|
238
254
|
object: object.fetch(schema_key, {}),
|
|
239
255
|
schema: schema_value.except(*RESERVED_OPTIONS),
|
|
240
256
|
root_schema_key: schema_key
|
|
241
257
|
)
|
|
258
|
+
|
|
259
|
+
return result unless result == true
|
|
242
260
|
else
|
|
243
261
|
is_success, given_type = validate_with(
|
|
244
262
|
object:,
|
|
@@ -250,12 +268,11 @@ module Servactory
|
|
|
250
268
|
|
|
251
269
|
next if is_success
|
|
252
270
|
|
|
253
|
-
[false, :wrong_element_type, { key_name: schema_key, expected_type: attribute_type, given_type: }]
|
|
271
|
+
return [false, :wrong_element_type, { key_name: schema_key, expected_type: attribute_type, given_type: }]
|
|
254
272
|
end
|
|
255
273
|
end
|
|
256
274
|
|
|
257
|
-
|
|
258
|
-
errors.compact.first || true
|
|
275
|
+
true
|
|
259
276
|
end
|
|
260
277
|
|
|
261
278
|
# Validates a single field against its type specification.
|
|
@@ -277,11 +294,11 @@ module Servactory
|
|
|
277
294
|
return true
|
|
278
295
|
end
|
|
279
296
|
|
|
280
|
-
value = object
|
|
297
|
+
value = object.fetch(schema_key, nil)
|
|
281
298
|
prepared_value = prepare_value_from(schema_value:, value:, required: attribute_required)
|
|
282
299
|
|
|
283
300
|
[
|
|
284
|
-
Array(attribute_type).
|
|
301
|
+
Array(attribute_type).any? { |type| prepared_value.is_a?(type) },
|
|
285
302
|
prepared_value.class.name
|
|
286
303
|
]
|
|
287
304
|
end
|
|
@@ -297,7 +314,7 @@ module Servactory
|
|
|
297
314
|
required || (
|
|
298
315
|
!required && !fetch_default_from(schema_value).nil?
|
|
299
316
|
) || (
|
|
300
|
-
!required && !object
|
|
317
|
+
!required && !object.fetch(schema_key, nil).nil?
|
|
301
318
|
)
|
|
302
319
|
end
|
|
303
320
|
|
|
@@ -330,19 +347,18 @@ module Servactory
|
|
|
330
347
|
# @param object [Hash] Object to modify
|
|
331
348
|
# @param schema [Hash] Schema definition
|
|
332
349
|
# @return [void]
|
|
333
|
-
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
350
|
+
# rubocop:disable-next Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
334
351
|
def prepare_object_with!(object:, schema:)
|
|
335
|
-
schema.
|
|
352
|
+
schema.each do |schema_key, schema_value|
|
|
336
353
|
attribute_type = schema_value.fetch(:type, String)
|
|
337
354
|
required = schema_value.fetch(:required, true)
|
|
338
|
-
object_value = object
|
|
355
|
+
object_value = object.fetch(schema_key, nil)
|
|
339
356
|
|
|
340
357
|
if attribute_type == Hash
|
|
341
358
|
# Apply nested Hash defaults.
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
object[schema_key] = default_value
|
|
359
|
+
if !required && !Servactory::Utils.value_present?(object_value)
|
|
360
|
+
default_value = schema_value.key?(:default) ? schema_value[:default].deep_dup : {}
|
|
361
|
+
object[schema_key] = default_value unless default_value.nil?
|
|
346
362
|
end
|
|
347
363
|
|
|
348
364
|
# Recursively prepare nested objects.
|
|
@@ -360,14 +376,13 @@ module Servactory
|
|
|
360
376
|
|
|
361
377
|
# Execute prepare callback if defined.
|
|
362
378
|
unless (input_prepare = schema_value[:prepare]).nil?
|
|
363
|
-
object[schema_key] = input_prepare.call(value: object
|
|
379
|
+
object[schema_key] = input_prepare.call(value: object.fetch(schema_key, nil))
|
|
364
380
|
end
|
|
365
381
|
|
|
366
382
|
object
|
|
367
383
|
end
|
|
368
384
|
end
|
|
369
385
|
end
|
|
370
|
-
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
371
386
|
|
|
372
387
|
########################################################################
|
|
373
388
|
########################################################################
|
|
@@ -37,8 +37,8 @@ module Servactory
|
|
|
37
37
|
# Use in your service definition:
|
|
38
38
|
#
|
|
39
39
|
# ```ruby
|
|
40
|
-
# class
|
|
41
|
-
# input :service_class, type: Class, target:
|
|
40
|
+
# class Orders::Process < ApplicationService::Base
|
|
41
|
+
# input :service_class, type: Class, target: Payments::Charge
|
|
42
42
|
# input :handler_class, type: Class, target: [CreateHandler, UpdateHandler]
|
|
43
43
|
# end
|
|
44
44
|
# ```
|
|
@@ -48,7 +48,7 @@ module Servactory
|
|
|
48
48
|
# Specify target class directly or as an array:
|
|
49
49
|
#
|
|
50
50
|
# ```ruby
|
|
51
|
-
# input :service_class, type: Class, target:
|
|
51
|
+
# input :service_class, type: Class, target: Payments::Charge
|
|
52
52
|
# input :handler_class, type: Class, target: [CreateHandler, UpdateHandler]
|
|
53
53
|
# ```
|
|
54
54
|
#
|
|
@@ -100,7 +100,7 @@ module Servactory
|
|
|
100
100
|
# Creates a Target validator instance.
|
|
101
101
|
#
|
|
102
102
|
# @param option_name [Symbol] The option name (default: :target)
|
|
103
|
-
# @return [Servactory::Maintenance::
|
|
103
|
+
# @return [Servactory::Maintenance::Options::Helper]
|
|
104
104
|
def self.use(option_name = :target)
|
|
105
105
|
instance = new(option_name, :in)
|
|
106
106
|
instance.must(:"be_#{option_name}")
|
data/lib/servactory/utils.rb
CHANGED
|
@@ -5,13 +5,17 @@ module Servactory
|
|
|
5
5
|
extend self
|
|
6
6
|
|
|
7
7
|
def adapt(data)
|
|
8
|
-
|
|
9
|
-
data = Servactory::Utils.send(:instance_variables_to_hash_from, data)
|
|
10
|
-
end
|
|
8
|
+
data = instance_variables_to_hash_from(data) if datory?(data)
|
|
11
9
|
|
|
12
10
|
data.symbolize_keys
|
|
13
11
|
end
|
|
14
12
|
|
|
13
|
+
# @param data [Object]
|
|
14
|
+
# @return [Boolean] True if #adapt accepts the data as service arguments
|
|
15
|
+
def adaptable?(data)
|
|
16
|
+
data.is_a?(Hash) || datory?(data)
|
|
17
|
+
end
|
|
18
|
+
|
|
15
19
|
def define_attribute_with(input: nil, internal: nil, output: nil)
|
|
16
20
|
return input if really_input?(input)
|
|
17
21
|
return internal if really_internal?(internal)
|
|
@@ -108,6 +112,12 @@ module Servactory
|
|
|
108
112
|
|
|
109
113
|
private
|
|
110
114
|
|
|
115
|
+
def datory?(data)
|
|
116
|
+
return false unless defined?(Datory::Base)
|
|
117
|
+
|
|
118
|
+
data.is_a?(Datory::Base)
|
|
119
|
+
end
|
|
120
|
+
|
|
111
121
|
def instance_variables_to_hash_from(data) # rubocop:disable Metrics/MethodLength
|
|
112
122
|
data.instance_variables.to_h do |key|
|
|
113
123
|
value = data.instance_variable_get(key)
|
data/lib/servactory/version.rb
CHANGED
data/lib/servactory.rb
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
require "zeitwerk"
|
|
4
4
|
|
|
5
|
+
require "forwardable"
|
|
6
|
+
|
|
5
7
|
require "stroma"
|
|
6
8
|
|
|
7
9
|
require "active_support/all"
|
|
@@ -10,16 +12,13 @@ require "uri"
|
|
|
10
12
|
|
|
11
13
|
loader = Zeitwerk::Loader.for_gem
|
|
12
14
|
loader.ignore("#{__dir__}/generators")
|
|
15
|
+
loader.ignore("#{__dir__}/servactory/engine.rb")
|
|
13
16
|
loader.ignore("#{__dir__}/servactory/test_kit/rspec")
|
|
14
17
|
loader.inflector.inflect(
|
|
15
18
|
"dsl" => "DSL"
|
|
16
19
|
)
|
|
17
20
|
loader.setup
|
|
18
21
|
|
|
19
|
-
# Eager load DSL to initialize Stroma::Registry.
|
|
20
|
-
# Registry must be populated before any service class is defined.
|
|
21
|
-
require_relative "servactory/dsl"
|
|
22
|
-
|
|
23
22
|
module Servactory; end
|
|
24
23
|
|
|
25
24
|
require "servactory/engine" if defined?(Rails::Engine)
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: servactory
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.1.0.
|
|
4
|
+
version: 3.1.0.rc4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Anton Sokolov
|
|
@@ -43,14 +43,20 @@ dependencies:
|
|
|
43
43
|
requirements:
|
|
44
44
|
- - ">="
|
|
45
45
|
- !ruby/object:Gem::Version
|
|
46
|
-
version: '0.
|
|
46
|
+
version: '0.5'
|
|
47
|
+
- - "<"
|
|
48
|
+
- !ruby/object:Gem::Version
|
|
49
|
+
version: '1.0'
|
|
47
50
|
type: :runtime
|
|
48
51
|
prerelease: false
|
|
49
52
|
version_requirements: !ruby/object:Gem::Requirement
|
|
50
53
|
requirements:
|
|
51
54
|
- - ">="
|
|
52
55
|
- !ruby/object:Gem::Version
|
|
53
|
-
version: '0.
|
|
56
|
+
version: '0.5'
|
|
57
|
+
- - "<"
|
|
58
|
+
- !ruby/object:Gem::Version
|
|
59
|
+
version: '1.0'
|
|
54
60
|
- !ruby/object:Gem::Dependency
|
|
55
61
|
name: zeitwerk
|
|
56
62
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -184,6 +190,7 @@ executables: []
|
|
|
184
190
|
extensions: []
|
|
185
191
|
extra_rdoc_files: []
|
|
186
192
|
files:
|
|
193
|
+
- LICENSE
|
|
187
194
|
- README.md
|
|
188
195
|
- Rakefile
|
|
189
196
|
- config/locales/de.yml
|
|
@@ -191,6 +198,7 @@ files:
|
|
|
191
198
|
- config/locales/es.yml
|
|
192
199
|
- config/locales/fr.yml
|
|
193
200
|
- config/locales/it.yml
|
|
201
|
+
- config/locales/ja.yml
|
|
194
202
|
- config/locales/ru.yml
|
|
195
203
|
- lib/generators/README.md
|
|
196
204
|
- lib/generators/servactory/base.rb
|
|
@@ -290,20 +298,28 @@ files:
|
|
|
290
298
|
- lib/servactory/test_kit/rspec/helpers/argument_matchers.rb
|
|
291
299
|
- lib/servactory/test_kit/rspec/helpers/concerns/error_messages.rb
|
|
292
300
|
- lib/servactory/test_kit/rspec/helpers/concerns/service_class_validation.rb
|
|
301
|
+
- lib/servactory/test_kit/rspec/helpers/exception_validator.rb
|
|
293
302
|
- lib/servactory/test_kit/rspec/helpers/fluent.rb
|
|
294
303
|
- lib/servactory/test_kit/rspec/helpers/input_validator.rb
|
|
295
304
|
- lib/servactory/test_kit/rspec/helpers/legacy.rb
|
|
296
305
|
- lib/servactory/test_kit/rspec/helpers/mock_executor.rb
|
|
297
306
|
- lib/servactory/test_kit/rspec/helpers/output_validator.rb
|
|
307
|
+
- lib/servactory/test_kit/rspec/helpers/service_inputs_guard.rb
|
|
308
|
+
- lib/servactory/test_kit/rspec/helpers/service_inputs_matcher.rb
|
|
298
309
|
- lib/servactory/test_kit/rspec/helpers/service_mock_builder.rb
|
|
299
310
|
- lib/servactory/test_kit/rspec/helpers/service_mock_config.rb
|
|
311
|
+
- lib/servactory/test_kit/rspec/helpers/wrap_block_adapter.rb
|
|
300
312
|
- lib/servactory/test_kit/rspec/matchers.rb
|
|
301
313
|
- lib/servactory/test_kit/rspec/matchers/base/attribute_matcher.rb
|
|
314
|
+
- lib/servactory/test_kit/rspec/matchers/base/message_expectation.rb
|
|
302
315
|
- lib/servactory/test_kit/rspec/matchers/base/submatcher.rb
|
|
303
316
|
- lib/servactory/test_kit/rspec/matchers/base/submatcher_context.rb
|
|
304
317
|
- lib/servactory/test_kit/rspec/matchers/base/submatcher_registry.rb
|
|
305
318
|
- lib/servactory/test_kit/rspec/matchers/concerns/attribute_data_access.rb
|
|
306
319
|
- lib/servactory/test_kit/rspec/matchers/concerns/error_message_builder.rb
|
|
320
|
+
- lib/servactory/test_kit/rspec/matchers/concerns/option_helper_rules.rb
|
|
321
|
+
- lib/servactory/test_kit/rspec/matchers/concerns/proc_message.rb
|
|
322
|
+
- lib/servactory/test_kit/rspec/matchers/concerns/required_message.rb
|
|
307
323
|
- lib/servactory/test_kit/rspec/matchers/concerns/value_comparison.rb
|
|
308
324
|
- lib/servactory/test_kit/rspec/matchers/have_service_input_matcher.rb
|
|
309
325
|
- lib/servactory/test_kit/rspec/matchers/have_service_internal_matcher.rb
|
|
@@ -357,7 +373,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
357
373
|
- !ruby/object:Gem::Version
|
|
358
374
|
version: '0'
|
|
359
375
|
requirements: []
|
|
360
|
-
rubygems_version: 4.0.
|
|
376
|
+
rubygems_version: 4.0.21
|
|
361
377
|
specification_version: 4
|
|
362
378
|
summary: A set of tools for building reliable services of any complexity
|
|
363
379
|
test_files: []
|