smart_initializer 0.5.0 → 0.9.0
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/.rubocop.yml +1 -1
- data/CHANGELOG.md +46 -1
- data/Gemfile.lock +45 -44
- data/LICENSE.txt +1 -1
- data/README.md +283 -40
- data/bin/console +2 -2
- data/gemfiles/with_external_deps.gemfile.lock +38 -38
- data/gemfiles/without_external_deps.gemfile.lock +50 -45
- data/lib/smart_core/initializer/attribute/factory/base.rb +145 -0
- data/lib/smart_core/initializer/attribute/factory/option.rb +107 -0
- data/lib/smart_core/initializer/attribute/factory/param.rb +63 -0
- data/lib/smart_core/initializer/attribute/factory.rb +5 -199
- data/lib/smart_core/initializer/attribute/finalizer/abstract.rb +2 -0
- data/lib/smart_core/initializer/attribute/finalizer/instance_method.rb +1 -1
- data/lib/smart_core/initializer/attribute/finalizer.rb +5 -5
- data/lib/smart_core/initializer/attribute/list.rb +20 -0
- data/lib/smart_core/initializer/attribute/{parameters.rb → value/base.rb} +35 -65
- data/lib/smart_core/initializer/attribute/value/option.rb +101 -0
- data/lib/smart_core/initializer/attribute/value/param.rb +24 -0
- data/lib/smart_core/initializer/attribute/value.rb +9 -0
- data/lib/smart_core/initializer/attribute.rb +3 -112
- data/lib/smart_core/initializer/configuration.rb +9 -0
- data/lib/smart_core/initializer/constructor/definer.rb +135 -46
- data/lib/smart_core/initializer/constructor.rb +29 -14
- data/lib/smart_core/initializer/dsl.rb +38 -24
- data/lib/smart_core/initializer/errors.rb +20 -0
- data/lib/smart_core/initializer/functionality.rb +7 -8
- data/lib/smart_core/initializer/plugins/thy_types/thy_types/abstract_factory.rb +13 -2
- data/lib/smart_core/initializer/settings/auto_cast.rb +40 -0
- data/lib/smart_core/initializer/settings/base.rb +49 -0
- data/lib/smart_core/initializer/settings/duplicator.rb +5 -0
- data/lib/smart_core/initializer/settings/strict_options.rb +40 -0
- data/lib/smart_core/initializer/settings/type_system.rb +10 -28
- data/lib/smart_core/initializer/settings.rb +40 -0
- data/lib/smart_core/initializer/type_system/interop/abstract_factory.rb +12 -2
- data/lib/smart_core/initializer/type_system/interop.rb +10 -1
- data/lib/smart_core/initializer/type_system/registry.rb +2 -1
- data/lib/smart_core/initializer/type_system/smart_types/abstract_factory.rb +13 -2
- data/lib/smart_core/initializer/type_system/smart_types.rb +2 -2
- data/lib/smart_core/initializer/version.rb +2 -2
- data/lib/smart_core/initializer.rb +14 -4
- data/smart_initializer.gemspec +3 -3
- metadata +18 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9ef704918e8e3d81bfb2dd551b96f4e68f2a0f2cefacfdbced95ae9cce1a6b0b
|
4
|
+
data.tar.gz: 3960c509958efb9a0886d959ff3a55b6965bb916f80bd32bf04e0977d58b7560
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 329ebcfc66cab98ab6e35b392c425df04eb5d03260b3bcefceb6c9cffa8863bad1fafce5d3b822c4fd0d39e0caab36a502b38a8ed15ecba1f0157908a6bbbc0d
|
7
|
+
data.tar.gz: 31f8259c26367c56961dc70cd086dcae7e96f3eafa206b3395b2f4afc0cb25afc3bba6d55a94251d1495bb13fd27c3c590ca67ace17bba1af226b48ceacfb7a9
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,9 +1,54 @@
|
|
1
1
|
# Changelog
|
2
2
|
All notable changes to this project will be documented in this file.
|
3
3
|
|
4
|
+
## [0.9.0] - 2021-12-19
|
5
|
+
### Changed
|
6
|
+
- `:finalize` block is not invoked on the `option` with `optional: true` flag;
|
7
|
+
|
8
|
+
## [0.8.0] - 2021-12-04
|
9
|
+
### Added
|
10
|
+
- New options for option and param attributes:
|
11
|
+
- Support for attribute **aliasing** (`:as` parameter);
|
12
|
+
- supports: `option`, `param`;
|
13
|
+
- Support for attribute **auto-casting** (`:auto_cast` parameter);
|
14
|
+
- supports: `option`, `param`;
|
15
|
+
- Support for **mutable** attributes (`:mutable` parameter) with type-validation inside;
|
16
|
+
- supports: `option`, `options`, `param`, `params`;
|
17
|
+
- Support for **optional** attributes (`:optional` parameter);
|
18
|
+
- supports: `option`;
|
19
|
+
- **SmartCore::Initializer::Configuration**:
|
20
|
+
- Configuration setting `strict_options` now works separately "per-class" in all configs manner
|
21
|
+
(each class shares the global state but has own state too)
|
22
|
+
- Support for per-class/global `:auto_cast` configuration;
|
23
|
+
- provides a global/per-class behavior for `:cast` option (`false` by default);
|
24
|
+
- `options` declaration now supports `privacy` option;
|
25
|
+
- `params` declaration now supports `privacy` option;
|
26
|
+
|
27
|
+
### Changed
|
28
|
+
- Drop support of **Ruby@2.4**;
|
29
|
+
- `:default` attribute parameter now duplicates the passed value during object instantiation;
|
30
|
+
- `:default` attribute parameter only works with `option` attribute (`param` can't have `default` parameter now);
|
31
|
+
- Attribute values generated by `:finalize` are type-validated now too;
|
32
|
+
- Now lambda-based `:finalize` attributes are being checked for the signature during attribute declaration;
|
33
|
+
- Some error messages have become more readable;
|
34
|
+
|
35
|
+
## Fixed
|
36
|
+
- `send` method overlaping/rewriting: otions and params named as `send` breaks the internal
|
37
|
+
framework-related invocations of the attribute definitioning inside the custom object constructor
|
38
|
+
(this name rewrites internal Ruby's `send` method and brokes some things);
|
39
|
+
|
40
|
+
## [0.7.0] - 2021-06-23
|
41
|
+
### Added
|
42
|
+
- `strict_options` config option for non-strict checking of passed options;
|
43
|
+
|
44
|
+
## [0.6.0] - 2021-06-23
|
45
|
+
### Added
|
46
|
+
- Validation messages for incorrect attribute types;
|
47
|
+
|
4
48
|
## [0.5.0] - 2021-01-18
|
5
|
-
|
49
|
+
### Changed
|
6
50
|
- Updated `smart_types` dependency (`~> 0.4.0`) to guarantee **Ruby@3** compatibility;
|
51
|
+
- Updated development dependencies;
|
7
52
|
|
8
53
|
## [0.4.0] - 2021-01-18
|
9
54
|
### Added
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
smart_initializer (0.
|
4
|
+
smart_initializer (0.9.0)
|
5
5
|
qonfig (~> 0.24)
|
6
6
|
smart_engine (~> 0.11)
|
7
7
|
smart_types (~> 0.4)
|
@@ -9,39 +9,39 @@ PATH
|
|
9
9
|
GEM
|
10
10
|
remote: https://rubygems.org/
|
11
11
|
specs:
|
12
|
-
activesupport (6.1.1)
|
12
|
+
activesupport (6.1.4.1)
|
13
13
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
14
14
|
i18n (>= 1.6, < 2)
|
15
15
|
minitest (>= 5.1)
|
16
16
|
tzinfo (~> 2.0)
|
17
17
|
zeitwerk (~> 2.3)
|
18
|
-
armitage-rubocop (1.
|
19
|
-
rubocop (= 1.
|
20
|
-
rubocop-performance (= 1.
|
21
|
-
rubocop-rails (= 2.
|
22
|
-
rubocop-rake (= 0.
|
23
|
-
rubocop-rspec (= 2.
|
24
|
-
ast (2.4.
|
18
|
+
armitage-rubocop (1.23.0.1)
|
19
|
+
rubocop (= 1.23.0)
|
20
|
+
rubocop-performance (= 1.12.0)
|
21
|
+
rubocop-rails (= 2.12.4)
|
22
|
+
rubocop-rake (= 0.6.0)
|
23
|
+
rubocop-rspec (= 2.6.0)
|
24
|
+
ast (2.4.2)
|
25
25
|
coderay (1.1.3)
|
26
|
-
concurrent-ruby (1.1.
|
26
|
+
concurrent-ruby (1.1.9)
|
27
27
|
diff-lcs (1.4.4)
|
28
|
-
docile (1.
|
29
|
-
i18n (1.8.
|
28
|
+
docile (1.4.0)
|
29
|
+
i18n (1.8.11)
|
30
30
|
concurrent-ruby (~> 1.0)
|
31
31
|
method_source (1.0.0)
|
32
|
-
minitest (5.14.
|
33
|
-
parallel (1.
|
34
|
-
parser (3.0.
|
32
|
+
minitest (5.14.4)
|
33
|
+
parallel (1.21.0)
|
34
|
+
parser (3.0.3.1)
|
35
35
|
ast (~> 2.4.1)
|
36
|
-
pry (0.
|
36
|
+
pry (0.14.1)
|
37
37
|
coderay (~> 1.1)
|
38
38
|
method_source (~> 1.0)
|
39
|
-
qonfig (0.
|
39
|
+
qonfig (0.26.0)
|
40
40
|
rack (2.2.3)
|
41
41
|
rainbow (3.0.0)
|
42
|
-
rake (13.0.
|
43
|
-
regexp_parser (2.0
|
44
|
-
rexml (3.2.
|
42
|
+
rake (13.0.6)
|
43
|
+
regexp_parser (2.2.0)
|
44
|
+
rexml (3.2.5)
|
45
45
|
rspec (3.10.0)
|
46
46
|
rspec-core (~> 3.10.0)
|
47
47
|
rspec-expectations (~> 3.10.0)
|
@@ -51,59 +51,60 @@ GEM
|
|
51
51
|
rspec-expectations (3.10.1)
|
52
52
|
diff-lcs (>= 1.2.0, < 2.0)
|
53
53
|
rspec-support (~> 3.10.0)
|
54
|
-
rspec-mocks (3.10.
|
54
|
+
rspec-mocks (3.10.2)
|
55
55
|
diff-lcs (>= 1.2.0, < 2.0)
|
56
56
|
rspec-support (~> 3.10.0)
|
57
|
-
rspec-support (3.10.
|
58
|
-
rubocop (1.
|
57
|
+
rspec-support (3.10.3)
|
58
|
+
rubocop (1.23.0)
|
59
59
|
parallel (~> 1.10)
|
60
|
-
parser (>=
|
60
|
+
parser (>= 3.0.0.0)
|
61
61
|
rainbow (>= 2.2.2, < 4.0)
|
62
62
|
regexp_parser (>= 1.8, < 3.0)
|
63
63
|
rexml
|
64
|
-
rubocop-ast (>= 1.
|
64
|
+
rubocop-ast (>= 1.12.0, < 2.0)
|
65
65
|
ruby-progressbar (~> 1.7)
|
66
|
-
unicode-display_width (>= 1.4.0, <
|
67
|
-
rubocop-ast (1.
|
68
|
-
parser (>=
|
69
|
-
rubocop-performance (1.
|
70
|
-
rubocop (>=
|
66
|
+
unicode-display_width (>= 1.4.0, < 3.0)
|
67
|
+
rubocop-ast (1.14.0)
|
68
|
+
parser (>= 3.0.1.1)
|
69
|
+
rubocop-performance (1.12.0)
|
70
|
+
rubocop (>= 1.7.0, < 2.0)
|
71
71
|
rubocop-ast (>= 0.4.0)
|
72
|
-
rubocop-rails (2.
|
72
|
+
rubocop-rails (2.12.4)
|
73
73
|
activesupport (>= 4.2.0)
|
74
74
|
rack (>= 1.1)
|
75
|
-
rubocop (>=
|
76
|
-
rubocop-rake (0.
|
77
|
-
rubocop
|
78
|
-
rubocop-rspec (2.1.0)
|
75
|
+
rubocop (>= 1.7.0, < 2.0)
|
76
|
+
rubocop-rake (0.6.0)
|
79
77
|
rubocop (~> 1.0)
|
80
|
-
|
78
|
+
rubocop-rspec (2.6.0)
|
79
|
+
rubocop (~> 1.19)
|
81
80
|
ruby-progressbar (1.11.0)
|
82
81
|
simplecov (0.21.2)
|
83
82
|
docile (~> 1.1)
|
84
83
|
simplecov-html (~> 0.11)
|
85
84
|
simplecov_json_formatter (~> 0.1)
|
86
85
|
simplecov-html (0.12.3)
|
87
|
-
simplecov_json_formatter (0.1.
|
88
|
-
smart_engine (0.
|
89
|
-
smart_types (0.
|
86
|
+
simplecov_json_formatter (0.1.3)
|
87
|
+
smart_engine (0.12.0)
|
88
|
+
smart_types (0.7.0)
|
90
89
|
smart_engine (~> 0.11)
|
91
90
|
tzinfo (2.0.4)
|
92
91
|
concurrent-ruby (~> 1.0)
|
93
|
-
unicode-display_width (1.
|
94
|
-
zeitwerk (2.
|
92
|
+
unicode-display_width (2.1.0)
|
93
|
+
zeitwerk (2.5.1)
|
95
94
|
|
96
95
|
PLATFORMS
|
96
|
+
x86_64-darwin-19
|
97
97
|
x86_64-darwin-20
|
98
|
+
x86_64-darwin-21
|
98
99
|
|
99
100
|
DEPENDENCIES
|
100
|
-
armitage-rubocop (~> 1.
|
101
|
+
armitage-rubocop (~> 1.23)
|
101
102
|
bundler (~> 2.2)
|
102
|
-
pry (~> 0.
|
103
|
+
pry (~> 0.14)
|
103
104
|
rake (~> 13.0)
|
104
105
|
rspec (~> 3.10)
|
105
106
|
simplecov (~> 0.21)
|
106
107
|
smart_initializer!
|
107
108
|
|
108
109
|
BUNDLED WITH
|
109
|
-
2.2.
|
110
|
+
2.2.32
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,8 +1,14 @@
|
|
1
|
-
# SmartCore::Initializer · [](https://badge.fury.io/rb/smart_initializer)
|
1
|
+
# SmartCore::Initializer · <a target="_blank" href="https://github.com/Cado-Labs"><img src="https://github.com/Cado-Labs/cado-labs-logos/raw/main/cado_labs_badge.svg" alt="Supported by Cado Labs" style="max-width: 100%; height: 20px"></a> · [](https://badge.fury.io/rb/smart_initializer)
|
2
2
|
|
3
3
|
A simple and convenient way to declare complex constructors with a support for various commonly used type systems.
|
4
4
|
(**in active development**).
|
5
5
|
|
6
|
+
---
|
7
|
+
|
8
|
+
<img src="https://github.com/Cado-Labs/cado-labs-resources/blob/main/cado_labs_supporting_rounded.svg" alt="Supported by Cado Labs" />
|
9
|
+
|
10
|
+
---
|
11
|
+
|
6
12
|
## Installation
|
7
13
|
|
8
14
|
```ruby
|
@@ -24,9 +30,21 @@ require 'smart_core/initializer'
|
|
24
30
|
## Table of contents
|
25
31
|
|
26
32
|
- [Synopsis](#synopsis)
|
33
|
+
- [Initialization flow](#initialization-flow)
|
34
|
+
- [Attribute value definition flow](#attribute-value-definition-flow-during-object-allocation-and-construction)
|
35
|
+
- [Constructor definition DSL](#constructor-definition-dsl)
|
36
|
+
- [param](#param)
|
37
|
+
- [option](#option)
|
38
|
+
- [params](#params)
|
39
|
+
- [options](#options)
|
40
|
+
- [param and params signature](#param-and-params-signautre)
|
41
|
+
- [option and options signature](#option-and-options-signature)
|
42
|
+
- [Initializer integration](#initializer-integration)
|
43
|
+
- [Basic Example](#basic-example)
|
27
44
|
- [Access to the instance attributes](#access-to-the-instance-attributes)
|
28
45
|
- [Configuration](#configuration)
|
29
46
|
- [Type aliasing](#type-aliasing)
|
47
|
+
- [Type casting](#type-casting)
|
30
48
|
- [Initialization extension](#initialization-extension)
|
31
49
|
- [Plugins](#plugins)
|
32
50
|
- [thy-types](#plugin-thy-types)
|
@@ -37,51 +55,92 @@ require 'smart_core/initializer'
|
|
37
55
|
|
38
56
|
## Synopsis
|
39
57
|
|
40
|
-
|
58
|
+
#### Initialization flow
|
41
59
|
|
42
|
-
1. Parameter + Option definitioning;
|
43
|
-
2. Original
|
60
|
+
1. Parameter + Option definitioning and initialization (custom object allocator and constructor);
|
61
|
+
2. Original **#initialize** invokation;
|
44
62
|
3. Initialization extensions invokation;
|
45
63
|
|
46
|
-
**
|
64
|
+
**NOTE!**: **SmarteCore::Initializer**'s constructor is invoked first
|
65
|
+
in order to guarantee the validity of the SmartCore::Initializer's functionality
|
66
|
+
(such as `attribute overlap chek`, `instant type checking`, `value post-processing by finalize`, etc)
|
47
67
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
- `privacy` - reader incapsulation level;
|
57
|
-
- `finalize` - value post-processing (receives method name or proc);
|
58
|
-
- `default` - defalut value (if an attribute is not provided);
|
59
|
-
- `type_system` - differently chosen type system for the current attribute;
|
60
|
-
- last `Hash` argument will be treated as `kwarg`s;
|
61
|
-
|
62
|
-
#### initializer integration
|
68
|
+
#### Attribute value definition flow (during object allocation and construction):
|
69
|
+
|
70
|
+
1. `original value`
|
71
|
+
2. *(if defined)*: `default value` (default value is used when `original value` is not defined)
|
72
|
+
3. *(if defined)*: `finalize`;
|
73
|
+
|
74
|
+
**NOTE**: `:finalize` block are not invoked on omitted `optional: true` attributes
|
75
|
+
which has no `:default` definition bock and which are not passed to the constructor. Example:
|
63
76
|
|
64
77
|
```ruby
|
65
|
-
#
|
78
|
+
# without :default
|
66
79
|
|
67
|
-
class
|
80
|
+
class User
|
68
81
|
include SmartCore::Initializer
|
82
|
+
option :age, :string, optional: true, finalize: -> (val) { "#{val}_years" }
|
69
83
|
end
|
84
|
+
|
85
|
+
User.new.age # => nil
|
70
86
|
```
|
71
87
|
|
72
88
|
```ruby
|
73
|
-
# with
|
89
|
+
# with :default
|
74
90
|
|
75
|
-
class
|
76
|
-
include SmartCore::Initializer
|
91
|
+
class User
|
92
|
+
include SmartCore::Initializer
|
93
|
+
option :age, :string, optional: true, default: '0', finalize: -> (val) { "#{val}_years" }
|
77
94
|
end
|
78
95
|
|
79
|
-
|
80
|
-
include SmartCore::Initializer(type_system: :thy_types)
|
81
|
-
end
|
96
|
+
User.new.age # => '0_years'
|
82
97
|
```
|
83
98
|
|
84
|
-
|
99
|
+
### Constructor definition DSL
|
100
|
+
|
101
|
+
**NOTE**: last `Hash` argument will be treated as `kwarg`s;
|
102
|
+
|
103
|
+
#### param
|
104
|
+
|
105
|
+
- `param` - defines name-like attribute:
|
106
|
+
- `cast` (optional) - type-cast received value if value has invalid type;
|
107
|
+
- `privacy` (optional) - reader incapsulation level;
|
108
|
+
- `finalize` (optional) - value post-processing (receives method name or proc) (the result value type is also validate);
|
109
|
+
- `type_system` (optional) - differently chosen type system for the current attribute;
|
110
|
+
- `as` (optional)- attribute alias (be careful with naming aliases that overlap the names of other attributes);
|
111
|
+
- `mutable` (optional) - generate type-validated attr_writer in addition to attr_reader (`false` by default)
|
112
|
+
- (**limitation**) param has no `:default` option;
|
113
|
+
|
114
|
+
#### option
|
115
|
+
|
116
|
+
- `option` - defines kwarg-like attribute:
|
117
|
+
- `cast` (optional) - type-cast received value if value has invalid type;
|
118
|
+
- `privacy` (optional) - reader incapsulation level;
|
119
|
+
- `as` (optional) - attribute alias (be careful with naming aliases that overlap the names of other attributes);
|
120
|
+
- `mutable` (optional) - generate type-validated attr_writer in addition to attr_reader (`false` by default)
|
121
|
+
- `optional` (optional) - mark attribut as optional (you can may not initialize optional attributes,
|
122
|
+
their values will be initialized with `nil` or by `default:` parameter);
|
123
|
+
- `finalize` (optional) - value post-processing (receives method name or proc) (the result value type is also validate);
|
124
|
+
- expects `Proc` object or `symbol`/`string` isntance method;
|
125
|
+
- `default` (optional) - defalut value (if an attribute is not provided);
|
126
|
+
- expects `Proc` object or a simple value of any type;
|
127
|
+
- non-proc values will be `dup`licate during initialization;
|
128
|
+
- `type_system` (optional) - differently chosen type system for the current attribute;
|
129
|
+
|
130
|
+
#### params
|
131
|
+
|
132
|
+
- `params` - defines a series of parameters;
|
133
|
+
- `:mutable` (optional) - (`false` by default);
|
134
|
+
- `:privacy` (optional) - (`:public` by default);
|
135
|
+
|
136
|
+
#### options
|
137
|
+
|
138
|
+
- `options` - defines a series of options;
|
139
|
+
- `:mutable` (optional) - (`false` by default);
|
140
|
+
- `:privacy` (optional) - (`:public` by default);
|
141
|
+
|
142
|
+
|
143
|
+
#### `param` and `params` signautre:
|
85
144
|
|
86
145
|
```ruby
|
87
146
|
param <attribute_name>,
|
@@ -89,10 +148,19 @@ param <attribute_name>,
|
|
89
148
|
cast: false, # false by default
|
90
149
|
privacy: :public, # :public by default
|
91
150
|
finalize: proc { |value| value }, # no finalization by default
|
151
|
+
finalize: :some_method, # use this apporiach in order to finalize by `some_method(value)` instance method
|
152
|
+
as: :some_alias, # define attribute alias
|
153
|
+
mutable: true, # (false by default) generate type-validated attr_writer in addition to attr_reader
|
92
154
|
type_system: :smart_types # used by default
|
93
155
|
```
|
94
156
|
|
95
|
-
|
157
|
+
```ruby
|
158
|
+
params <atribute_name1>, <attribute_name2>, <attribute_name3>, ...,
|
159
|
+
mutable: true, # generate type-validated attr_writer in addition to attr_reader (false by default);
|
160
|
+
privacy: :private # incapsulate all attributes as private
|
161
|
+
```
|
162
|
+
|
163
|
+
#### `option` and `options` signature:
|
96
164
|
|
97
165
|
```ruby
|
98
166
|
option <attribute_name>,
|
@@ -100,11 +168,58 @@ option <attribute_name>,
|
|
100
168
|
cast: false, # false by default
|
101
169
|
privacy: :public, # :public by default
|
102
170
|
finalize: proc { |value| value }, # no finalization by default
|
171
|
+
finalize: :some_method, # use this apporiach in order to finalize by `some_method(value)` instance method
|
103
172
|
default: 123, # no default value by default
|
173
|
+
default: proc { 123 }, # use proc/lambda object for dynamic initialization
|
174
|
+
as: :some_alias, # define attribute alias
|
175
|
+
mutable: true, # (false by default) generate type-validated attr_writer in addition to attr_reader
|
176
|
+
optional: true # (false by default) mark attribute as optional (attribute will be defined with `nil` or by `default:` value)
|
104
177
|
type_system: :smart_types # used by default
|
105
178
|
```
|
106
179
|
|
107
|
-
|
180
|
+
```ruby
|
181
|
+
options <attribute_name1>, <attribute_name2>, <attribute_name3>, ...,
|
182
|
+
mutable: true, # generate type-validated attr_writer in addition to attr_reader (false by default);
|
183
|
+
privacy: :private # incapsulate all attributes as private
|
184
|
+
```
|
185
|
+
|
186
|
+
---
|
187
|
+
|
188
|
+
## Initializer integration
|
189
|
+
|
190
|
+
- supports per-class configurations;
|
191
|
+
- possible configurations:
|
192
|
+
- `:type_system` - chosen type-system (`smart_types` by default);
|
193
|
+
- `:strict_options` - fail extra kwarg-attributes, passed to the constructor (`true` by default);
|
194
|
+
- `:auto_cast` - type-cast all values to the declared attribute type (`false` by default);
|
195
|
+
|
196
|
+
```ruby
|
197
|
+
# with pre-configured type system (:smart_types, see Configuration doc)
|
198
|
+
|
199
|
+
class MyStructure
|
200
|
+
include SmartCore::Initializer
|
201
|
+
end
|
202
|
+
```
|
203
|
+
|
204
|
+
```ruby
|
205
|
+
# with manually chosen settings
|
206
|
+
|
207
|
+
class MyStructure
|
208
|
+
include SmartCore::Initializer(
|
209
|
+
type_system: :smart_types, # use smart_types
|
210
|
+
auto_cast: true, # type-cast all values by default
|
211
|
+
strict_options: false # ignore extra kwargs passed to the constructor
|
212
|
+
)
|
213
|
+
end
|
214
|
+
|
215
|
+
class AnotherStructure
|
216
|
+
include SmartCore::Initializer(type_system: :thy_types) # use thy_types and global defaults
|
217
|
+
end
|
218
|
+
```
|
219
|
+
|
220
|
+
---
|
221
|
+
|
222
|
+
### Basic Example:
|
108
223
|
|
109
224
|
|
110
225
|
```ruby
|
@@ -114,13 +229,34 @@ class User
|
|
114
229
|
include SmartCore::Initializer(type_system: :smart_types)
|
115
230
|
|
116
231
|
param :user_id, SmartCore::Types::Value::Integer, cast: false, privacy: :public
|
232
|
+
param :login, :string, mutable: true
|
233
|
+
|
117
234
|
option :role, default: :user, finalize: -> { |value| Role.find(name: value) }
|
118
235
|
|
236
|
+
# NOTE: for method-based finalizetion use `your_method(value)` isntance method of your class;
|
237
|
+
# NOTE: for dynamic default values use `proc` objects and `lambda` objects;
|
238
|
+
|
119
239
|
params :name, :password
|
120
240
|
options :metadata, :enabled
|
121
241
|
end
|
122
242
|
|
123
|
-
|
243
|
+
# with correct types (incorrect types will raise SmartCore::Initializer::IncorrectTypeError)
|
244
|
+
object = User.new(1, 'kek123', 'John', 'test123', role: :admin, metadata: {}, enabled: false)
|
245
|
+
|
246
|
+
# attribute accessing:
|
247
|
+
object.user_id # => 1
|
248
|
+
object.login # => 'kek123'
|
249
|
+
object.name # => 'John'
|
250
|
+
object.password # => 'test123'
|
251
|
+
object.role # => :admin
|
252
|
+
object.metadata # => {}
|
253
|
+
object.enabled # => false
|
254
|
+
|
255
|
+
# attribute mutation (only mutable attributes have a mutator):
|
256
|
+
object.login = 123 # => (type vlaidation error) raises SmartCore::Initializer::IncorrectTypeError (expected String, got Integer)
|
257
|
+
object.login # => 'kek123'
|
258
|
+
object.login = 'pek456'
|
259
|
+
object.login # => 'pek456'
|
124
260
|
```
|
125
261
|
|
126
262
|
---
|
@@ -152,25 +288,65 @@ user.__attributes__ # => { first_name: 'Rustam', second_name: 'Ibragimov', age:
|
|
152
288
|
|
153
289
|
## Configuration
|
154
290
|
|
155
|
-
-
|
291
|
+
- **configuration setitngs**:
|
292
|
+
- `:default_type_system` - default type system (`smart_types` by default);
|
293
|
+
- `:strict_options` - fail on extra kwarg-attributes passed to the constructor (`true` by default);
|
294
|
+
- `:auto_cast` - type-cast all values to the declared attribute type (`false` by default);
|
295
|
+
- by default, all classes uses and inherits the Global configuration;
|
156
296
|
- you can read config values via `[]` or `.config.settings` or `.config[key]`;
|
157
|
-
-
|
158
|
-
|
297
|
+
- each class can be configured separately (in `include` invocation);
|
298
|
+
- global configuration affects classes used the default global configs in run-time;
|
299
|
+
- each class can be re-configured separately in run-time;
|
300
|
+
- based on `Qonfig` gem;
|
159
301
|
|
160
302
|
```ruby
|
161
|
-
#
|
303
|
+
# Global configuration:
|
304
|
+
|
162
305
|
SmartCore::Initializer::Configuration.configure do |config|
|
163
306
|
config.default_type_system = :smart_types # default setting value
|
307
|
+
config.strict_options = true # default setting value
|
308
|
+
config.auto_cast = false # default setting value
|
164
309
|
end
|
165
310
|
```
|
166
311
|
|
167
312
|
```ruby
|
168
|
-
#
|
313
|
+
# Read configs:
|
314
|
+
|
169
315
|
SmartCore::Initializer::Configuration[:default_type_system]
|
170
316
|
SmartCore::Initializer::Configuration.config[:default_type_system]
|
171
317
|
SmartCore::Initializer::Configuration.config.settings.default_type_system
|
172
318
|
```
|
173
319
|
|
320
|
+
```ruby
|
321
|
+
# per-class configuration:
|
322
|
+
|
323
|
+
class Parameters
|
324
|
+
include SmartCore::Initializer(auto_cast: true, strict_options: false)
|
325
|
+
# 1. use globally configured `smart_types` (default value)
|
326
|
+
# 2. type-cast all attributes by default (auto_cast: true)
|
327
|
+
# 3. ignore extra kwarg-attributes passed to the constructor (strict_options: false)
|
328
|
+
end
|
329
|
+
|
330
|
+
class User
|
331
|
+
include SmartCore::Initializer(type_system: :thy_types)
|
332
|
+
# 1. use :thy_types isntead of pre-configured :smart_types
|
333
|
+
# 2. use pre-configured auto_cast (false by default above)
|
334
|
+
# 3. use pre-configured strict_options ()
|
335
|
+
end
|
336
|
+
```
|
337
|
+
|
338
|
+
```ruby
|
339
|
+
# debug class-related configurations:
|
340
|
+
|
341
|
+
class SomeClass
|
342
|
+
include SmartCore::Initializer(type_system: :thy_types)
|
343
|
+
end
|
344
|
+
|
345
|
+
SomeClass.__initializer_settings__[:type_system] # => :thy_types
|
346
|
+
SomeClass.__initializer_settings__[:auto_cast] # => false
|
347
|
+
SomeClass.__initializer_settings__[:strict_options] # => true
|
348
|
+
```
|
349
|
+
|
174
350
|
---
|
175
351
|
|
176
352
|
## Type aliasing
|
@@ -206,6 +382,63 @@ SmartCore::Initializer::TypeSystem::ThyTypes.type_aliases
|
|
206
382
|
|
207
383
|
---
|
208
384
|
|
385
|
+
## Type-casting
|
386
|
+
|
387
|
+
- make param/option as type-castable:
|
388
|
+
|
389
|
+
```ruby
|
390
|
+
class Order
|
391
|
+
include SmartCore::Initializer
|
392
|
+
|
393
|
+
param :manager, 'string' # cast: false is used by default
|
394
|
+
param :amount, 'float', cast: true
|
395
|
+
|
396
|
+
option :status, :symbol # cast: false is used by default
|
397
|
+
option :is_processed, 'boolean', cast: true
|
398
|
+
option :processed_at, 'time', cast: true
|
399
|
+
end
|
400
|
+
|
401
|
+
order = Order.new(
|
402
|
+
'Daiver',
|
403
|
+
'123.456',
|
404
|
+
status: :pending,
|
405
|
+
is_processed: nil,
|
406
|
+
processed_at: '2021-01-01'
|
407
|
+
)
|
408
|
+
|
409
|
+
order.manager # => 'Daiver'
|
410
|
+
order.amount # => 123.456 (type casted)
|
411
|
+
order.status # => :pending
|
412
|
+
order.is_processed # => false (type casted)
|
413
|
+
order.processed_at # => 2021-01-01 00:00:00 +0300 (type casted)
|
414
|
+
```
|
415
|
+
|
416
|
+
- configure automatic type casting:
|
417
|
+
|
418
|
+
```ruby
|
419
|
+
# per class
|
420
|
+
|
421
|
+
class User
|
422
|
+
include SmartCore::Initializer(auto_cast: true) # auto type cast every attribute
|
423
|
+
|
424
|
+
param :x, 'string'
|
425
|
+
param :y, 'numeric', cast: false # disable type-casting
|
426
|
+
|
427
|
+
option :b, 'integer', cast: false # disable type-casting
|
428
|
+
option :c, 'boolean'
|
429
|
+
end
|
430
|
+
```
|
431
|
+
|
432
|
+
```ruby
|
433
|
+
# globally
|
434
|
+
|
435
|
+
SmartCore::Initializer::Configuration.configure do |config|
|
436
|
+
config.auto_cast = true # false by default
|
437
|
+
end
|
438
|
+
```
|
439
|
+
|
440
|
+
---
|
441
|
+
|
209
442
|
## Initialization extension
|
210
443
|
|
211
444
|
- `ext_init(&block)`:
|
@@ -289,10 +522,14 @@ User.new(123, 'test', { admin: true, age: 22 })
|
|
289
522
|
|
290
523
|
## Roadmap
|
291
524
|
|
292
|
-
- (
|
293
|
-
-
|
294
|
-
-
|
525
|
+
- More semantic attribute declaration errors (more domain-related attribute error objects);
|
526
|
+
- incorrect `:finalize` argument type: `ArgumentError` => `FinalizeArgumentError`;
|
527
|
+
- incorrect `:as` argument type: `ArguemntError` => `AsArgumentError`;
|
528
|
+
- etc;
|
529
|
+
- Support for `RSpec` doubles and instance_doubles inside the type system integration;
|
530
|
+
- Specs restructuring;
|
295
531
|
- Migrate from `TravisCI` to `GitHub Actions`;
|
532
|
+
- Extract `Type Interop` system to `smart_type-system`;
|
296
533
|
|
297
534
|
---
|
298
535
|
|
@@ -346,6 +583,12 @@ bundle exec rake rubocop -A
|
|
346
583
|
|
347
584
|
Released under MIT License.
|
348
585
|
|
586
|
+
## Supporting
|
587
|
+
|
588
|
+
<a target="_blank" href="https://github.com/Cado-Labs">
|
589
|
+
<img src="https://github.com/Cado-Labs/cado-labs-logos/raw/main/cado_labs_badge.svg" alt="Supported by Cado Labs" style="max-width: 100%;">
|
590
|
+
</a>
|
591
|
+
|
349
592
|
## Authors
|
350
593
|
|
351
594
|
[Rustam Ibragimov](https://github.com/0exp)
|