servactory 2.16.1 → 3.0.0.rc2
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/README.md +38 -9
- data/config/locales/de.yml +134 -0
- data/config/locales/en.yml +15 -0
- data/config/locales/es.yml +134 -0
- data/config/locales/fr.yml +134 -0
- data/config/locales/it.yml +134 -0
- data/config/locales/ru.yml +15 -0
- data/lib/generators/README.md +45 -0
- data/lib/generators/servactory/base.rb +82 -0
- data/lib/generators/servactory/extension/USAGE +54 -0
- data/lib/generators/servactory/extension/extension_generator.rb +41 -0
- data/lib/generators/servactory/extension/templates/extension.rb.tt +62 -0
- data/lib/generators/servactory/install/USAGE +27 -0
- data/lib/generators/servactory/install/install_generator.rb +94 -0
- data/lib/generators/servactory/{templates/services/application_service/base.rb → install/templates/application_service/base.rb.tt} +29 -19
- data/lib/generators/servactory/{templates/services/application_service/exceptions.rb → install/templates/application_service/exceptions.rb.tt} +1 -1
- data/lib/generators/servactory/{templates/services/application_service/result.rb → install/templates/application_service/result.rb.tt} +1 -1
- data/lib/generators/servactory/rspec/USAGE +46 -0
- data/lib/generators/servactory/rspec/rspec_generator.rb +95 -0
- data/lib/generators/servactory/rspec/templates/service_spec.rb.tt +58 -0
- data/lib/generators/servactory/service/USAGE +51 -0
- data/lib/generators/servactory/service/service_generator.rb +56 -0
- data/lib/generators/servactory/service/templates/service.rb.tt +22 -0
- data/lib/servactory/actions/collection.rb +56 -1
- data/lib/servactory/actions/dsl.rb +11 -11
- data/lib/servactory/actions/tools/rules.rb +1 -1
- data/lib/servactory/actions/tools/runner.rb +111 -28
- data/lib/servactory/base.rb +1 -7
- data/lib/servactory/configuration/actions/aliases/collection.rb +5 -0
- data/lib/servactory/configuration/actions/rescue_handlers/collection.rb +5 -0
- data/lib/servactory/configuration/actions/shortcuts/collection.rb +5 -0
- data/lib/servactory/configuration/collection_mode/class_names_collection.rb +5 -0
- data/lib/servactory/configuration/config.rb +36 -0
- data/lib/servactory/configuration/configurable.rb +95 -0
- data/lib/servactory/configuration/dsl.rb +3 -27
- data/lib/servactory/configuration/factory.rb +20 -20
- data/lib/servactory/configuration/hash_mode/class_names_collection.rb +5 -0
- data/lib/servactory/configuration/option_helpers/option_helpers_collection.rb +5 -0
- data/lib/servactory/context/warehouse/inputs.rb +2 -2
- 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 +11 -7
- data/lib/servactory/dsl.rb +10 -8
- data/lib/servactory/maintenance/attributes/tools/validation.rb +1 -1
- data/lib/servactory/result.rb +2 -2
- data/lib/servactory/test_kit/fake_type.rb +23 -0
- data/lib/servactory/test_kit/result.rb +45 -0
- data/lib/servactory/test_kit/rspec/helpers/argument_matchers.rb +97 -0
- data/lib/servactory/test_kit/rspec/helpers/concerns/error_messages.rb +179 -0
- data/lib/servactory/test_kit/rspec/helpers/concerns/service_class_validation.rb +74 -0
- data/lib/servactory/test_kit/rspec/helpers/fluent.rb +110 -0
- data/lib/servactory/test_kit/rspec/helpers/input_validator.rb +149 -0
- data/lib/servactory/test_kit/rspec/helpers/legacy.rb +228 -0
- data/lib/servactory/test_kit/rspec/helpers/mock_executor.rb +256 -0
- data/lib/servactory/test_kit/rspec/helpers/output_validator.rb +121 -0
- data/lib/servactory/test_kit/rspec/helpers/service_mock_builder.rb +422 -0
- data/lib/servactory/test_kit/rspec/helpers/service_mock_config.rb +129 -0
- data/lib/servactory/test_kit/rspec/helpers.rb +51 -84
- data/lib/servactory/test_kit/rspec/matchers/base/attribute_matcher.rb +324 -0
- data/lib/servactory/test_kit/rspec/matchers/base/submatcher.rb +133 -0
- data/lib/servactory/test_kit/rspec/matchers/base/submatcher_context.rb +101 -0
- data/lib/servactory/test_kit/rspec/matchers/base/submatcher_registry.rb +205 -0
- data/lib/servactory/test_kit/rspec/matchers/concerns/attribute_data_access.rb +100 -0
- data/lib/servactory/test_kit/rspec/matchers/concerns/error_message_builder.rb +106 -0
- data/lib/servactory/test_kit/rspec/matchers/concerns/value_comparison.rb +97 -0
- data/lib/servactory/test_kit/rspec/matchers/have_service_input_matcher.rb +89 -219
- data/lib/servactory/test_kit/rspec/matchers/have_service_internal_matcher.rb +74 -166
- data/lib/servactory/test_kit/rspec/matchers/have_service_output_matcher.rb +238 -0
- data/lib/servactory/test_kit/rspec/matchers/result/be_failure_service_matcher.rb +257 -0
- data/lib/servactory/test_kit/rspec/matchers/result/be_success_service_matcher.rb +185 -0
- data/lib/servactory/test_kit/rspec/matchers/submatchers/input/default_submatcher.rb +81 -0
- data/lib/servactory/test_kit/rspec/matchers/submatchers/input/optional_submatcher.rb +62 -0
- data/lib/servactory/test_kit/rspec/matchers/submatchers/input/required_submatcher.rb +93 -0
- data/lib/servactory/test_kit/rspec/matchers/submatchers/input/valid_with_submatcher.rb +271 -0
- data/lib/servactory/test_kit/rspec/matchers/submatchers/shared/consists_of_submatcher.rb +85 -0
- data/lib/servactory/test_kit/rspec/matchers/submatchers/shared/inclusion_submatcher.rb +120 -0
- data/lib/servactory/test_kit/rspec/matchers/submatchers/shared/message_submatcher.rb +115 -0
- data/lib/servactory/test_kit/rspec/matchers/submatchers/shared/must_submatcher.rb +82 -0
- data/lib/servactory/test_kit/rspec/matchers/submatchers/shared/schema_submatcher.rb +102 -0
- data/lib/servactory/test_kit/rspec/matchers/submatchers/shared/target_submatcher.rb +125 -0
- data/lib/servactory/test_kit/rspec/matchers/submatchers/shared/types_submatcher.rb +77 -0
- data/lib/servactory/test_kit/rspec/matchers.rb +126 -285
- data/lib/servactory/test_kit/utils/faker.rb +62 -2
- data/lib/servactory/tool_kit/dynamic_options/consists_of.rb +166 -0
- data/lib/servactory/tool_kit/dynamic_options/format.rb +195 -8
- data/lib/servactory/tool_kit/dynamic_options/inclusion.rb +219 -17
- data/lib/servactory/tool_kit/dynamic_options/max.rb +143 -0
- data/lib/servactory/tool_kit/dynamic_options/min.rb +143 -0
- data/lib/servactory/tool_kit/dynamic_options/multiple_of.rb +157 -8
- data/lib/servactory/tool_kit/dynamic_options/must.rb +194 -0
- data/lib/servactory/tool_kit/dynamic_options/schema.rb +226 -2
- data/lib/servactory/tool_kit/dynamic_options/target.rb +248 -0
- data/lib/servactory/version.rb +4 -4
- data/lib/servactory.rb +6 -0
- metadata +57 -48
- data/lib/generators/servactory/install_generator.rb +0 -21
- data/lib/generators/servactory/rspec_generator.rb +0 -88
- data/lib/generators/servactory/service_generator.rb +0 -49
- data/lib/servactory/configuration/setup.rb +0 -97
- data/lib/servactory/test_kit/rspec/matchers/have_service_attribute_matchers/consists_of_matcher.rb +0 -68
- data/lib/servactory/test_kit/rspec/matchers/have_service_attribute_matchers/inclusion_matcher.rb +0 -73
- data/lib/servactory/test_kit/rspec/matchers/have_service_attribute_matchers/message_matcher.rb +0 -91
- data/lib/servactory/test_kit/rspec/matchers/have_service_attribute_matchers/must_matcher.rb +0 -72
- data/lib/servactory/test_kit/rspec/matchers/have_service_attribute_matchers/schema_matcher.rb +0 -92
- data/lib/servactory/test_kit/rspec/matchers/have_service_attribute_matchers/types_matcher.rb +0 -72
- data/lib/servactory/test_kit/rspec/matchers/have_service_input_matchers/default_matcher.rb +0 -69
- data/lib/servactory/test_kit/rspec/matchers/have_service_input_matchers/optional_matcher.rb +0 -63
- data/lib/servactory/test_kit/rspec/matchers/have_service_input_matchers/required_matcher.rb +0 -81
- data/lib/servactory/test_kit/rspec/matchers/have_service_input_matchers/valid_with_matcher.rb +0 -199
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
it:
|
|
2
|
+
servactory:
|
|
3
|
+
common:
|
|
4
|
+
undefined_method:
|
|
5
|
+
missing_name: "[%{service_class_name}] %{error_text}"
|
|
6
|
+
methods:
|
|
7
|
+
call:
|
|
8
|
+
not_used: "[%{service_class_name}] Niente da eseguire. Usa `make` o crea un metodo `call`."
|
|
9
|
+
cannot_be_overwritten: "[%{service_class_name}] I seguenti metodi non possono essere sovrascritti: %{list_of_methods}"
|
|
10
|
+
inputs:
|
|
11
|
+
undefined:
|
|
12
|
+
for_fetch: "[%{service_class_name}] Attributo di input non definito `%{input_name}`"
|
|
13
|
+
for_assign: "[%{service_class_name}] Attributo di input non definito `%{input_name}`"
|
|
14
|
+
validations:
|
|
15
|
+
must:
|
|
16
|
+
default_error: "[%{service_class_name}] L'input `%{input_name}` deve \"%{code}\""
|
|
17
|
+
syntax_error: "[%{service_class_name}] Errore di sintassi in `%{code}` dell'input `%{input_name}`: %{exception_message}"
|
|
18
|
+
dynamic_options:
|
|
19
|
+
consists_of:
|
|
20
|
+
required: "[%{service_class_name}] Elemento richiesto mancante nella collezione di input `%{input_name}`"
|
|
21
|
+
wrong_type: "[%{service_class_name}] Tipo di collezione di input errato `%{input_name}`, previsto `%{expected_type}`, ricevuto `%{given_type}`"
|
|
22
|
+
wrong_element_type: "[%{service_class_name}] Tipo di elemento errato nella collezione di input `%{input_name}`, previsto `%{expected_type}`, ricevuto `%{given_type}`"
|
|
23
|
+
format:
|
|
24
|
+
default: "[%{service_class_name}] L'input `%{input_name}` non corrisponde al formato `%{format_name}`"
|
|
25
|
+
wrong_pattern: "[%{service_class_name}] L'input `%{input_name}` non corrisponde al formato `%{format_name}`"
|
|
26
|
+
wrong_type: "[%{service_class_name}] L'input `%{input_name}` deve essere una stringa per la validazione del formato `%{format_name}`"
|
|
27
|
+
unknown: "[%{service_class_name}] Formato sconosciuto `%{format_name}` specificato per l'input `%{input_name}`"
|
|
28
|
+
inclusion:
|
|
29
|
+
default: "[%{service_class_name}] Valore errato in `%{input_name}`, deve essere uno di `%{input_inclusion}`, ricevuto `%{value}`"
|
|
30
|
+
invalid_option: "[%{service_class_name}] L'input `%{input_name}` ha valore mancante nell'opzione `%{option_name}`"
|
|
31
|
+
min:
|
|
32
|
+
default: "[%{service_class_name}] L'input `%{input_name}` ha ricevuto il valore `%{value}`, che è inferiore a `%{option_value}`"
|
|
33
|
+
max:
|
|
34
|
+
default: "[%{service_class_name}] L'input `%{input_name}` ha ricevuto il valore `%{value}`, che è superiore a `%{option_value}`"
|
|
35
|
+
multiple_of:
|
|
36
|
+
default: "[%{service_class_name}] L'input `%{input_name}` ha il valore `%{value}`, che non è un multiplo di `%{option_value}`"
|
|
37
|
+
blank: "[%{service_class_name}] L'input `%{input_name}` ha un valore non valido `%{option_value}` nell'opzione `%{option_name}`"
|
|
38
|
+
divided_by_0: "[%{service_class_name}] L'input `%{input_name}` ha un valore non valido `%{option_value}` nell'opzione `%{option_name}`"
|
|
39
|
+
schema:
|
|
40
|
+
wrong_type: "[%{service_class_name}] Tipo errato dell'input `%{input_name}`, previsto `%{expected_type}`, ricevuto `%{given_type}`"
|
|
41
|
+
wrong_element_type: "[%{service_class_name}] Tipo errato nell'hash di input `%{input_name}`, per `%{key_name}` previsto `%{expected_type}`, ricevuto `%{given_type}`"
|
|
42
|
+
wrong_element_value: "[%{service_class_name}] Valore errato nell'hash di input `%{input_name}`, per `%{key_name}` valore previsto di tipo `%{expected_type}`, ricevuto `%{given_type}`"
|
|
43
|
+
target:
|
|
44
|
+
default: "[%{service_class_name}] L'input `%{input_name}` ha obiettivo errato, deve essere `%{expected_target}`, ricevuto `%{value}`"
|
|
45
|
+
invalid_option: "[%{service_class_name}] L'input `%{input_name}` ha valore mancante nell'opzione `%{option_name}`"
|
|
46
|
+
required:
|
|
47
|
+
default_error:
|
|
48
|
+
default: "[%{service_class_name}] L'input richiesto `%{input_name}` è mancante"
|
|
49
|
+
type:
|
|
50
|
+
default_error:
|
|
51
|
+
default: "[%{service_class_name}] Tipo errato dell'input `%{input_name}`, previsto `%{expected_type}`, ricevuto `%{given_type}`"
|
|
52
|
+
tools:
|
|
53
|
+
find_unnecessary:
|
|
54
|
+
error: "[%{service_class_name}] Attributi inattesi: `%{unnecessary_attributes}`"
|
|
55
|
+
rules:
|
|
56
|
+
error: "[%{service_class_name}] Conflitto nelle opzioni dell'input `%{input_name}`: `%{conflict_code}`"
|
|
57
|
+
internals:
|
|
58
|
+
undefined:
|
|
59
|
+
for_fetch: "[%{service_class_name}] Attributo interno non definito `%{internal_name}`"
|
|
60
|
+
for_assign: "[%{service_class_name}] Attributo interno non definito `%{internal_name}`"
|
|
61
|
+
validations:
|
|
62
|
+
must:
|
|
63
|
+
default_error: "[%{service_class_name}] L'attributo interno `%{internal_name}` deve \"%{code}\""
|
|
64
|
+
syntax_error: "[%{service_class_name}] Errore di sintassi in `%{code}` dell'attributo interno `%{internal_name}`: %{exception_message}"
|
|
65
|
+
dynamic_options:
|
|
66
|
+
consists_of:
|
|
67
|
+
required: "[%{service_class_name}] Elemento richiesto mancante nella collezione dell'attributo interno `%{internal_name}`"
|
|
68
|
+
wrong_type: "[%{service_class_name}] Tipo di collezione errato dell'attributo interno `%{internal_name}`, previsto `%{expected_type}`, ricevuto `%{given_type}`"
|
|
69
|
+
wrong_element_type: "[%{service_class_name}] Tipo di elemento errato nella collezione dell'attributo interno `%{internal_name}`, previsto `%{expected_type}`, ricevuto `%{given_type}`"
|
|
70
|
+
format:
|
|
71
|
+
default: "[%{service_class_name}] L'attributo interno `%{internal_name}` non corrisponde al formato `%{format_name}`"
|
|
72
|
+
wrong_pattern: "[%{service_class_name}] L'attributo interno `%{internal_name}` non corrisponde al formato `%{format_name}`"
|
|
73
|
+
wrong_type: "[%{service_class_name}] L'attributo interno `%{internal_name}` deve essere una stringa per la validazione del formato `%{format_name}`"
|
|
74
|
+
unknown: "[%{service_class_name}] Formato sconosciuto `%{format_name}` specificato per l'attributo interno `%{internal_name}`"
|
|
75
|
+
inclusion:
|
|
76
|
+
default: "[%{service_class_name}] Valore errato in `%{internal_name}`, deve essere uno di `%{internal_inclusion}`, ricevuto `%{value}`"
|
|
77
|
+
invalid_option: "[%{service_class_name}] L'attributo interno `%{internal_name}` ha valore mancante nell'opzione `%{option_name}`"
|
|
78
|
+
min:
|
|
79
|
+
default: "[%{service_class_name}] L'attributo interno `%{internal_name}` ha ricevuto il valore `%{value}`, che è inferiore a `%{option_value}`"
|
|
80
|
+
max:
|
|
81
|
+
default: "[%{service_class_name}] L'attributo interno `%{internal_name}` ha ricevuto il valore `%{value}`, che è superiore a `%{option_value}`"
|
|
82
|
+
multiple_of:
|
|
83
|
+
default: "[%{service_class_name}] L'attributo interno `%{internal_name}` ha il valore `%{value}`, che non è un multiplo di `%{option_value}`"
|
|
84
|
+
blank: "[%{service_class_name}] L'attributo interno `%{internal_name}` ha un valore non valido `%{option_value}` nell'opzione `%{option_name}`"
|
|
85
|
+
divided_by_0: "[%{service_class_name}] L'attributo interno `%{internal_name}` ha un valore non valido `%{option_value}` nell'opzione `%{option_name}`"
|
|
86
|
+
schema:
|
|
87
|
+
wrong_type: "[%{service_class_name}] Tipo errato dell'attributo interno `%{internal_name}`, previsto `%{expected_type}`, ricevuto `%{given_type}`"
|
|
88
|
+
wrong_element_type: "[%{service_class_name}] Tipo errato nell'hash dell'attributo interno `%{internal_name}`, per `%{key_name}` previsto `%{expected_type}`, ricevuto `%{given_type}`"
|
|
89
|
+
wrong_element_value: "[%{service_class_name}] Valore errato nell'hash dell'attributo interno `%{internal_name}`, per `%{key_name}` valore previsto di tipo `%{expected_type}`, ricevuto `%{given_type}`"
|
|
90
|
+
target:
|
|
91
|
+
default: "[%{service_class_name}] L'attributo interno `%{internal_name}` ha obiettivo errato, deve essere `%{expected_target}`, ricevuto `%{value}`"
|
|
92
|
+
invalid_option: "[%{service_class_name}] L'attributo interno `%{internal_name}` ha valore mancante nell'opzione `%{option_name}`"
|
|
93
|
+
type:
|
|
94
|
+
default_error:
|
|
95
|
+
default: "[%{service_class_name}] Tipo errato dell'attributo interno `%{internal_name}`, previsto `%{expected_type}`, ricevuto `%{given_type}`"
|
|
96
|
+
outputs:
|
|
97
|
+
undefined:
|
|
98
|
+
for_fetch: "[%{service_class_name}] Attributo di output non definito `%{output_name}`"
|
|
99
|
+
for_assign: "[%{service_class_name}] Attributo di output non definito `%{output_name}`"
|
|
100
|
+
validations:
|
|
101
|
+
must:
|
|
102
|
+
default_error: "[%{service_class_name}] L'attributo di output `%{output_name}` deve \"%{code}\""
|
|
103
|
+
syntax_error: "[%{service_class_name}] Errore di sintassi in `%{code}` dell'attributo di output `%{output_name}`: %{exception_message}"
|
|
104
|
+
dynamic_options:
|
|
105
|
+
consists_of:
|
|
106
|
+
required: "[%{service_class_name}] Elemento richiesto mancante nella collezione dell'attributo di output `%{output_name}`"
|
|
107
|
+
wrong_type: "[%{service_class_name}] Tipo di collezione errato dell'attributo di output `%{output_name}`, previsto `%{expected_type}`, ricevuto `%{given_type}`"
|
|
108
|
+
wrong_element_type: "[%{service_class_name}] Tipo di elemento errato nella collezione dell'attributo di output `%{output_name}`, previsto `%{expected_type}`, ricevuto `%{given_type}`"
|
|
109
|
+
format:
|
|
110
|
+
default: "[%{service_class_name}] L'attributo di output `%{output_name}` non corrisponde al formato `%{format_name}`"
|
|
111
|
+
wrong_pattern: "[%{service_class_name}] L'attributo di output `%{output_name}` non corrisponde al formato `%{format_name}`"
|
|
112
|
+
wrong_type: "[%{service_class_name}] L'attributo di output `%{output_name}` deve essere una stringa per la validazione del formato `%{format_name}`"
|
|
113
|
+
unknown: "[%{service_class_name}] Formato sconosciuto `%{format_name}` specificato per l'attributo di output `%{output_name}`"
|
|
114
|
+
inclusion:
|
|
115
|
+
default: "[%{service_class_name}] Valore errato in `%{output_name}`, deve essere uno di `%{output_inclusion}`, ricevuto `%{value}`"
|
|
116
|
+
invalid_option: "[%{service_class_name}] L'attributo di output `%{output_name}` ha valore mancante nell'opzione `%{option_name}`"
|
|
117
|
+
min:
|
|
118
|
+
default: "[%{service_class_name}] L'attributo di output `%{output_name}` ha ricevuto il valore `%{value}`, che è inferiore a `%{option_value}`"
|
|
119
|
+
max:
|
|
120
|
+
default: "[%{service_class_name}] L'attributo di output `%{output_name}` ha ricevuto il valore `%{value}`, che è superiore a `%{option_value}`"
|
|
121
|
+
multiple_of:
|
|
122
|
+
default: "[%{service_class_name}] L'attributo di output `%{output_name}` ha il valore `%{value}`, che non è un multiplo di `%{option_value}`"
|
|
123
|
+
blank: "[%{service_class_name}] L'attributo di output `%{output_name}` ha un valore non valido `%{option_value}` nell'opzione `%{option_name}`"
|
|
124
|
+
divided_by_0: "[%{service_class_name}] L'attributo di output `%{output_name}` ha un valore non valido `%{option_value}` nell'opzione `%{option_name}`"
|
|
125
|
+
schema:
|
|
126
|
+
wrong_type: "[%{service_class_name}] Tipo errato dell'attributo di output `%{output_name}`, previsto `%{expected_type}`, ricevuto `%{given_type}`"
|
|
127
|
+
wrong_element_type: "[%{service_class_name}] Tipo errato nell'hash dell'attributo di output `%{output_name}`, per `%{key_name}` previsto `%{expected_type}`, ricevuto `%{given_type}`"
|
|
128
|
+
wrong_element_value: "[%{service_class_name}] Valore errato nell'hash dell'attributo di output `%{output_name}`, per `%{key_name}` valore previsto di tipo `%{expected_type}`, ricevuto `%{given_type}`"
|
|
129
|
+
target:
|
|
130
|
+
default: "[%{service_class_name}] L'attributo di output `%{output_name}` ha obiettivo errato, deve essere `%{expected_target}`, ricevuto `%{value}`"
|
|
131
|
+
invalid_option: "[%{service_class_name}] L'attributo di output `%{output_name}` ha valore mancante nell'opzione `%{option_name}`"
|
|
132
|
+
type:
|
|
133
|
+
default_error:
|
|
134
|
+
default: "[%{service_class_name}] Tipo errato dell'attributo di output `%{output_name}`, previsto `%{expected_type}`, ricevuto `%{given_type}`"
|
data/config/locales/ru.yml
CHANGED
|
@@ -23,9 +23,11 @@ ru:
|
|
|
23
23
|
format:
|
|
24
24
|
default: "[%{service_class_name}] Инпут `%{input_name}` не соответствует формату `%{format_name}`"
|
|
25
25
|
wrong_pattern: "[%{service_class_name}] Инпут `%{input_name}` не соответствует формату `%{format_name}`"
|
|
26
|
+
wrong_type: "[%{service_class_name}] Инпут `%{input_name}` должен быть строкой для валидации формата `%{format_name}`"
|
|
26
27
|
unknown: "[%{service_class_name}] Указан неизвестный формат `%{format_name}` у инпута `%{input_name}`"
|
|
27
28
|
inclusion:
|
|
28
29
|
default: "[%{service_class_name}] Неправильное значение в `%{input_name}`, должно быть одним из `%{input_inclusion}`, получено `%{value}`"
|
|
30
|
+
invalid_option: "[%{service_class_name}] Инпут `%{input_name}` имеет незаполненное значение в опции `%{option_name}`"
|
|
29
31
|
min:
|
|
30
32
|
default: "[%{service_class_name}] Инпут `%{input_name}` получил значение `%{value}`, которое меньше `%{option_value}`"
|
|
31
33
|
max:
|
|
@@ -38,6 +40,9 @@ ru:
|
|
|
38
40
|
wrong_type: "[%{service_class_name}] Неправильный тип инпута `%{input_name}`, ожидалось `%{expected_type}`, получено `%{given_type}`"
|
|
39
41
|
wrong_element_type: "[%{service_class_name}] Неправильный тип в хеше инпута `%{input_name}`, для `%{key_name}` ожидалось `%{expected_type}`, получено `%{given_type}`"
|
|
40
42
|
wrong_element_value: "[%{service_class_name}] Неправильное значение в хеше инпута `%{input_name}`, для `%{key_name}` ожидалось значение с типом `%{expected_type}`, получено `%{given_type}`"
|
|
43
|
+
target:
|
|
44
|
+
default: "[%{service_class_name}] Инпут `%{input_name}` имеет неправильное значение, должно быть `%{expected_target}`, получено `%{value}`"
|
|
45
|
+
invalid_option: "[%{service_class_name}] Инпут `%{input_name}` имеет незаполненное значение в опции `%{option_name}`"
|
|
41
46
|
required:
|
|
42
47
|
default_error:
|
|
43
48
|
default: "[%{service_class_name}] Обязательный инпут `%{input_name}` отсутствует"
|
|
@@ -65,9 +70,11 @@ ru:
|
|
|
65
70
|
format:
|
|
66
71
|
default: "[%{service_class_name}] Внутренний атрибут `%{internal_name}` не соответствует формату `%{format_name}`"
|
|
67
72
|
wrong_pattern: "[%{service_class_name}] Внутренний атрибут `%{internal_name}` не соответствует формату `%{format_name}`"
|
|
73
|
+
wrong_type: "[%{service_class_name}] Внутренний атрибут `%{internal_name}` должен быть строкой для валидации формата `%{format_name}`"
|
|
68
74
|
unknown: "[%{service_class_name}] Указан неизвестный формат `%{format_name}` у внутреннего атрибута `%{internal_name}`"
|
|
69
75
|
inclusion:
|
|
70
76
|
default: "[%{service_class_name}] Неправильное значение в `%{internal_name}`, должно быть одним из `%{internal_inclusion}`, получено `%{value}`"
|
|
77
|
+
invalid_option: "[%{service_class_name}] Внутренний атрибут `%{internal_name}` имеет незаполненное значение в опции `%{option_name}`"
|
|
71
78
|
min:
|
|
72
79
|
default: "[%{service_class_name}] Внутренний атрибут `%{internal_name}` получил значение `%{value}`, которое меньше `%{option_value}`"
|
|
73
80
|
max:
|
|
@@ -80,6 +87,9 @@ ru:
|
|
|
80
87
|
wrong_type: "[%{service_class_name}] Неправильный тип внутреннего атрибута `%{internal_name}`, ожидалось `%{expected_type}`, получено `%{given_type}`"
|
|
81
88
|
wrong_element_type: "[%{service_class_name}] Неправильный тип в хеше внутреннего атрибута `%{internal_name}`, для `%{key_name}` ожидалось `%{expected_type}`, получено `%{given_type}`"
|
|
82
89
|
wrong_element_value: "[%{service_class_name}] Неправильное значение в хеше внутреннего атрибута `%{internal_name}`, для `%{key_name}` ожидалось значение с типом `%{expected_type}`, получено `%{given_type}`"
|
|
90
|
+
target:
|
|
91
|
+
default: "[%{service_class_name}] Внутренний атрибут `%{internal_name}` имеет неправильное значение, должно быть `%{expected_target}`, получено `%{value}`"
|
|
92
|
+
invalid_option: "[%{service_class_name}] Внутренний атрибут `%{internal_name}` имеет незаполненное значение в опции `%{option_name}`"
|
|
83
93
|
type:
|
|
84
94
|
default_error:
|
|
85
95
|
default: "[%{service_class_name}] Неправильный тип внутреннего атрибута `%{internal_name}`, ожидалось `%{expected_type}`, получено `%{given_type}`"
|
|
@@ -99,9 +109,11 @@ ru:
|
|
|
99
109
|
format:
|
|
100
110
|
default: "[%{service_class_name}] Выходящий атрибут `%{output_name}` не соответствует формату `%{format_name}`"
|
|
101
111
|
wrong_pattern: "[%{service_class_name}] Выходящий атрибут `%{output_name}` не соответствует формату `%{format_name}`"
|
|
112
|
+
wrong_type: "[%{service_class_name}] Выходящий атрибут `%{output_name}` должен быть строкой для валидации формата `%{format_name}`"
|
|
102
113
|
unknown: "[%{service_class_name}] Указан неизвестный формат `%{format_name}` у выходящего атрибута `%{output_name}`"
|
|
103
114
|
inclusion:
|
|
104
115
|
default: "[%{service_class_name}] Неправильное значение в `%{output_name}`, должно быть одним из `%{output_inclusion}`, получено `%{value}`"
|
|
116
|
+
invalid_option: "[%{service_class_name}] Выходящий атрибут `%{output_name}` имеет незаполненное значение в опции `%{option_name}`"
|
|
105
117
|
min:
|
|
106
118
|
default: "[%{service_class_name}] Выходящий атрибут `%{output_name}` получил значение `%{value}`, которое меньше `%{option_value}`"
|
|
107
119
|
max:
|
|
@@ -114,6 +126,9 @@ ru:
|
|
|
114
126
|
wrong_type: "[%{service_class_name}] Неправильный тип выходящего атрибута `%{output_name}`, ожидалось `%{expected_type}`, получено `%{given_type}`"
|
|
115
127
|
wrong_element_type: "[%{service_class_name}] Неправильный тип в хеше выходящего атрибута `%{output_name}`, для `%{key_name}` ожидалось `%{expected_type}`, получено `%{given_type}`"
|
|
116
128
|
wrong_element_value: "[%{service_class_name}] Неправильное значение в хеше выходящего атрибута `%{output_name}`, для `%{key_name}` ожидалось значение с типом `%{expected_type}`, получено `%{given_type}`"
|
|
129
|
+
target:
|
|
130
|
+
default: "[%{service_class_name}] Выходящий атрибут `%{output_name}` имеет неправильное значение, должно быть `%{expected_target}`, получено `%{value}`"
|
|
131
|
+
invalid_option: "[%{service_class_name}] Выходящий атрибут `%{output_name}` имеет незаполненное значение в опции `%{option_name}`"
|
|
117
132
|
type:
|
|
118
133
|
default_error:
|
|
119
134
|
default: "[%{service_class_name}] Неправильный тип выходящего атрибута `%{output_name}`, ожидалось `%{expected_type}`, получено `%{given_type}`"
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Servactory Generators
|
|
2
|
+
|
|
3
|
+
## Installation
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
rails generate servactory:install [options]
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
**Options:**
|
|
10
|
+
- `--namespace` — Base namespace (default: `ApplicationService`)
|
|
11
|
+
- `--path` — Path to install service files (default: `app/services`)
|
|
12
|
+
- `--locales` — Locales to install (available: `en`, `ru`, `de`, `fr`, `es`, `it`)
|
|
13
|
+
- `--minimal` — Generate minimal setup without configuration examples
|
|
14
|
+
|
|
15
|
+
## Service
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
rails generate servactory:service NAME [inputs] [options]
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
**Arguments:**
|
|
22
|
+
- `NAME` — Service name (e.g., `Users::Create`, `ProcessOrder`)
|
|
23
|
+
- `inputs` — Input attributes with optional types (e.g., `email:string name:String user:User`)
|
|
24
|
+
|
|
25
|
+
**Options:**
|
|
26
|
+
- `--base-class` — Base class for service (default: `ApplicationService::Base`)
|
|
27
|
+
- `--path` — Path to generate service files (default: `app/services`)
|
|
28
|
+
- `--skip-output` — Skip default output declaration
|
|
29
|
+
|
|
30
|
+
## RSpec
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
rails generate servactory:rspec NAME [inputs] [options]
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Generates RSpec spec for a Servactory service.
|
|
37
|
+
|
|
38
|
+
**Arguments:**
|
|
39
|
+
- `NAME` — Service name (e.g., `Users::Create`)
|
|
40
|
+
- `inputs` — Input attributes with optional types (e.g., `email:string name:String`)
|
|
41
|
+
|
|
42
|
+
**Options:**
|
|
43
|
+
- `--call-method` — Primary call method: `call` or `call!` (default: `call!`)
|
|
44
|
+
- `--path` — Path to service files (default: `app/services`). Spec path is auto-derived: `app/X` → `spec/X`, `lib/X` → `spec/X`
|
|
45
|
+
- `--skip-pending` — Skip pending placeholder
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails/generators/base"
|
|
4
|
+
require "rails/generators/named_base"
|
|
5
|
+
|
|
6
|
+
module Servactory
|
|
7
|
+
module Generators
|
|
8
|
+
class Base < Rails::Generators::Base
|
|
9
|
+
def self.gem_root
|
|
10
|
+
@gem_root ||= File.expand_path("../../..", __dir__)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.gem_locales_path
|
|
14
|
+
@gem_locales_path ||= File.join(gem_root, "config", "locales")
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def gem_root
|
|
20
|
+
self.class.gem_root
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def gem_locales_path
|
|
24
|
+
self.class.gem_locales_path
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
class NamedBase < Rails::Generators::NamedBase
|
|
29
|
+
VALID_INPUT_NAME_REGEX = /\A[a-z_][a-zA-Z0-9_]*\z/
|
|
30
|
+
|
|
31
|
+
TYPE_MAPPING = {
|
|
32
|
+
"string" => "String",
|
|
33
|
+
"integer" => "Integer",
|
|
34
|
+
"float" => "Float",
|
|
35
|
+
"boolean" => "[TrueClass, FalseClass]",
|
|
36
|
+
"bool" => "[TrueClass, FalseClass]",
|
|
37
|
+
"array" => "Array",
|
|
38
|
+
"hash" => "Hash",
|
|
39
|
+
"symbol" => "Symbol",
|
|
40
|
+
"date" => "Date",
|
|
41
|
+
"datetime" => "DateTime",
|
|
42
|
+
"time" => "Time",
|
|
43
|
+
"nil" => "NilClass",
|
|
44
|
+
"nilclass" => "NilClass",
|
|
45
|
+
"decimal" => "BigDecimal",
|
|
46
|
+
"bigdecimal" => "BigDecimal"
|
|
47
|
+
}.freeze
|
|
48
|
+
|
|
49
|
+
private
|
|
50
|
+
|
|
51
|
+
def input_names
|
|
52
|
+
@input_names ||= parsed_inputs.map { |input| input[:name] }
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def parsed_inputs
|
|
56
|
+
@parsed_inputs ||= inputs.map do |input_argument|
|
|
57
|
+
parts = input_argument.to_s.split(":", 2)
|
|
58
|
+
name = parts[0].strip
|
|
59
|
+
type = normalize_type(parts[1])
|
|
60
|
+
|
|
61
|
+
validate_input_name!(name)
|
|
62
|
+
|
|
63
|
+
{ name:, type: }
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def validate_input_name!(name)
|
|
68
|
+
return if name.match?(VALID_INPUT_NAME_REGEX)
|
|
69
|
+
|
|
70
|
+
raise ArgumentError, "Invalid input name '#{name}'. " \
|
|
71
|
+
"Input names must start with a lowercase letter or underscore, " \
|
|
72
|
+
"followed by letters, numbers, or underscores."
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def normalize_type(type_string)
|
|
76
|
+
return "String" if type_string.blank?
|
|
77
|
+
|
|
78
|
+
TYPE_MAPPING[type_string.downcase] || type_string
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
Description:
|
|
2
|
+
Generates a new Servactory extension module.
|
|
3
|
+
|
|
4
|
+
Usage:
|
|
5
|
+
rails generate servactory:extension NAME [options]
|
|
6
|
+
|
|
7
|
+
Arguments:
|
|
8
|
+
NAME The name of the extension (e.g., MyExtension, Admin::AuditTrail)
|
|
9
|
+
|
|
10
|
+
Options:
|
|
11
|
+
--path=PATH Path to generate extension files (default: app/services/application_service/extensions)
|
|
12
|
+
--namespace=NAMESPACE Base namespace for the extension module (default: ApplicationService)
|
|
13
|
+
|
|
14
|
+
Generated Structure:
|
|
15
|
+
The extension follows the standard Servactory extension pattern with:
|
|
16
|
+
- self.included(base) hook for module setup
|
|
17
|
+
- ClassMethods module for DSL methods (called at class definition time)
|
|
18
|
+
- InstanceMethods module for runtime behavior (call! override)
|
|
19
|
+
- stroma.settings integration for configuration storage
|
|
20
|
+
|
|
21
|
+
Examples:
|
|
22
|
+
rails generate servactory:extension MyExtension
|
|
23
|
+
Creates app/services/application_service/extensions/my_extension/dsl.rb
|
|
24
|
+
Module: ApplicationService::Extensions::MyExtension::DSL
|
|
25
|
+
|
|
26
|
+
rails generate servactory:extension Admin::AuditTrail
|
|
27
|
+
Creates app/services/application_service/extensions/admin/audit_trail/dsl.rb
|
|
28
|
+
Module: ApplicationService::Extensions::Admin::AuditTrail::DSL
|
|
29
|
+
|
|
30
|
+
rails generate servactory:extension MyExtension --path=lib/my_gem/extensions
|
|
31
|
+
Creates lib/my_gem/extensions/my_extension/dsl.rb
|
|
32
|
+
|
|
33
|
+
rails generate servactory:extension MyExtension --namespace=MyApp::Services
|
|
34
|
+
Creates extension with MyApp::Services::Extensions::MyExtension::DSL namespace
|
|
35
|
+
|
|
36
|
+
Usage in Service:
|
|
37
|
+
After generation, include the extension in your service base class:
|
|
38
|
+
|
|
39
|
+
# app/services/application_service/base.rb
|
|
40
|
+
module ApplicationService
|
|
41
|
+
class Base < Servactory::Base
|
|
42
|
+
extensions do
|
|
43
|
+
before :actions, ApplicationService::Extensions::MyExtension::DSL
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
Then use the DSL method in your services:
|
|
49
|
+
|
|
50
|
+
class MyService < ApplicationService::Base
|
|
51
|
+
my_extension!(my_setting: "value")
|
|
52
|
+
|
|
53
|
+
# ...
|
|
54
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Servactory
|
|
4
|
+
module Generators
|
|
5
|
+
class ExtensionGenerator < Rails::Generators::NamedBase
|
|
6
|
+
source_root File.expand_path("templates", __dir__)
|
|
7
|
+
|
|
8
|
+
class_option :path,
|
|
9
|
+
type: :string,
|
|
10
|
+
default: "app/services/application_service/extensions",
|
|
11
|
+
desc: "Path to generate extension files"
|
|
12
|
+
|
|
13
|
+
class_option :namespace,
|
|
14
|
+
type: :string,
|
|
15
|
+
default: "ApplicationService",
|
|
16
|
+
desc: "Base namespace for the extension module"
|
|
17
|
+
|
|
18
|
+
def create_extension
|
|
19
|
+
template "extension.rb.tt", extension_file_path
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def extension_file_path
|
|
25
|
+
"#{extensions_path}/#{file_path}/dsl.rb"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def extensions_path
|
|
29
|
+
options[:path]
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def base_namespace
|
|
33
|
+
options[:namespace]
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def extension_key
|
|
37
|
+
file_path.tr("/", "_")
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module <%= base_namespace %>
|
|
4
|
+
module Extensions
|
|
5
|
+
module <%= class_name %>
|
|
6
|
+
module DSL
|
|
7
|
+
# Hook called when this module is included in a service base class.
|
|
8
|
+
# Sets up both class-level DSL methods and instance-level runtime behavior.
|
|
9
|
+
def self.included(base)
|
|
10
|
+
base.extend(ClassMethods)
|
|
11
|
+
base.include(InstanceMethods)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Class-level DSL methods - called at service class definition time.
|
|
15
|
+
# Use these to configure extension behavior for the service class.
|
|
16
|
+
module ClassMethods
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
# Example DSL method that stores configuration in stroma settings.
|
|
20
|
+
# Usage in service: <%= extension_key %>!(my_setting: "value")
|
|
21
|
+
def <%= extension_key %>!(my_setting: nil)
|
|
22
|
+
stroma.settings[:actions][:<%= extension_key %>][:my_setting] = my_setting
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Instance-level methods - called at service runtime.
|
|
27
|
+
# Override call! to add behavior before, after, or around service execution.
|
|
28
|
+
module InstanceMethods
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
# Override call! to customize service execution flow.
|
|
32
|
+
#
|
|
33
|
+
# Common patterns:
|
|
34
|
+
# Before: validate/check conditions, then call super
|
|
35
|
+
# After: call super, then process outputs
|
|
36
|
+
# Around: wrap super in context (e.g., transaction { super })
|
|
37
|
+
# Error: call super with rescue block for error handling
|
|
38
|
+
#
|
|
39
|
+
# Available parameters for call!:
|
|
40
|
+
# def call!(**) - basic, most common
|
|
41
|
+
# def call!(incoming_arguments: {}, **) - access raw arguments before input processing
|
|
42
|
+
# def call!(collection_of_inputs:, collection_of_internals:, collection_of_outputs:, **) - full access
|
|
43
|
+
def call!(**)
|
|
44
|
+
# Access class-level configuration stored in stroma settings
|
|
45
|
+
my_setting = self.class.stroma.settings[:actions][:<%= extension_key %>][:my_setting]
|
|
46
|
+
|
|
47
|
+
# Example: Before pattern - validate before execution
|
|
48
|
+
# if my_setting.present?
|
|
49
|
+
# fail!(:my_error, message: "Error message") unless some_condition
|
|
50
|
+
# end
|
|
51
|
+
|
|
52
|
+
# Always call super to continue the execution chain
|
|
53
|
+
super
|
|
54
|
+
|
|
55
|
+
# Example: After pattern - process outputs after execution
|
|
56
|
+
# process_result(outputs) if my_setting.present?
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
Description:
|
|
2
|
+
Installs Servactory base service configuration into your Rails application.
|
|
3
|
+
|
|
4
|
+
Usage:
|
|
5
|
+
rails generate servactory:install [options]
|
|
6
|
+
|
|
7
|
+
Options:
|
|
8
|
+
--namespace=NAMESPACE Base namespace for services (default: ApplicationService)
|
|
9
|
+
--locales=LOCALES Locales to install (available: en, ru, de, fr, es, it)
|
|
10
|
+
--minimal Generate minimal setup without configuration examples
|
|
11
|
+
--path=PATH Path to install service files (default: app/services)
|
|
12
|
+
|
|
13
|
+
Examples:
|
|
14
|
+
rails generate servactory:install
|
|
15
|
+
Creates app/services/application_service/ with base.rb, exceptions.rb, result.rb
|
|
16
|
+
|
|
17
|
+
rails generate servactory:install --path=lib/my_gem/services
|
|
18
|
+
Creates lib/my_gem/services/application_service/ for gem/library use
|
|
19
|
+
|
|
20
|
+
rails generate servactory:install --namespace=MyApp::Services
|
|
21
|
+
Creates app/services/my_app/services/ with all files
|
|
22
|
+
|
|
23
|
+
rails generate servactory:install --locales=en,de,fr
|
|
24
|
+
Also copies locale files to config/locales/ (available: en, ru, de, fr, es, it)
|
|
25
|
+
|
|
26
|
+
rails generate servactory:install --minimal
|
|
27
|
+
Creates minimal setup without configuration examples
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../base"
|
|
4
|
+
|
|
5
|
+
module Servactory
|
|
6
|
+
module Generators
|
|
7
|
+
class InstallGenerator < Servactory::Generators::Base
|
|
8
|
+
source_root File.expand_path("templates", __dir__)
|
|
9
|
+
|
|
10
|
+
VALID_NAMESPACE_REGEX = /\A[A-Z][a-zA-Z0-9_]*(::[A-Z][a-zA-Z0-9_]*)*\z/
|
|
11
|
+
|
|
12
|
+
class_option :namespace,
|
|
13
|
+
type: :string,
|
|
14
|
+
default: "ApplicationService",
|
|
15
|
+
desc: "Base namespace for services"
|
|
16
|
+
|
|
17
|
+
class_option :path,
|
|
18
|
+
type: :string,
|
|
19
|
+
default: "app/services",
|
|
20
|
+
desc: "Path to install service files"
|
|
21
|
+
|
|
22
|
+
class_option :locales,
|
|
23
|
+
type: :array,
|
|
24
|
+
default: [],
|
|
25
|
+
desc: "Locales to install (e.g., --locales=en,ru)"
|
|
26
|
+
|
|
27
|
+
class_option :minimal,
|
|
28
|
+
type: :boolean,
|
|
29
|
+
default: false,
|
|
30
|
+
desc: "Generate minimal setup without configuration examples"
|
|
31
|
+
|
|
32
|
+
def create_application_service
|
|
33
|
+
validate_namespace!
|
|
34
|
+
|
|
35
|
+
template "application_service/base.rb.tt", service_path("base.rb")
|
|
36
|
+
template "application_service/exceptions.rb.tt", service_path("exceptions.rb")
|
|
37
|
+
template "application_service/result.rb.tt", service_path("result.rb")
|
|
38
|
+
|
|
39
|
+
create_file service_path("dynamic_options/.keep"), ""
|
|
40
|
+
create_file service_path("extensions/.keep"), ""
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def copy_locales
|
|
44
|
+
return if locales.blank?
|
|
45
|
+
|
|
46
|
+
locales.each do |locale|
|
|
47
|
+
locale_file = "servactory.#{locale}.yml"
|
|
48
|
+
source_path = File.join(gem_locales_path, "#{locale}.yml")
|
|
49
|
+
|
|
50
|
+
if File.exist?(source_path)
|
|
51
|
+
copy_file source_path, "config/locales/#{locale_file}"
|
|
52
|
+
else
|
|
53
|
+
say "Locale file not found: #{locale} (expected at #{source_path})", :yellow
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
private
|
|
59
|
+
|
|
60
|
+
def validate_namespace!
|
|
61
|
+
return if namespace.match?(VALID_NAMESPACE_REGEX)
|
|
62
|
+
|
|
63
|
+
raise ArgumentError, "Invalid namespace '#{namespace}'. " \
|
|
64
|
+
"Namespace must be a valid Ruby constant name " \
|
|
65
|
+
"(e.g., 'ApplicationService', 'MyApp::Services')."
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def namespace
|
|
69
|
+
options[:namespace]
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def namespace_path
|
|
73
|
+
namespace.underscore
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def base_path
|
|
77
|
+
options[:path]
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def service_path(filename)
|
|
81
|
+
"#{base_path}/#{namespace_path}/#{filename}"
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def locales
|
|
85
|
+
# Handle both "--locales=en,ru" (single string) and "--locales en ru" (array)
|
|
86
|
+
options[:locales].flat_map { |locale| locale.split(",") }
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def minimal?
|
|
90
|
+
options[:minimal]
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|