datory 1.0.0.rc1
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 +7 -0
- data/README.md +26 -0
- data/Rakefile +12 -0
- data/config/locales/en.yml +99 -0
- data/config/locales/ru.yml +99 -0
- data/lib/datory/attributes/attribute.rb +14 -0
- data/lib/datory/attributes/collection.rb +30 -0
- data/lib/datory/attributes/dsl.rb +76 -0
- data/lib/datory/attributes/workspace.rb +79 -0
- data/lib/datory/base.rb +8 -0
- data/lib/datory/context/callable.rb +67 -0
- data/lib/datory/context/dsl.rb +12 -0
- data/lib/datory/context/workspace.rb +39 -0
- data/lib/datory/result.rb +5 -0
- data/lib/datory/service/base.rb +19 -0
- data/lib/datory/service/builder.rb +8 -0
- data/lib/datory/service/exceptions.rb +13 -0
- data/lib/datory/version.rb +12 -0
- data/lib/datory.rb +17 -0
- metadata +241 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 9a373fdef28cc23b1fede6c3c3405e92ca888b832792122bde0c9a2758aab365
|
4
|
+
data.tar.gz: 962d0fc90e6a130d249800d982176ece5b7e85226979e4e6a94c2a306b1b7a4d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 947b785c440d6fef3672dc82cb25eb8c59e256f881974f32dc50673fe626274d0723b0b8e09c1c24ba4c6714b77eabfbf0a83a3399794dd41b8ef2039426ec3c
|
7
|
+
data.tar.gz: 9984cdcd0c95f0b3e5de163fe84b46e2275ce7e61c6764fcfcb38e0696832d9922f8313108ec2ae6505a18543ca36ac8c8a87d67cfa4d2f205cd41953aabc59b
|
data/README.md
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
<p align="center">
|
2
|
+
<a href="https://rubygems.org/gems/datory"><img src="https://img.shields.io/gem/v/datory?logo=rubygems&logoColor=fff" alt="Gem version"></a>
|
3
|
+
<a href="https://github.com/servactory/datory/releases"><img src="https://img.shields.io/github/release-date/servactory/datory" alt="Release Date"></a>
|
4
|
+
</p>
|
5
|
+
|
6
|
+
## Documentation
|
7
|
+
|
8
|
+
See [datory.servactory.com](https://datory.servactory.com) for documentation.
|
9
|
+
|
10
|
+
## Quick Start
|
11
|
+
|
12
|
+
### Installation
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
gem "datory"
|
16
|
+
```
|
17
|
+
|
18
|
+
## Contributing
|
19
|
+
|
20
|
+
This project is intended to be a safe, welcoming space for collaboration.
|
21
|
+
Contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
22
|
+
We recommend reading the [contributing guide](./website/docs/CONTRIBUTING.md) as well.
|
23
|
+
|
24
|
+
## License
|
25
|
+
|
26
|
+
Datory is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
en:
|
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}] Nothing to perform. Use `make` or create a `call` method."
|
9
|
+
cannot_be_overwritten: "[%{service_class_name}] The following methods cannot be overwritten: %{list_of_methods}"
|
10
|
+
inputs:
|
11
|
+
undefined:
|
12
|
+
getter: "[%{service_class_name}] Undefined input attribute `%{input_name}`"
|
13
|
+
setter: "[%{service_class_name}] Undefined input attribute `%{input_name}`"
|
14
|
+
validations:
|
15
|
+
inclusion:
|
16
|
+
default_error: "[%{service_class_name}] Wrong value in `%{input_name}`, must be one of `%{input_inclusion}`"
|
17
|
+
must:
|
18
|
+
default_error: "[%{service_class_name}] Input `%{input_name}` must \"%{code}\""
|
19
|
+
syntax_error: "[%{service_class_name}] Syntax error inside `%{code}` of `%{input_name}` input: %{exception_message}"
|
20
|
+
dynamic_options:
|
21
|
+
format:
|
22
|
+
default: "[%{service_class_name}] Input `%{input_name}` does not match `%{format_name}` format"
|
23
|
+
wrong_pattern: "[%{service_class_name}] Input `%{input_name}` does not match `%{format_name}` format"
|
24
|
+
unknown: "[%{service_class_name}] Unknown `%{format_name}` format specified for input `%{input_name}`"
|
25
|
+
min:
|
26
|
+
default: "[%{service_class_name}] Input `%{input_name}` received value `%{value}`, which is less than `%{option_value}`"
|
27
|
+
max:
|
28
|
+
default: "[%{service_class_name}] Input `%{input_name}` received value `%{value}`, which is greater than `%{option_value}`"
|
29
|
+
required:
|
30
|
+
default_error:
|
31
|
+
default: "[%{service_class_name}] Required input `%{input_name}` is missing"
|
32
|
+
for_collection: "[%{service_class_name}] Required element in input collection `%{input_name}` is missing"
|
33
|
+
type:
|
34
|
+
default_error:
|
35
|
+
default: "[%{service_class_name}] Wrong type of input `%{input_name}`, expected `%{expected_type}`, got `%{given_type}`"
|
36
|
+
for_collection:
|
37
|
+
wrong_type: "[%{service_class_name}] Wrong input collection type `%{input_name}`, expected `%{expected_type}`, got `%{given_type}`"
|
38
|
+
wrong_element_type: "[%{service_class_name}] Wrong type in input collection `%{input_name}`, expected `%{expected_type}`, got `%{given_type}`"
|
39
|
+
for_hash:
|
40
|
+
wrong_element_type: "[%{service_class_name}] Wrong type in input hash `%{input_name}`, expected `%{expected_type}` for `%{key_name}`, got `%{given_type}`"
|
41
|
+
tools:
|
42
|
+
find_unnecessary:
|
43
|
+
error: "[%{service_class_name}] Unexpected attributes: `%{unnecessary_attributes}`"
|
44
|
+
rules:
|
45
|
+
error: "[%{service_class_name}] Conflict in `%{input_name}` input options: `%{conflict_code}`"
|
46
|
+
internals:
|
47
|
+
undefined:
|
48
|
+
getter: "[%{service_class_name}] Undefined internal attribute `%{internal_name}`"
|
49
|
+
setter: "[%{service_class_name}] Undefined internal attribute `%{internal_name}`"
|
50
|
+
validations:
|
51
|
+
inclusion:
|
52
|
+
default_error: "[%{service_class_name}] Wrong value in `%{internal_name}`, must be one of `%{internal_inclusion}`"
|
53
|
+
must:
|
54
|
+
default_error: "[%{service_class_name}] Internal attribute `%{internal_name}` must \"%{code}\""
|
55
|
+
syntax_error: "[%{service_class_name}] Syntax error inside `%{code}` of `%{internal_name}` internal attribute: %{exception_message}"
|
56
|
+
dynamic_options:
|
57
|
+
format:
|
58
|
+
default: "[%{service_class_name}] Internal attribute `%{internal_name}` does not match `%{format_name}` format"
|
59
|
+
wrong_pattern: "[%{service_class_name}] Internal attribute `%{internal_name}` does not match `%{format_name}` format"
|
60
|
+
unknown: "[%{service_class_name}] Unknown `%{format_name}` format specified for output attribute `%{internal_name}`"
|
61
|
+
min:
|
62
|
+
default: "[%{service_class_name}] Internal attribute `%{internal_name}` received value `%{value}`, which is less than `%{option_value}`"
|
63
|
+
max:
|
64
|
+
default: "[%{service_class_name}] Internal attribute `%{internal_name}` received value `%{value}`, which is greater than `%{option_value}`"
|
65
|
+
type:
|
66
|
+
default_error:
|
67
|
+
default: "[%{service_class_name}] Wrong type of internal attribute `%{internal_name}`, expected `%{expected_type}`, got `%{given_type}`"
|
68
|
+
for_collection:
|
69
|
+
wrong_type: "[%{service_class_name}] Wrong internal attribute collection type `%{internal_name}`, expected `%{expected_type}`, got `%{given_type}`"
|
70
|
+
wrong_element_type: "[%{service_class_name}] Wrong element type in internal attribute collection `%{internal_name}`, expected `%{expected_type}`, got `%{given_type}`"
|
71
|
+
for_hash:
|
72
|
+
wrong_element_type: "[%{service_class_name}] Wrong type in internal attribute hash `%{internal_name}`, expected `%{expected_type}` for `%{key_name}`, got `%{given_type}`"
|
73
|
+
outputs:
|
74
|
+
undefined:
|
75
|
+
getter: "[%{service_class_name}] Undefined output attribute `%{output_name}`"
|
76
|
+
setter: "[%{service_class_name}] Undefined output attribute `%{output_name}`"
|
77
|
+
validations:
|
78
|
+
inclusion:
|
79
|
+
default_error: "[%{service_class_name}] Wrong value in `%{output_name}`, must be one of `%{output_inclusion}`"
|
80
|
+
must:
|
81
|
+
default_error: "[%{service_class_name}] Output attribute `%{output_name}` must \"%{code}\""
|
82
|
+
syntax_error: "[%{service_class_name}] Syntax error inside `%{code}` of `%{output_name}` output attribute: %{exception_message}"
|
83
|
+
dynamic_options:
|
84
|
+
format:
|
85
|
+
default: "[%{service_class_name}] Output attribute `%{output_name}` does not match `%{format_name}` format"
|
86
|
+
wrong_pattern: "[%{service_class_name}] Output attribute `%{output_name}` does not match `%{format_name}` format"
|
87
|
+
unknown: "[%{service_class_name}] Unknown `%{format_name}` format specified for output attribute `%{output_name}`"
|
88
|
+
min:
|
89
|
+
default: "[%{service_class_name}] Output attribute `%{output_name}` received value `%{value}`, which is less than `%{option_value}`"
|
90
|
+
max:
|
91
|
+
default: "[%{service_class_name}] Output attribute `%{output_name}` received value `%{value}`, which is greater than `%{option_value}`"
|
92
|
+
type:
|
93
|
+
default_error:
|
94
|
+
default: "[%{service_class_name}] Wrong type of output attribute `%{output_name}`, expected `%{expected_type}`, got `%{given_type}`"
|
95
|
+
for_collection:
|
96
|
+
wrong_type: "[%{service_class_name}] Wrong output attribute collection type `%{output_name}`, expected `%{expected_type}`, got `%{given_type}`"
|
97
|
+
wrong_element_type: "[%{service_class_name}] Wrong element type in output attribute collection `%{output_name}`, expected `%{expected_type}`, got `%{given_type}`"
|
98
|
+
for_hash:
|
99
|
+
wrong_element_type: "[%{service_class_name}] Wrong type in output attribute hash `%{output_name}`, expected `%{expected_type}` for `%{key_name}`, got `%{given_type}`"
|
@@ -0,0 +1,99 @@
|
|
1
|
+
ru:
|
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}] Нечего выполнять. Используйте `make` или создайте метод `call`."
|
9
|
+
cannot_be_overwritten: "[%{service_class_name}] Нельзя перезаписать следующие методы: %{list_of_methods}"
|
10
|
+
inputs:
|
11
|
+
undefined:
|
12
|
+
getter: "[%{service_class_name}] Неизвестный входящий атрибут `%{input_name}`"
|
13
|
+
setter: "[%{service_class_name}] Неизвестный входящий атрибут `%{input_name}`"
|
14
|
+
validations:
|
15
|
+
inclusion:
|
16
|
+
default_error: "[%{service_class_name}] Неправильное значение в `%{input_name}`, должно быть одним из `%{input_inclusion}`"
|
17
|
+
must:
|
18
|
+
default_error: "[%{service_class_name}] Инпут `%{input_name}` должен \"%{code}\""
|
19
|
+
syntax_error: "[%{service_class_name}] Синтаксическая ошибка внутри `%{code}` инпута `%{input_name}`: %{exception_message}"
|
20
|
+
dynamic_options:
|
21
|
+
format:
|
22
|
+
default: "[%{service_class_name}] Инпут `%{input_name}` не соответствует формату `%{format_name}`"
|
23
|
+
wrong_pattern: "[%{service_class_name}] Инпут `%{input_name}` не соответствует формату `%{format_name}`"
|
24
|
+
unknown: "[%{service_class_name}] Указан неизвестный формат `%{format_name}` у инпута `%{input_name}`"
|
25
|
+
min:
|
26
|
+
default: "[%{service_class_name}] Инпут `%{input_name}` получил значение `%{value}`, которое меньше `%{option_value}`"
|
27
|
+
max:
|
28
|
+
default: "[%{service_class_name}] Инпут `%{input_name}` получил значение `%{value}`, которое больше `%{option_value}`"
|
29
|
+
required:
|
30
|
+
default_error:
|
31
|
+
default: "[%{service_class_name}] Обязательный инпут `%{input_name}` отсутствует"
|
32
|
+
for_collection: "[%{service_class_name}] Обязательный элемент в коллекции инпута `%{input_name}` отсутствует"
|
33
|
+
type:
|
34
|
+
default_error:
|
35
|
+
default: "[%{service_class_name}] Неправильный тип инпута `%{input_name}`, ожидалось `%{expected_type}`, получено `%{given_type}`"
|
36
|
+
for_collection:
|
37
|
+
wrong_type: "[%{service_class_name}] Неправильный тип коллекции инпута `%{input_name}`, ожидалось `%{expected_type}`, получено `%{given_type}`"
|
38
|
+
wrong_element_type: "[%{service_class_name}] Неправильный тип в коллекции инпута `%{input_name}`, ожидалось `%{expected_type}`, получено `%{given_type}`"
|
39
|
+
for_hash:
|
40
|
+
wrong_element_type: "[%{service_class_name}] Неправильный тип в хеше инпута `%{input_name}`, для `%{key_name}` ожидалось `%{expected_type}`, получено `%{given_type}`"
|
41
|
+
|
42
|
+
tools:
|
43
|
+
find_unnecessary:
|
44
|
+
error: "[%{service_class_name}] Неожиданные атрибуты: `%{unnecessary_attributes}`"
|
45
|
+
rules:
|
46
|
+
error: "[%{service_class_name}] Конфликт в опциях инпута `%{input_name}`: `%{conflict_code}`"
|
47
|
+
internals:
|
48
|
+
undefined:
|
49
|
+
getter: "[%{service_class_name}] Неизвестный внутренний атрибут `%{internal_name}`"
|
50
|
+
setter: "[%{service_class_name}] Неизвестный внутренний атрибут `%{internal_name}`"
|
51
|
+
validations:
|
52
|
+
inclusion:
|
53
|
+
default_error: "[%{service_class_name}] Неправильное значение в `%{internal_name}`, должно быть одним из `%{internal_inclusion}`"
|
54
|
+
must:
|
55
|
+
default_error: "[%{service_class_name}] Внутренний атрибут `%{internal_name}` должен \"%{code}\""
|
56
|
+
syntax_error: "[%{service_class_name}] Синтаксическая ошибка внутри `%{code}` внутреннего атрибута `%{internal_name}`: %{exception_message}"
|
57
|
+
dynamic_options:
|
58
|
+
format:
|
59
|
+
default: "[%{service_class_name}] Внутренний атрибут `%{internal_name}` не соответствует формату `%{format_name}`"
|
60
|
+
wrong_pattern: "[%{service_class_name}] Внутренний атрибут `%{internal_name}` не соответствует формату `%{format_name}`"
|
61
|
+
unknown: "[%{service_class_name}] Указан неизвестный формат `%{format_name}` у внутреннего атрибута `%{internal_name}`"
|
62
|
+
min:
|
63
|
+
default: "[%{service_class_name}] Внутренний атрибут `%{internal_name}` получил значение `%{value}`, которое меньше `%{option_value}`"
|
64
|
+
max:
|
65
|
+
default: "[%{service_class_name}] Внутренний атрибут `%{internal_name}` получил значение `%{value}`, которое больше `%{option_value}`"
|
66
|
+
type:
|
67
|
+
default_error:
|
68
|
+
default: "[%{service_class_name}] Неправильный тип внутреннего атрибута `%{internal_name}`, ожидалось `%{expected_type}`, получено `%{given_type}`"
|
69
|
+
for_collection:
|
70
|
+
wrong_type: "[%{service_class_name}] Неправильный тип коллекции внутреннего атрибута `%{internal_name}`, ожидалось `%{expected_type}`, получено `%{given_type}`"
|
71
|
+
wrong_element_type: "[%{service_class_name}] Неправильный тип элемента в коллекции внутреннего атрибута `%{internal_name}`, ожидалось `%{expected_type}`, получено `%{given_type}`"
|
72
|
+
for_hash:
|
73
|
+
wrong_element_type: "[%{service_class_name}] Неправильный тип в хеше внутреннего атрибута `%{internal_name}`, для `%{key_name}` ожидалось `%{expected_type}`, получено `%{given_type}`"
|
74
|
+
outputs:
|
75
|
+
undefined:
|
76
|
+
getter: "[%{service_class_name}] Неизвестный выходящий атрибут `%{output_name}`"
|
77
|
+
setter: "[%{service_class_name}] Неизвестный выходящий атрибут `%{output_name}`"
|
78
|
+
validations:
|
79
|
+
inclusion:
|
80
|
+
default_error: "[%{service_class_name}] Неправильное значение в `%{output_name}`, должно быть одним из `%{output_inclusion}`"
|
81
|
+
must:
|
82
|
+
default_error: "[%{service_class_name}] Выходящий атрибут `%{output_name}` должен \"%{code}\""
|
83
|
+
syntax_error: "[%{service_class_name}] Синтаксическая ошибка внутри `%{code}` выходящего атрибута `%{output_name}`: %{exception_message}"
|
84
|
+
dynamic_options:
|
85
|
+
format:
|
86
|
+
default: "[%{service_class_name}] Выходящий атрибут `%{output_name}` не соответствует формату `%{format_name}`"
|
87
|
+
wrong_pattern: "[%{service_class_name}] Выходящий атрибут `%{output_name}` не соответствует формату `%{format_name}`"
|
88
|
+
unknown: "[%{service_class_name}] Указан неизвестный формат `%{format_name}` у выходящего атрибута `%{output_name}`"
|
89
|
+
min:
|
90
|
+
default: "[%{service_class_name}] Выходящий атрибут `%{output_name}` получил значение `%{value}`, которое меньше `%{option_value}`"
|
91
|
+
max:
|
92
|
+
default: "[%{service_class_name}] Выходящий атрибут `%{output_name}` получил значение `%{value}`, которое больше `%{option_value}`"
|
93
|
+
type:
|
94
|
+
default: "[%{service_class_name}] Неправильный тип выходящего атрибута `%{output_name}`, ожидалось `%{expected_type}`, получено `%{given_type}`"
|
95
|
+
for_collection:
|
96
|
+
wrong_type: "[%{service_class_name}] Неправильный тип коллекции выходящего атрибута `%{output_name}`, ожидалось `%{expected_type}`, получено `%{given_type}`"
|
97
|
+
wrong_element_type: "[%{service_class_name}] Неправильный тип элемента в коллекции выходящего атрибута `%{output_name}`, ожидалось `%{expected_type}`, получено `%{given_type}`"
|
98
|
+
for_hash:
|
99
|
+
wrong_element_type: "[%{service_class_name}] Неправильный тип в хеше выходящего атрибута `%{output_name}`, для `%{key_name}` ожидалось `%{expected_type}`, получено `%{given_type}`"
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datory
|
4
|
+
module Attributes
|
5
|
+
class Collection
|
6
|
+
extend Forwardable
|
7
|
+
def_delegators :@collection, :<<, :each, :map, :merge # :filter, :each, :map, :flat_map, :to_h, :merge, :find
|
8
|
+
|
9
|
+
def initialize(collection = Set.new)
|
10
|
+
@collection = collection
|
11
|
+
end
|
12
|
+
|
13
|
+
# def only(*names)
|
14
|
+
# Collection.new(filter { |input| names.include?(input.internal_name) })
|
15
|
+
# end
|
16
|
+
|
17
|
+
# def except(*names)
|
18
|
+
# Collection.new(filter { |input| !names.include?(input.internal_name) })
|
19
|
+
# end
|
20
|
+
|
21
|
+
def names
|
22
|
+
map(&:name)
|
23
|
+
end
|
24
|
+
|
25
|
+
# def find_by(name:)
|
26
|
+
# find { |input| input.internal_name == name }
|
27
|
+
# end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datory
|
4
|
+
module Attributes
|
5
|
+
module DSL
|
6
|
+
def self.included(base)
|
7
|
+
base.extend(ClassMethods)
|
8
|
+
base.include(Workspace)
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
def inherited(child)
|
13
|
+
super
|
14
|
+
|
15
|
+
child.send(:collection_of_attributes).merge(collection_of_attributes)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def singular(value)
|
21
|
+
@singular = value
|
22
|
+
end
|
23
|
+
|
24
|
+
def plural(value)
|
25
|
+
@plural = value
|
26
|
+
end
|
27
|
+
|
28
|
+
def attribute(name, **options)
|
29
|
+
collection_of_attributes << Attribute.new(name, **options)
|
30
|
+
end
|
31
|
+
|
32
|
+
def string(name, **options)
|
33
|
+
options = options.merge(type: String)
|
34
|
+
attribute(name, **options)
|
35
|
+
end
|
36
|
+
|
37
|
+
def integer(name, **options)
|
38
|
+
options = options.merge(type: Integer)
|
39
|
+
attribute(name, **options)
|
40
|
+
end
|
41
|
+
|
42
|
+
def float(name, **options)
|
43
|
+
options = options.merge(type: Float)
|
44
|
+
attribute(name, **options)
|
45
|
+
end
|
46
|
+
|
47
|
+
def date(name, **options)
|
48
|
+
options = options.merge(type: Date)
|
49
|
+
attribute(name, **options)
|
50
|
+
end
|
51
|
+
|
52
|
+
def time(name, **options)
|
53
|
+
options = options.merge(type: Time)
|
54
|
+
attribute(name, **options)
|
55
|
+
end
|
56
|
+
|
57
|
+
def datetime(name, **options)
|
58
|
+
options = options.merge(type: DateTime)
|
59
|
+
attribute(name, **options)
|
60
|
+
end
|
61
|
+
|
62
|
+
def one(name, include:, as: nil)
|
63
|
+
attribute(name, as: as.presence || name, type: Hash, include: include)
|
64
|
+
end
|
65
|
+
|
66
|
+
def many(name, include:, as: nil)
|
67
|
+
attribute(name, as: as.presence || name, type: Array, consists_of: Hash, include: include)
|
68
|
+
end
|
69
|
+
|
70
|
+
def collection_of_attributes
|
71
|
+
@collection_of_attributes ||= Collection.new
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datory
|
4
|
+
module Attributes
|
5
|
+
module Workspace
|
6
|
+
class ServiceFactory
|
7
|
+
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
8
|
+
def self.create(model_class, class_name, collection_of_attributes)
|
9
|
+
return if model_class.const_defined?(class_name)
|
10
|
+
|
11
|
+
class_sample = Class.new(Datory::Service::Builder) do
|
12
|
+
collection_of_attributes.each do |attribute| # rubocop:disable Metrics/BlockLength
|
13
|
+
input_internal_name = attribute.options.fetch(:as, attribute.name)
|
14
|
+
|
15
|
+
input attribute.name,
|
16
|
+
as: input_internal_name,
|
17
|
+
type: attribute.options.fetch(:type),
|
18
|
+
required: attribute.options.fetch(:required, true),
|
19
|
+
consists_of: attribute.options.fetch(:consists_of, false),
|
20
|
+
prepare: (lambda do |value:|
|
21
|
+
include_class = attribute.options.fetch(:include, nil)
|
22
|
+
return value unless include_class.present?
|
23
|
+
|
24
|
+
type = attribute.options.fetch(:type, nil)
|
25
|
+
|
26
|
+
if [Set, Array].include?(type)
|
27
|
+
value.map { |item| include_class.build(**item) }
|
28
|
+
else
|
29
|
+
include_class.build(**value)
|
30
|
+
end
|
31
|
+
end)
|
32
|
+
|
33
|
+
output input_internal_name,
|
34
|
+
consists_of: (
|
35
|
+
if (type = attribute.options.fetch(:consists_of, false)) == Hash
|
36
|
+
Datory::Result
|
37
|
+
else
|
38
|
+
type
|
39
|
+
end
|
40
|
+
),
|
41
|
+
type: if (type = attribute.options.fetch(:type)) == Hash
|
42
|
+
Datory::Result
|
43
|
+
else
|
44
|
+
type
|
45
|
+
end
|
46
|
+
|
47
|
+
make :"assign_#{input_internal_name}_output"
|
48
|
+
|
49
|
+
define_method(:"assign_#{input_internal_name}_output") do
|
50
|
+
outputs.public_send(:"#{input_internal_name}=", inputs.public_send(input_internal_name))
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
model_class.const_set(class_name, class_sample)
|
56
|
+
end
|
57
|
+
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def build!(incoming_attributes:, collection_of_attributes:, **)
|
63
|
+
super
|
64
|
+
|
65
|
+
builder_class_name = "GBuilder"
|
66
|
+
|
67
|
+
ServiceFactory.create(self.class, builder_class_name, collection_of_attributes)
|
68
|
+
|
69
|
+
builder_class = "#{self.class.name}::#{builder_class_name}".constantize
|
70
|
+
|
71
|
+
builder_class.call!(**incoming_attributes)
|
72
|
+
|
73
|
+
# Tools::Unnecessary.find!(self, attributes, collection_of_attributes)
|
74
|
+
# Tools::Rules.check!(self, collection_of_attributes)
|
75
|
+
# Tools::Validation.validate!(self, attributes, collection_of_attributes)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
data/lib/datory/base.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datory
|
4
|
+
module Context
|
5
|
+
module Callable
|
6
|
+
def serialize(model)
|
7
|
+
hash = {}
|
8
|
+
|
9
|
+
collection_of_attributes.each do |attribute|
|
10
|
+
internal_name = attribute.options.fetch(:as, attribute.name)
|
11
|
+
include_class = attribute.options.fetch(:include, nil)
|
12
|
+
output_formatter = attribute.options.fetch(:output, nil)
|
13
|
+
|
14
|
+
value = model.public_send(internal_name)
|
15
|
+
|
16
|
+
value =
|
17
|
+
if include_class.present?
|
18
|
+
type = attribute.options.fetch(:type, nil)
|
19
|
+
|
20
|
+
if [Set, Array].include?(type)
|
21
|
+
value.map { |item| include_class.serialize(item) }
|
22
|
+
else
|
23
|
+
include_class.serialize(value)
|
24
|
+
end
|
25
|
+
elsif output_formatter.is_a?(Proc)
|
26
|
+
output_formatter.call(value: value)
|
27
|
+
elsif [Date, Time, DateTime].include?(value.class)
|
28
|
+
value.to_s
|
29
|
+
else
|
30
|
+
value
|
31
|
+
end
|
32
|
+
|
33
|
+
hash[attribute.name] = value
|
34
|
+
end
|
35
|
+
|
36
|
+
hash
|
37
|
+
end
|
38
|
+
|
39
|
+
def deserialize(json)
|
40
|
+
hash = JSON.parse(json.to_json)
|
41
|
+
build(**hash)
|
42
|
+
end
|
43
|
+
|
44
|
+
# def build!(attributes = {})
|
45
|
+
# context = send(:new)
|
46
|
+
#
|
47
|
+
# _build!(context, **attributes)
|
48
|
+
# end
|
49
|
+
|
50
|
+
def build(attributes = {})
|
51
|
+
context = send(:new)
|
52
|
+
|
53
|
+
_build!(context, **attributes)
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def _build!(context, **attributes)
|
59
|
+
context.send(
|
60
|
+
:_build!,
|
61
|
+
incoming_attributes: attributes.symbolize_keys,
|
62
|
+
collection_of_attributes: collection_of_attributes
|
63
|
+
)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datory
|
4
|
+
module Context
|
5
|
+
module Workspace
|
6
|
+
def attributes
|
7
|
+
@attributes ||= Attributes.new(
|
8
|
+
context: self,
|
9
|
+
incoming_attributes: incoming_attributes,
|
10
|
+
collection_of_attributes: collection_of_attributes
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
attr_reader :incoming_attributes,
|
17
|
+
:collection_of_attributes
|
18
|
+
|
19
|
+
def _build!(
|
20
|
+
incoming_attributes:,
|
21
|
+
collection_of_attributes:
|
22
|
+
)
|
23
|
+
build!(
|
24
|
+
incoming_attributes: incoming_attributes,
|
25
|
+
collection_of_attributes: collection_of_attributes
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
def build!(
|
30
|
+
incoming_attributes:,
|
31
|
+
collection_of_attributes:,
|
32
|
+
**
|
33
|
+
)
|
34
|
+
@incoming_attributes = incoming_attributes
|
35
|
+
@collection_of_attributes = collection_of_attributes
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datory
|
4
|
+
module Service
|
5
|
+
class Base
|
6
|
+
include Servactory::DSL
|
7
|
+
|
8
|
+
configuration do
|
9
|
+
input_exception_class Datory::Service::Exceptions::Input
|
10
|
+
internal_exception_class Datory::Service::Exceptions::Internal
|
11
|
+
output_exception_class Datory::Service::Exceptions::Output
|
12
|
+
|
13
|
+
failure_class Datory::Service::Exceptions::Failure
|
14
|
+
|
15
|
+
result_class Datory::Result
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datory
|
4
|
+
module Service
|
5
|
+
module Exceptions
|
6
|
+
class Input < Servactory::Exceptions::Input; end
|
7
|
+
class Output < Servactory::Exceptions::Output; end
|
8
|
+
class Internal < Servactory::Exceptions::Internal; end
|
9
|
+
|
10
|
+
class Failure < Servactory::Exceptions::Failure; end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/lib/datory.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "zeitwerk"
|
4
|
+
|
5
|
+
require "active_support/all"
|
6
|
+
|
7
|
+
require "uri"
|
8
|
+
|
9
|
+
loader = Zeitwerk::Loader.for_gem
|
10
|
+
loader.inflector.inflect(
|
11
|
+
"dsl" => "DSL"
|
12
|
+
)
|
13
|
+
loader.setup
|
14
|
+
|
15
|
+
module Datory; end
|
16
|
+
|
17
|
+
require "datory/engine" if defined?(Rails::Engine)
|
metadata
ADDED
@@ -0,0 +1,241 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: datory
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0.rc1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Anton Sokolov
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-04-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '5.1'
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '7.2'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '5.1'
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '7.2'
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: i18n
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '1.14'
|
40
|
+
type: :runtime
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '1.14'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: servactory
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '2.4'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '2.4'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: zeitwerk
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '2.6'
|
68
|
+
type: :runtime
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '2.6'
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: appraisal
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '2.5'
|
82
|
+
type: :development
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - "~>"
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '2.5'
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: rake
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - "~>"
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '13.0'
|
96
|
+
type: :development
|
97
|
+
prerelease: false
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - "~>"
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '13.0'
|
103
|
+
- !ruby/object:Gem::Dependency
|
104
|
+
name: rbs
|
105
|
+
requirement: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 3.1.3
|
110
|
+
type: :development
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - ">="
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: 3.1.3
|
117
|
+
- !ruby/object:Gem::Dependency
|
118
|
+
name: rspec
|
119
|
+
requirement: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - "~>"
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '3.12'
|
124
|
+
type: :development
|
125
|
+
prerelease: false
|
126
|
+
version_requirements: !ruby/object:Gem::Requirement
|
127
|
+
requirements:
|
128
|
+
- - "~>"
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: '3.12'
|
131
|
+
- !ruby/object:Gem::Dependency
|
132
|
+
name: rubocop
|
133
|
+
requirement: !ruby/object:Gem::Requirement
|
134
|
+
requirements:
|
135
|
+
- - "~>"
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '1.57'
|
138
|
+
type: :development
|
139
|
+
prerelease: false
|
140
|
+
version_requirements: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - "~>"
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '1.57'
|
145
|
+
- !ruby/object:Gem::Dependency
|
146
|
+
name: rubocop-performance
|
147
|
+
requirement: !ruby/object:Gem::Requirement
|
148
|
+
requirements:
|
149
|
+
- - "~>"
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
version: '1.19'
|
152
|
+
type: :development
|
153
|
+
prerelease: false
|
154
|
+
version_requirements: !ruby/object:Gem::Requirement
|
155
|
+
requirements:
|
156
|
+
- - "~>"
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
version: '1.19'
|
159
|
+
- !ruby/object:Gem::Dependency
|
160
|
+
name: rubocop-rake
|
161
|
+
requirement: !ruby/object:Gem::Requirement
|
162
|
+
requirements:
|
163
|
+
- - "~>"
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: '0.6'
|
166
|
+
type: :development
|
167
|
+
prerelease: false
|
168
|
+
version_requirements: !ruby/object:Gem::Requirement
|
169
|
+
requirements:
|
170
|
+
- - "~>"
|
171
|
+
- !ruby/object:Gem::Version
|
172
|
+
version: '0.6'
|
173
|
+
- !ruby/object:Gem::Dependency
|
174
|
+
name: rubocop-rspec
|
175
|
+
requirement: !ruby/object:Gem::Requirement
|
176
|
+
requirements:
|
177
|
+
- - "~>"
|
178
|
+
- !ruby/object:Gem::Version
|
179
|
+
version: '2.24'
|
180
|
+
type: :development
|
181
|
+
prerelease: false
|
182
|
+
version_requirements: !ruby/object:Gem::Requirement
|
183
|
+
requirements:
|
184
|
+
- - "~>"
|
185
|
+
- !ruby/object:Gem::Version
|
186
|
+
version: '2.24'
|
187
|
+
description: A set of tools for building reliable services of any complexity
|
188
|
+
email:
|
189
|
+
- profox.rus@gmail.com
|
190
|
+
executables: []
|
191
|
+
extensions: []
|
192
|
+
extra_rdoc_files: []
|
193
|
+
files:
|
194
|
+
- README.md
|
195
|
+
- Rakefile
|
196
|
+
- config/locales/en.yml
|
197
|
+
- config/locales/ru.yml
|
198
|
+
- lib/datory.rb
|
199
|
+
- lib/datory/attributes/attribute.rb
|
200
|
+
- lib/datory/attributes/collection.rb
|
201
|
+
- lib/datory/attributes/dsl.rb
|
202
|
+
- lib/datory/attributes/workspace.rb
|
203
|
+
- lib/datory/base.rb
|
204
|
+
- lib/datory/context/callable.rb
|
205
|
+
- lib/datory/context/dsl.rb
|
206
|
+
- lib/datory/context/workspace.rb
|
207
|
+
- lib/datory/result.rb
|
208
|
+
- lib/datory/service/base.rb
|
209
|
+
- lib/datory/service/builder.rb
|
210
|
+
- lib/datory/service/exceptions.rb
|
211
|
+
- lib/datory/version.rb
|
212
|
+
homepage: https://github.com/servactory/datory
|
213
|
+
licenses:
|
214
|
+
- MIT
|
215
|
+
metadata:
|
216
|
+
homepage_uri: https://github.com/servactory/datory
|
217
|
+
documentation_uri: https://datory.servactory.com
|
218
|
+
source_code_uri: https://github.com/servactory/datory
|
219
|
+
bug_tracker_uri: https://github.com/servactory/datory/issues
|
220
|
+
changelog_uri: https://github.com/servactory/datory/blob/master/CHANGELOG.md
|
221
|
+
rubygems_mfa_required: 'true'
|
222
|
+
post_install_message:
|
223
|
+
rdoc_options: []
|
224
|
+
require_paths:
|
225
|
+
- lib
|
226
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
227
|
+
requirements:
|
228
|
+
- - ">="
|
229
|
+
- !ruby/object:Gem::Version
|
230
|
+
version: 3.0.0
|
231
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
232
|
+
requirements:
|
233
|
+
- - ">="
|
234
|
+
- !ruby/object:Gem::Version
|
235
|
+
version: '0'
|
236
|
+
requirements: []
|
237
|
+
rubygems_version: 3.5.6
|
238
|
+
signing_key:
|
239
|
+
specification_version: 4
|
240
|
+
summary: A set of tools for building reliable services of any complexity
|
241
|
+
test_files: []
|