servactory 1.4.4 → 1.4.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 54a713971d52bebd38a97f473eb942be19f5c4029604aa26f0729cb1dc40f24a
4
- data.tar.gz: 1b368e874cdf3c502328fe3dbf71758a3c0821140c1b0e9a595f6622b41ec1bc
3
+ metadata.gz: 995ff46dfe5e3620a05d0bbe4b21f515de2b63e593f971e1ec906721cd4bfb6d
4
+ data.tar.gz: 9df30c884f28760025da0a9f1e68ccb12a42e5cea702602c086fd0b31212da62
5
5
  SHA512:
6
- metadata.gz: c2e412f4e06a1a21aa70a43a0f898f6d5fc0adcca1eaf7922edb80aa719313b9c2325d83ef41e34eda9c8cacc988e60b076938e23b1ff1e709d50aee9ce0f0b1
7
- data.tar.gz: d871cef64e8249b89572f6b97e9fdd9410632d20a393ea77d59f36481acc7f0207bfa26e6c79749a2031962927b965955986f257ce298d554d8289f2f85bfaf4
6
+ metadata.gz: 6bf7a7a0b667c3dce0926747b36fa85dc7cb6452e54cf7a51367918f8530cd09996a0d21e5d19d0fc06bc91cdfa3c00f2f0a464b9816738b9ea935b88c0d997b
7
+ data.tar.gz: 8b29bf3059b7420492c63321737eca8b9f79deea94ce52dfb5dd203c70f0a8fecbbeb29b55e2eb73a687220f85cbb71a5bd85664cd5b45a404e2cbe7ed168a42
data/README.md CHANGED
@@ -14,10 +14,13 @@ A set of tools for building reliable services of any complexity.
14
14
  - [Preparation](#preparation)
15
15
  - [Usage](#usage)
16
16
  - [Minimal example](#minimal-example)
17
+ - [Call](#call)
18
+ - [Result](#result)
17
19
  - [Input attributes](#input-attributes)
18
20
  - [Isolated usage](#isolated-usage)
19
21
  - [As an internal argument](#isolated-usage)
20
22
  - [Optional inputs](#optional-inputs)
23
+ - [As (internal name)](#as-internal-name)
21
24
  - [An array of specific values](#an-array-of-specific-values)
22
25
  - [Inclusion](#inclusion)
23
26
  - [Must](#must)
@@ -25,7 +28,7 @@ A set of tools for building reliable services of any complexity.
25
28
  - [Internal attributes](#internal-attributes)
26
29
  - [Stage](#stage)
27
30
  - [Failures](#failures)
28
- - [Result](#result)
31
+ - [I18n](#i18n)
29
32
  - [Testing](#testing)
30
33
  - [Thanks](#thanks)
31
34
  - [Contributing](#contributing)
@@ -111,6 +114,47 @@ end
111
114
 
112
115
  [More examples](https://github.com/afuno/servactory/tree/main/examples/usual)
113
116
 
117
+ ### Call
118
+
119
+ Services can only be called via `.call` and `.call!` methods.
120
+
121
+ The `.call` method will only fail if it catches an exception in the input arguments.
122
+ Internal and output attributes, as well as methods for failures - all this will be collected in the result.
123
+
124
+ The `.call!` method will fail if it catches any exception.
125
+
126
+ #### Via .call
127
+
128
+ ```ruby
129
+ UsersService::Accept.call(user: User.first)
130
+ ```
131
+
132
+ #### Via .call!
133
+
134
+ ```ruby
135
+ UsersService::Accept.call!(user: User.first)
136
+ ```
137
+
138
+ ### Result
139
+
140
+ All services have the result of their work. For example, in case of success this call:
141
+
142
+ ```ruby
143
+ service_result = UsersService::Accept.call!(user: User.first)
144
+ ```
145
+
146
+ Will return this:
147
+
148
+ ```ruby
149
+ #<Servactory::Result:0x0000000107ad9e88 @user="...">
150
+ ```
151
+
152
+ And then you can work with this result, for example, in this way:
153
+
154
+ ```ruby
155
+ Notification::SendJob.perform_later(service_result.user.id)
156
+ ```
157
+
114
158
  ### Input attributes
115
159
 
116
160
  #### Isolated usage
@@ -163,7 +207,7 @@ class UsersService::Create < ApplicationService::Base
163
207
  end
164
208
  ```
165
209
 
166
- #### As
210
+ #### As (internal name)
167
211
 
168
212
  This option changes the name of the input within the service.
169
213
 
@@ -346,25 +390,11 @@ def check!
346
390
  end
347
391
  ```
348
392
 
349
- ### Result
350
-
351
- All services have the result of their work. For example, in case of success this call:
352
-
353
- ```ruby
354
- service_result = NotificationService::Create.call!(user: User.first)
355
- ```
356
-
357
- Will return this:
393
+ ## I18n
358
394
 
359
- ```ruby
360
- #<Servactory::Result:0x0000000112c00748 @notification=...>
361
- ```
362
-
363
- And then you can work with this result, for example, in this way:
395
+ All texts are stored in the localization file. All texts can be changed or supplemented by new locales.
364
396
 
365
- ```ruby
366
- Notification::SendJob.perform_later(service_result.notification.id)
367
- ```
397
+ [See en.yml file](https://github.com/afuno/servactory/tree/main/config/locales/en.yml)
368
398
 
369
399
  ## Testing
370
400
 
@@ -0,0 +1,33 @@
1
+ en:
2
+ servactory:
3
+ input_arguments:
4
+ checks:
5
+ inclusion:
6
+ default_error: "[%{service_class_name}] Wrong value in `%{input_name}`, must be one of `%{input_inclusion}`"
7
+ must:
8
+ default_error: "[%{service_class_name}] Input `%{input_name}` must \"%{code}\""
9
+ syntax_error: "[%{service_class_name}] Syntax error inside `%{code}` of `%{input_name}` input"
10
+ required:
11
+ default_error:
12
+ default: "[%{service_class_name}] Required input `%{input_name}` is missing"
13
+ for_array: "[%{service_class_name}] Required element in input array `%{input_name}` is missing"
14
+ type:
15
+ default_error:
16
+ default: "[%{service_class_name}] Wrong type of input `%{input_name}`, expected `%{expected_type}`, got `%{given_type}`"
17
+ for_array: "[%{service_class_name}] Wrong type in input array `%{input_name}`, expected `%{expected_type}`"
18
+ tools:
19
+ find_unnecessary:
20
+ error: "[%{service_class_name}] Unexpected attributes: `%{unnecessary_attributes}`"
21
+ rules:
22
+ error: "[%{service_class_name}] Conflict in `%{input_name}` input options: `%{conflict_code}`"
23
+ internal_arguments:
24
+ checks:
25
+ type:
26
+ default_error: "[%{service_class_name}] Wrong type of internal argument `%{internal_argument_name}`, expected `%{expected_type}`, got `%{given_type}`"
27
+ output_arguments:
28
+ checks:
29
+ type:
30
+ default_error: "[%{service_class_name}] Wrong type of output argument `%{output_argument_name}`, expected `%{expected_type}`, got `%{given_type}`"
31
+ tools:
32
+ conflicts:
33
+ error: "[%{service_class_name}] Conflict between internal and output attributes `%{overlapping_attributes}`"
@@ -28,6 +28,29 @@ module Servactory
28
28
  )
29
29
  end
30
30
 
31
+ def call(arguments = {}) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
32
+ @context_store = Store.new(self)
33
+
34
+ assign_data_with(arguments)
35
+
36
+ input_arguments_workbench.find_unnecessary!
37
+ input_arguments_workbench.check_rules!
38
+ output_arguments_workbench.find_conflicts_in!(
39
+ collection_of_internal_arguments: collection_of_internal_arguments
40
+ )
41
+
42
+ prepare_data
43
+
44
+ input_arguments_workbench.check!
45
+
46
+ stage_handyman.run_methods!
47
+
48
+ Servactory::Result.prepare_for(
49
+ context: context_store.context,
50
+ collection_of_output_arguments: collection_of_output_arguments
51
+ )
52
+ end
53
+
31
54
  private
32
55
 
33
56
  attr_reader :context_store
@@ -6,7 +6,7 @@ module Servactory
6
6
  class Errors
7
7
  # NOTE: http://words.steveklabnik.com/beware-subclassing-ruby-core-classes
8
8
  extend Forwardable
9
- def_delegators :@collection, :<<, :filter, :reject, :empty?, :first
9
+ def_delegators :@collection, :<<, :to_a, :filter, :reject, :empty?, :first
10
10
 
11
11
  def initialize(collection = Set.new)
12
12
  @collection = collection
@@ -9,7 +9,7 @@ module Servactory
9
9
  def add_error(message, **arguments)
10
10
  message = message.call(**arguments) if message.is_a?(Proc)
11
11
 
12
- errors.add(message)
12
+ errors << message
13
13
  end
14
14
 
15
15
  private
@@ -6,7 +6,7 @@ module Servactory
6
6
  class Errors
7
7
  # NOTE: http://words.steveklabnik.com/beware-subclassing-ruby-core-classes
8
8
  extend Forwardable
9
- def_delegators :@collection, :add, :to_a
9
+ def_delegators :@collection, :<<, :to_a
10
10
 
11
11
  def initialize(*)
12
12
  @collection = Set.new
@@ -4,8 +4,14 @@ module Servactory
4
4
  module InputArguments
5
5
  module Checks
6
6
  class Inclusion < Base
7
- DEFAULT_MESSAGE = lambda do |service_class_name:, input:|
8
- "[#{service_class_name}] Wrong value in `#{input.name}`, must be one of `#{input.inclusion[:in]}`"
7
+ DEFAULT_MESSAGE = lambda do |service_class_name:, input:, value:|
8
+ I18n.t(
9
+ "servactory.input_arguments.checks.inclusion.default_error",
10
+ service_class_name: service_class_name,
11
+ input_name: input.name,
12
+ input_inclusion: input.inclusion[:in],
13
+ value: value
14
+ )
9
15
  end
10
16
 
11
17
  private_constant :DEFAULT_MESSAGE
@@ -36,7 +42,8 @@ module Servactory
36
42
  add_error(
37
43
  DEFAULT_MESSAGE,
38
44
  service_class_name: @context.class.name,
39
- input: @input
45
+ input: @input,
46
+ value: @value
40
47
  )
41
48
  end
42
49
  end
@@ -4,12 +4,28 @@ module Servactory
4
4
  module InputArguments
5
5
  module Checks
6
6
  class Must < Base
7
- DEFAULT_MESSAGE = lambda do |service_class_name:, input:, code:|
8
- "[#{service_class_name}] Input `#{input.name}` " \
9
- "must \"#{code.to_s.humanize(capitalize: false, keep_id_suffix: true)}\""
7
+ DEFAULT_MESSAGE = lambda do |service_class_name:, input:, value:, code:|
8
+ I18n.t(
9
+ "servactory.input_arguments.checks.must.default_error",
10
+ service_class_name: service_class_name,
11
+ input_name: input.name,
12
+ value: value,
13
+ code: code
14
+ )
15
+ end
16
+
17
+ SYNTAX_ERROR_MESSAGE = lambda do |service_class_name:, input:, value:, code:, exception_message:|
18
+ I18n.t(
19
+ "servactory.input_arguments.checks.must.syntax_error",
20
+ service_class_name: service_class_name,
21
+ input_name: input.name,
22
+ value: value,
23
+ code: code,
24
+ exception_message: exception_message
25
+ )
10
26
  end
11
27
 
12
- private_constant :DEFAULT_MESSAGE
28
+ private_constant :DEFAULT_MESSAGE, :SYNTAX_ERROR_MESSAGE
13
29
 
14
30
  def self.check(context:, input:, value:, check_key:, check_options:)
15
31
  return unless should_be_checked_for?(input, check_key)
@@ -39,9 +55,10 @@ module Servactory
39
55
  next if message.blank?
40
56
 
41
57
  add_error(
42
- DEFAULT_MESSAGE,
58
+ message,
43
59
  service_class_name: @context.class.name,
44
60
  input: @input,
61
+ value: @value,
45
62
  code: code
46
63
  )
47
64
  end
@@ -58,16 +75,13 @@ module Servactory
58
75
 
59
76
  message.presence || DEFAULT_MESSAGE
60
77
  rescue StandardError => e
61
- message_text =
62
- "[#{@context.class.name}] Syntax error inside `#{code}` of `#{@input.name}` input"
63
-
64
- puts "#{message_text}: #{e}"
65
-
66
78
  add_error(
67
- message_text,
79
+ SYNTAX_ERROR_MESSAGE,
68
80
  service_class_name: @context.class.name,
69
81
  input: @input,
70
- code: code
82
+ value: @value,
83
+ code: code,
84
+ exception_message: e.message
71
85
  )
72
86
  end
73
87
  end
@@ -5,11 +5,14 @@ module Servactory
5
5
  module Checks
6
6
  class Required < Base
7
7
  DEFAULT_MESSAGE = lambda do |service_class_name:, input:, value:|
8
- if input.array? && value.present?
9
- "[#{service_class_name}] Required element in input array `#{input.name}` is missing"
10
- else
11
- "[#{service_class_name}] Required input `#{input.name}` is missing"
12
- end
8
+ i18n_key = "servactory.input_arguments.checks.required.default_error."
9
+ i18n_key += input.array? && value.present? ? "for_array" : "default"
10
+
11
+ I18n.t(
12
+ i18n_key,
13
+ service_class_name: service_class_name,
14
+ input_name: input.name
15
+ )
13
16
  end
14
17
 
15
18
  private_constant :DEFAULT_MESSAGE
@@ -13,12 +13,22 @@ module Servactory
13
13
  elsif array_message.is_a?(String) && array_message.present?
14
14
  array_message
15
15
  else
16
- "[#{service_class_name}] Wrong type in input array `#{input.name}`, expected `#{expected_type}`"
16
+ I18n.t(
17
+ "servactory.input_arguments.checks.type.default_error.for_array",
18
+ service_class_name: service_class_name,
19
+ input_name: input.name,
20
+ expected_type: expected_type,
21
+ given_type: given_type
22
+ )
17
23
  end
18
24
  else
19
- "[#{service_class_name}] Wrong type of input `#{input.name}`, " \
20
- "expected `#{expected_type}`, " \
21
- "got `#{given_type}`"
25
+ I18n.t(
26
+ "servactory.input_arguments.checks.type.default_error.default",
27
+ service_class_name: service_class_name,
28
+ input_name: input.name,
29
+ expected_type: expected_type,
30
+ given_type: given_type
31
+ )
22
32
  end
23
33
  end
24
34
 
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Servactory
4
+ module InputArguments
5
+ class DefineInputConflict
6
+ attr_reader :content
7
+
8
+ def initialize(content:)
9
+ @content = content
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Servactory
4
+ module InputArguments
5
+ class DefineInputMethod
6
+ attr_reader :name,
7
+ :content
8
+
9
+ def initialize(name:, content:)
10
+ @name = name.to_sym
11
+ @content = content
12
+ end
13
+ end
14
+ end
15
+ end
@@ -55,22 +55,19 @@ module Servactory
55
55
  name: :required,
56
56
  input: self,
57
57
  check_class: Servactory::InputArguments::Checks::Required,
58
- define_input_methods: lambda do
59
- <<-RUBY
60
- def required?
61
- Servactory::Utils.boolean?(required[:is])
62
- end
63
-
64
- def optional?
65
- !required?
66
- end
67
- RUBY
68
- end,
69
- define_conflicts: lambda do
70
- <<-RUBY
71
- return :required_vs_default if required? && default_value_present?
72
- RUBY
73
- end,
58
+ define_input_methods: [
59
+ DefineInputMethod.new(
60
+ name: :required?,
61
+ content: ->(value:) { Servactory::Utils.boolean?(value[:is]) }
62
+ ),
63
+ DefineInputMethod.new(
64
+ name: :optional?,
65
+ content: ->(value:) { !Servactory::Utils.boolean?(value[:is]) }
66
+ )
67
+ ],
68
+ define_input_conflicts: [
69
+ DefineInputConflict.new(content: -> { return :required_vs_default if required? && default_value_present? })
70
+ ],
74
71
  need_for_checks: true,
75
72
  value_key: :is,
76
73
  value_fallback: true,
@@ -95,13 +92,12 @@ module Servactory
95
92
  name: :default,
96
93
  input: self,
97
94
  check_class: Servactory::InputArguments::Checks::Type,
98
- define_input_methods: lambda do
99
- <<-RUBY
100
- def default_value_present?
101
- !default.nil?
102
- end
103
- RUBY
104
- end,
95
+ define_input_methods: [
96
+ DefineInputMethod.new(
97
+ name: :default_value_present?,
98
+ content: ->(value:) { !value.nil? }
99
+ )
100
+ ],
105
101
  need_for_checks: true,
106
102
  value_fallback: nil,
107
103
  with_advanced_mode: false,
@@ -114,19 +110,16 @@ module Servactory
114
110
  name: :array,
115
111
  input: self,
116
112
  check_class: Servactory::InputArguments::Checks::Type,
117
- define_input_methods: lambda do
118
- <<-RUBY
119
- def array?
120
- Servactory::Utils.boolean?(array[:is])
121
- end
122
- RUBY
123
- end,
124
- define_conflicts: lambda do
125
- <<-RUBY
126
- return :array_vs_array if array? && types.include?(Array)
127
- return :array_vs_inclusion if array? && inclusion_present?
128
- RUBY
129
- end,
113
+ define_input_methods: [
114
+ DefineInputMethod.new(
115
+ name: :array?,
116
+ content: ->(value:) { Servactory::Utils.boolean?(value[:is]) }
117
+ )
118
+ ],
119
+ define_input_conflicts: [
120
+ DefineInputConflict.new(content: -> { return :array_vs_array if array? && types.include?(Array) }),
121
+ DefineInputConflict.new(content: -> { return :array_vs_inclusion if array? && inclusion_present? })
122
+ ],
130
123
  need_for_checks: false,
131
124
  value_key: :is,
132
125
  value_fallback: false,
@@ -139,13 +132,12 @@ module Servactory
139
132
  name: :inclusion,
140
133
  input: self,
141
134
  check_class: Servactory::InputArguments::Checks::Inclusion,
142
- define_input_methods: lambda do
143
- <<-RUBY
144
- def inclusion_present?
145
- inclusion[:in].is_a?(Array) && inclusion[:in].present?
146
- end
147
- RUBY
148
- end,
135
+ define_input_methods: [
136
+ DefineInputMethod.new(
137
+ name: :inclusion_present?,
138
+ content: ->(value:) { value[:in].is_a?(Array) && value[:in].present? }
139
+ )
140
+ ],
149
141
  need_for_checks: true,
150
142
  value_key: :in,
151
143
  value_fallback: nil,
@@ -158,13 +150,12 @@ module Servactory
158
150
  name: :must,
159
151
  input: self,
160
152
  check_class: Servactory::InputArguments::Checks::Must,
161
- define_input_methods: lambda do
162
- <<-RUBY
163
- def must_present?
164
- must.present?
165
- end
166
- RUBY
167
- end,
153
+ define_input_methods: [
154
+ DefineInputMethod.new(
155
+ name: :must_present?,
156
+ content: ->(value:) { value.present? }
157
+ )
158
+ ],
168
159
  need_for_checks: true,
169
160
  value_key: :is,
170
161
  value_fallback: nil,
@@ -178,13 +169,12 @@ module Servactory
178
169
  name: :internal,
179
170
  input: self,
180
171
  check_class: nil,
181
- define_input_methods: lambda do
182
- <<-RUBY
183
- def internal?
184
- Servactory::Utils.boolean?(internal[:is])
185
- end
186
- RUBY
187
- end,
172
+ define_input_methods: [
173
+ DefineInputMethod.new(
174
+ name: :internal?,
175
+ content: ->(value:) { Servactory::Utils.boolean?(value[:is]) }
176
+ )
177
+ ],
188
178
  need_for_checks: false,
189
179
  value_key: :is,
190
180
  value_fallback: false,
@@ -197,9 +187,7 @@ module Servactory
197
187
  end
198
188
 
199
189
  def conflict_code
200
- instance_eval(collection_of_options.defined_conflicts)
201
-
202
- nil
190
+ collection_of_options.defined_conflict_code
203
191
  end
204
192
 
205
193
  def with_conflicts?
@@ -9,7 +9,8 @@ module Servactory
9
9
 
10
10
  attr_reader :name,
11
11
  :check_class,
12
- :define_conflicts,
12
+ :define_input_methods,
13
+ :define_input_conflicts,
13
14
  :need_for_checks,
14
15
  :value_key,
15
16
  :value
@@ -24,13 +25,14 @@ module Servactory
24
25
  original_value: nil,
25
26
  value_key: nil,
26
27
  define_input_methods: nil,
27
- define_conflicts: nil,
28
+ define_input_conflicts: nil,
28
29
  with_advanced_mode: true,
29
30
  **options
30
31
  ) # do
31
32
  @name = name.to_sym
32
33
  @check_class = check_class
33
- @define_conflicts = define_conflicts
34
+ @define_input_methods = define_input_methods
35
+ @define_input_conflicts = define_input_conflicts
34
36
  @need_for_checks = need_for_checks
35
37
  @value_key = value_key
36
38
 
@@ -41,7 +43,7 @@ module Servactory
41
43
  with_advanced_mode: with_advanced_mode
42
44
  )
43
45
 
44
- input.instance_eval(define_input_methods.call) if define_input_methods.present?
46
+ prepare_input_methods_for(input)
45
47
  end
46
48
  # rubocop:enable Metrics/MethodLength
47
49
 
@@ -73,6 +75,22 @@ module Servactory
73
75
  DEFAULT_VALUE.call(key: value_key, value: value)
74
76
  end
75
77
  end
78
+
79
+ def prepare_input_methods_for(input)
80
+ input.instance_eval(define_input_methods_template) if define_input_methods_template.present?
81
+ end
82
+
83
+ def define_input_methods_template
84
+ return if @define_input_methods.blank?
85
+
86
+ @define_input_methods_template ||= @define_input_methods.map do |define_input_method|
87
+ <<-RUBY
88
+ def #{define_input_method.name}
89
+ #{define_input_method.content.call(value: @value)}
90
+ end
91
+ RUBY
92
+ end.join("\n")
93
+ end
76
94
  end
77
95
  end
78
96
  end
@@ -5,7 +5,7 @@ module Servactory
5
5
  class OptionsCollection
6
6
  # NOTE: http://words.steveklabnik.com/beware-subclassing-ruby-core-classes
7
7
  extend Forwardable
8
- def_delegators :@collection, :<<, :filter, :each, :map
8
+ def_delegators :@collection, :<<, :filter, :each, :map, :flat_map
9
9
 
10
10
  def initialize(*)
11
11
  @collection = Set.new
@@ -27,8 +27,12 @@ module Servactory
27
27
  end
28
28
  end
29
29
 
30
- def defined_conflicts
31
- map { |option| option.define_conflicts&.call }.reject(&:blank?).uniq.join
30
+ def defined_conflict_code
31
+ flat_map do |option|
32
+ option.define_input_conflicts&.map do |define_input_conflict|
33
+ define_input_conflict.content.call
34
+ end
35
+ end.reject(&:blank?).first
32
36
  end
33
37
  end
34
38
  end
@@ -17,8 +17,13 @@ module Servactory
17
17
  def check!
18
18
  return if unnecessary_attributes.empty?
19
19
 
20
- raise Servactory.configuration.input_argument_error_class,
21
- "[#{@context.class.name}] Unexpected attributes: `#{unnecessary_attributes.join(', ')}`"
20
+ message_text = I18n.t(
21
+ "servactory.input_arguments.tools.find_unnecessary.error",
22
+ service_class_name: @context.class.name,
23
+ unnecessary_attributes: unnecessary_attributes.join(", ")
24
+ )
25
+
26
+ raise Servactory.configuration.input_argument_error_class, message_text
22
27
  end
23
28
 
24
29
  private
@@ -28,9 +28,14 @@ module Servactory
28
28
  end
29
29
 
30
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}`"
31
+ message_text = I18n.t(
32
+ "servactory.input_arguments.tools.rules.error",
33
+ service_class_name: @context.class.name,
34
+ input_name: input_argument.name,
35
+ conflict_code: input_argument.conflict_code
36
+ )
37
+
38
+ raise Servactory.configuration.input_argument_error_class, message_text
34
39
  end
35
40
  end
36
41
  end
@@ -5,8 +5,13 @@ module Servactory
5
5
  module Checks
6
6
  class Type < Base
7
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}\""
8
+ I18n.t(
9
+ "servactory.internal_arguments.checks.type.default_error",
10
+ service_class_name: service_class_name,
11
+ internal_argument_name: internal_argument.name,
12
+ expected_type: expected_type,
13
+ given_type: given_type
14
+ )
10
15
  end
11
16
 
12
17
  private_constant :DEFAULT_MESSAGE
@@ -5,8 +5,13 @@ module Servactory
5
5
  module Checks
6
6
  class Type < Base
7
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}\""
8
+ I18n.t(
9
+ "servactory.output_arguments.checks.type.default_error",
10
+ service_class_name: service_class_name,
11
+ output_argument_name: output_argument.name,
12
+ expected_type: expected_type,
13
+ given_type: given_type
14
+ )
10
15
  end
11
16
 
12
17
  private_constant :DEFAULT_MESSAGE
@@ -17,9 +17,13 @@ module Servactory
17
17
  def check!
18
18
  return if overlapping_attributes.empty?
19
19
 
20
- raise Servactory.configuration.output_argument_error_class,
21
- "The \"#{@context.class.name}\" service contains internal attributes that " \
22
- "conflict with outputs: \"#{overlapping_attributes.join(', ')}\""
20
+ message_text = I18n.t(
21
+ "servactory.output_arguments.tools.conflicts.error",
22
+ service_class_name: @context.class.name,
23
+ overlapping_attributes: overlapping_attributes.join(", ")
24
+ )
25
+
26
+ raise Servactory.configuration.output_argument_error_class, message_text
23
27
  end
24
28
 
25
29
  private
@@ -9,13 +9,24 @@ module Servactory
9
9
  private
10
10
 
11
11
  def prepare_for(context:, collection_of_output_arguments:)
12
+ prepare_outputs_with(context: context, collection_of_output_arguments: collection_of_output_arguments)
13
+ prepare_statuses_with(context: context)
14
+
15
+ self
16
+ end
17
+
18
+ def prepare_outputs_with(context:, collection_of_output_arguments:)
12
19
  collection_of_output_arguments.each do |output|
13
20
  self.class.attr_reader(:"#{output.name}")
14
21
 
15
22
  instance_variable_set(:"@#{output.name}", context.instance_variable_get(:"@#{output.name}"))
16
23
  end
24
+ end
17
25
 
18
- self
26
+ def prepare_statuses_with(context:)
27
+ define_singleton_method(:errors) { context.errors }
28
+ define_singleton_method(:success?) { context.errors.empty? }
29
+ define_singleton_method(:failure?) { !context.errors.empty? }
19
30
  end
20
31
  end
21
32
  end
@@ -4,7 +4,7 @@ module Servactory
4
4
  module VERSION
5
5
  MAJOR = 1
6
6
  MINOR = 4
7
- PATCH = 4
7
+ PATCH = 6
8
8
 
9
9
  STRING = [MAJOR, MINOR, PATCH].join(".")
10
10
  end
metadata CHANGED
@@ -1,57 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: servactory
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.4
4
+ version: 1.4.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anton Sokolov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-05-15 00:00:00.000000000 Z
11
+ date: 2023-05-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: zeitwerk
14
+ name: activesupport
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '2.6'
19
+ version: '7.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '2.6'
26
+ version: '7.0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: activesupport
28
+ name: i18n
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '7.0'
33
+ version: '1.13'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '7.0'
40
+ version: '1.13'
41
41
  - !ruby/object:Gem::Dependency
42
- name: rake
42
+ name: zeitwerk
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '13.0'
48
- type: :development
47
+ version: '2.6'
48
+ type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '13.0'
54
+ version: '2.6'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: pry
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0.14'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '13.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '13.0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: rbs
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -159,6 +173,7 @@ extra_rdoc_files: []
159
173
  files:
160
174
  - README.md
161
175
  - Rakefile
176
+ - config/locales/en.yml
162
177
  - lib/servactory.rb
163
178
  - lib/servactory/base.rb
164
179
  - lib/servactory/configuration/dsl.rb
@@ -183,6 +198,8 @@ files:
183
198
  - lib/servactory/input_arguments/checks/required.rb
184
199
  - lib/servactory/input_arguments/checks/type.rb
185
200
  - lib/servactory/input_arguments/collection.rb
201
+ - lib/servactory/input_arguments/define_input_conflict.rb
202
+ - lib/servactory/input_arguments/define_input_method.rb
186
203
  - lib/servactory/input_arguments/dsl.rb
187
204
  - lib/servactory/input_arguments/input_argument.rb
188
205
  - lib/servactory/input_arguments/option.rb