smart_initializer 0.7.0 → 0.9.1
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 -3
- data/Gemfile.lock +40 -39
- data/README.md +286 -41
- data/bin/console +2 -2
- data/gemfiles/with_external_deps.gemfile.lock +40 -39
- data/gemfiles/without_external_deps.gemfile.lock +39 -40
- data/lib/smart_core/initializer/attribute/factory/base.rb +154 -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 -125
- data/lib/smart_core/initializer/configuration.rb +7 -3
- data/lib/smart_core/initializer/constructor/definer.rb +135 -46
- data/lib/smart_core/initializer/constructor.rb +28 -14
- data/lib/smart_core/initializer/dsl.rb +38 -24
- data/lib/smart_core/initializer/errors.rb +20 -4
- data/lib/smart_core/initializer/functionality.rb +7 -8
- 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/registry.rb +2 -1
- 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 +2 -2
- metadata +16 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '0298953ea16ae53d51961bc46a26eefcba667f4a7d07d9d09e7d59b33f68760e'
|
4
|
+
data.tar.gz: 1cdd0cde6871dcccc17641ad2870d71da26e4385f8e2df93affb96577d67f6b4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4c3cf5f55e9d79003a48d655eac65470029d2b7b2565e19dee0114168585c32a4b101405635492d5431e8e8041b2d09f7a805574ea356561d12470d321878a9a
|
7
|
+
data.tar.gz: 558a0037b339802ee10a9a4a60b2841cc8f6256bfa3d8576e65351d531c393cbd9542e988a5c49ecb7d30e3cae27a7b57b6f1dbb643cd56771fa3cdbb6e17315
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,16 +1,59 @@
|
|
1
1
|
# Changelog
|
2
2
|
All notable changes to this project will be documented in this file.
|
3
3
|
|
4
|
+
## [0.9.1] - 2022-03-06
|
5
|
+
|
6
|
+
### Fixed
|
7
|
+
|
8
|
+
- `finalize` now accepts lambdas with arity `-2`. For example `->(a, *b) {}` or `:freeze.to_proc`
|
9
|
+
which in `Ruby >= 3` returns lambda with arity equal to `-2`.
|
10
|
+
|
11
|
+
## [0.9.0] - 2021-12-19
|
12
|
+
### Changed
|
13
|
+
- `:finalize` block is not invoked on the `option` with `optional: true` flag;
|
14
|
+
|
15
|
+
## [0.8.0] - 2021-12-04
|
16
|
+
### Added
|
17
|
+
- New options for option and param attributes:
|
18
|
+
- Support for attribute **aliasing** (`:as` parameter);
|
19
|
+
- supports: `option`, `param`;
|
20
|
+
- Support for attribute **auto-casting** (`:auto_cast` parameter);
|
21
|
+
- supports: `option`, `param`;
|
22
|
+
- Support for **mutable** attributes (`:mutable` parameter) with type-validation inside;
|
23
|
+
- supports: `option`, `options`, `param`, `params`;
|
24
|
+
- Support for **optional** attributes (`:optional` parameter);
|
25
|
+
- supports: `option`;
|
26
|
+
- **SmartCore::Initializer::Configuration**:
|
27
|
+
- Configuration setting `strict_options` now works separately "per-class" in all configs manner
|
28
|
+
(each class shares the global state but has own state too)
|
29
|
+
- Support for per-class/global `:auto_cast` configuration;
|
30
|
+
- provides a global/per-class behavior for `:cast` option (`false` by default);
|
31
|
+
- `options` declaration now supports `privacy` option;
|
32
|
+
- `params` declaration now supports `privacy` option;
|
33
|
+
|
34
|
+
### Changed
|
35
|
+
- Drop support of **Ruby@2.4**;
|
36
|
+
- `:default` attribute parameter now duplicates the passed value during object instantiation;
|
37
|
+
- `:default` attribute parameter only works with `option` attribute (`param` can't have `default` parameter now);
|
38
|
+
- Attribute values generated by `:finalize` are type-validated now too;
|
39
|
+
- Now lambda-based `:finalize` attributes are being checked for the signature during attribute declaration;
|
40
|
+
- Some error messages have become more readable;
|
41
|
+
|
42
|
+
## Fixed
|
43
|
+
- `send` method overlaping/rewriting: otions and params named as `send` breaks the internal
|
44
|
+
framework-related invocations of the attribute definitioning inside the custom object constructor
|
45
|
+
(this name rewrites internal Ruby's `send` method and brokes some things);
|
46
|
+
|
4
47
|
## [0.7.0] - 2021-06-23
|
5
|
-
|
48
|
+
### Added
|
6
49
|
- `strict_options` config option for non-strict checking of passed options;
|
7
50
|
|
8
51
|
## [0.6.0] - 2021-06-23
|
9
|
-
|
52
|
+
### Added
|
10
53
|
- Validation messages for incorrect attribute types;
|
11
54
|
|
12
55
|
## [0.5.0] - 2021-01-18
|
13
|
-
|
56
|
+
### Changed
|
14
57
|
- Updated `smart_types` dependency (`~> 0.4.0`) to guarantee **Ruby@3** compatibility;
|
15
58
|
- Updated development dependencies;
|
16
59
|
|
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.1)
|
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.
|
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.
|
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
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.14.
|
36
|
+
pry (0.14.1)
|
37
37
|
coderay (~> 1.1)
|
38
38
|
method_source (~> 1.0)
|
39
|
-
qonfig (0.
|
39
|
+
qonfig (0.27.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)
|
@@ -54,51 +54,52 @@ GEM
|
|
54
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
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
66
|
unicode-display_width (>= 1.4.0, < 3.0)
|
67
|
-
rubocop-ast (1.
|
68
|
-
parser (>=
|
69
|
-
rubocop-performance (1.
|
70
|
-
rubocop (>=
|
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 (2.
|
94
|
-
zeitwerk (2.
|
92
|
+
unicode-display_width (2.1.0)
|
93
|
+
zeitwerk (2.5.1)
|
95
94
|
|
96
95
|
PLATFORMS
|
97
96
|
x86_64-darwin-19
|
98
97
|
x86_64-darwin-20
|
98
|
+
x86_64-darwin-21
|
99
|
+
x86_64-linux
|
99
100
|
|
100
101
|
DEPENDENCIES
|
101
|
-
armitage-rubocop (~> 1.
|
102
|
+
armitage-rubocop (~> 1.23)
|
102
103
|
bundler (~> 2.2)
|
103
104
|
pry (~> 0.14)
|
104
105
|
rake (~> 13.0)
|
@@ -107,4 +108,4 @@ DEPENDENCIES
|
|
107
108
|
smart_initializer!
|
108
109
|
|
109
110
|
BUNDLED WITH
|
110
|
-
2.2.
|
111
|
+
2.2.32
|
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,97 @@ 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
|
-
|
57
|
-
|
58
|
-
|
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
|
+
- if `default`-object is a proc-object - this proc-object will be invoked in the `outer scope` of block definition;
|
75
|
+
- if `finalize`-object is a proc-object - this proc-object will be invoked in the `isntance` context (class instance);
|
76
|
+
|
77
|
+
**NOTE**: `:finalize` block are not invoked on omitted `optional: true` attributes
|
78
|
+
which has no `:default` definition bock and which are not passed to the constructor. Example:
|
63
79
|
|
64
80
|
```ruby
|
65
|
-
#
|
81
|
+
# without :default
|
66
82
|
|
67
|
-
class
|
83
|
+
class User
|
68
84
|
include SmartCore::Initializer
|
85
|
+
option :age, :string, optional: true, finalize: -> (val) { "#{val}_years" }
|
69
86
|
end
|
87
|
+
|
88
|
+
User.new.age # => nil
|
70
89
|
```
|
71
90
|
|
72
91
|
```ruby
|
73
|
-
# with
|
92
|
+
# with :default
|
74
93
|
|
75
|
-
class
|
76
|
-
include SmartCore::Initializer
|
94
|
+
class User
|
95
|
+
include SmartCore::Initializer
|
96
|
+
option :age, :string, optional: true, default: '0', finalize: -> (val) { "#{val}_years" }
|
77
97
|
end
|
78
98
|
|
79
|
-
|
80
|
-
include SmartCore::Initializer(type_system: :thy_types)
|
81
|
-
end
|
99
|
+
User.new.age # => '0_years'
|
82
100
|
```
|
83
101
|
|
84
|
-
|
102
|
+
---
|
103
|
+
|
104
|
+
### Constructor definition DSL
|
105
|
+
|
106
|
+
**NOTE**: last `Hash` argument will be treated as `kwarg`s;
|
107
|
+
|
108
|
+
#### param
|
109
|
+
|
110
|
+
- `param` - defines name-like attribute:
|
111
|
+
- `cast` (optional) - type-cast received value if value has invalid type;
|
112
|
+
- `privacy` (optional) - reader incapsulation level;
|
113
|
+
- `finalize` (optional) - value post-processing (receives method name or proc) (the result value type is also validate);
|
114
|
+
- `type_system` (optional) - differently chosen type system for the current attribute;
|
115
|
+
- `as` (optional)- attribute alias (be careful with naming aliases that overlap the names of other attributes);
|
116
|
+
- `mutable` (optional) - generate type-validated attr_writer in addition to attr_reader (`false` by default)
|
117
|
+
- (**limitation**) param has no `:default` option;
|
118
|
+
|
119
|
+
#### option
|
120
|
+
|
121
|
+
- `option` - defines kwarg-like attribute:
|
122
|
+
- `cast` (optional) - type-cast received value if value has invalid type;
|
123
|
+
- `privacy` (optional) - reader incapsulation level;
|
124
|
+
- `as` (optional) - attribute alias (be careful with naming aliases that overlap the names of other attributes);
|
125
|
+
- `mutable` (optional) - generate type-validated attr_writer in addition to attr_reader (`false` by default)
|
126
|
+
- `optional` (optional) - mark attribut as optional (you can may not initialize optional attributes,
|
127
|
+
their values will be initialized with `nil` or by `default:` parameter);
|
128
|
+
- `finalize` (optional) - value post-processing (receives method name or proc) (the result value type is also validate);
|
129
|
+
- expects `Proc` object or `symbol`/`string` isntance method;
|
130
|
+
- `default` (optional) - defalut value (if an attribute is not provided);
|
131
|
+
- expects `Proc` object or a simple value of any type;
|
132
|
+
- non-proc values will be `dup`licate during initialization;
|
133
|
+
- `type_system` (optional) - differently chosen type system for the current attribute;
|
134
|
+
|
135
|
+
#### params
|
136
|
+
|
137
|
+
- `params` - defines a series of parameters;
|
138
|
+
- `:mutable` (optional) - (`false` by default);
|
139
|
+
- `:privacy` (optional) - (`:public` by default);
|
140
|
+
|
141
|
+
#### options
|
142
|
+
|
143
|
+
- `options` - defines a series of options;
|
144
|
+
- `:mutable` (optional) - (`false` by default);
|
145
|
+
- `:privacy` (optional) - (`:public` by default);
|
146
|
+
|
147
|
+
|
148
|
+
#### `param` and `params` signautre:
|
85
149
|
|
86
150
|
```ruby
|
87
151
|
param <attribute_name>,
|
@@ -89,10 +153,19 @@ param <attribute_name>,
|
|
89
153
|
cast: false, # false by default
|
90
154
|
privacy: :public, # :public by default
|
91
155
|
finalize: proc { |value| value }, # no finalization by default
|
156
|
+
finalize: :some_method, # use this apporiach in order to finalize by `some_method(value)` instance method
|
157
|
+
as: :some_alias, # define attribute alias
|
158
|
+
mutable: true, # (false by default) generate type-validated attr_writer in addition to attr_reader
|
92
159
|
type_system: :smart_types # used by default
|
93
160
|
```
|
94
161
|
|
95
|
-
|
162
|
+
```ruby
|
163
|
+
params <atribute_name1>, <attribute_name2>, <attribute_name3>, ...,
|
164
|
+
mutable: true, # generate type-validated attr_writer in addition to attr_reader (false by default);
|
165
|
+
privacy: :private # incapsulate all attributes as private
|
166
|
+
```
|
167
|
+
|
168
|
+
#### `option` and `options` signature:
|
96
169
|
|
97
170
|
```ruby
|
98
171
|
option <attribute_name>,
|
@@ -100,11 +173,58 @@ option <attribute_name>,
|
|
100
173
|
cast: false, # false by default
|
101
174
|
privacy: :public, # :public by default
|
102
175
|
finalize: proc { |value| value }, # no finalization by default
|
176
|
+
finalize: :some_method, # use this apporiach in order to finalize by `some_method(value)` instance method
|
103
177
|
default: 123, # no default value by default
|
178
|
+
default: proc { 123 }, # use proc/lambda object for dynamic initialization
|
179
|
+
as: :some_alias, # define attribute alias
|
180
|
+
mutable: true, # (false by default) generate type-validated attr_writer in addition to attr_reader
|
181
|
+
optional: true # (false by default) mark attribute as optional (attribute will be defined with `nil` or by `default:` value)
|
104
182
|
type_system: :smart_types # used by default
|
105
183
|
```
|
106
184
|
|
107
|
-
|
185
|
+
```ruby
|
186
|
+
options <attribute_name1>, <attribute_name2>, <attribute_name3>, ...,
|
187
|
+
mutable: true, # generate type-validated attr_writer in addition to attr_reader (false by default);
|
188
|
+
privacy: :private # incapsulate all attributes as private
|
189
|
+
```
|
190
|
+
|
191
|
+
---
|
192
|
+
|
193
|
+
## Initializer integration
|
194
|
+
|
195
|
+
- supports per-class configurations;
|
196
|
+
- possible configurations:
|
197
|
+
- `:type_system` - chosen type-system (`smart_types` by default);
|
198
|
+
- `:strict_options` - fail extra kwarg-attributes, passed to the constructor (`true` by default);
|
199
|
+
- `:auto_cast` - type-cast all values to the declared attribute type (`false` by default);
|
200
|
+
|
201
|
+
```ruby
|
202
|
+
# with pre-configured type system (:smart_types, see Configuration doc)
|
203
|
+
|
204
|
+
class MyStructure
|
205
|
+
include SmartCore::Initializer
|
206
|
+
end
|
207
|
+
```
|
208
|
+
|
209
|
+
```ruby
|
210
|
+
# with manually chosen settings
|
211
|
+
|
212
|
+
class MyStructure
|
213
|
+
include SmartCore::Initializer(
|
214
|
+
type_system: :smart_types, # use smart_types
|
215
|
+
auto_cast: true, # type-cast all values by default
|
216
|
+
strict_options: false # ignore extra kwargs passed to the constructor
|
217
|
+
)
|
218
|
+
end
|
219
|
+
|
220
|
+
class AnotherStructure
|
221
|
+
include SmartCore::Initializer(type_system: :thy_types) # use thy_types and global defaults
|
222
|
+
end
|
223
|
+
```
|
224
|
+
|
225
|
+
---
|
226
|
+
|
227
|
+
### Basic Example:
|
108
228
|
|
109
229
|
|
110
230
|
```ruby
|
@@ -114,13 +234,34 @@ class User
|
|
114
234
|
include SmartCore::Initializer(type_system: :smart_types)
|
115
235
|
|
116
236
|
param :user_id, SmartCore::Types::Value::Integer, cast: false, privacy: :public
|
237
|
+
param :login, :string, mutable: true
|
238
|
+
|
117
239
|
option :role, default: :user, finalize: -> { |value| Role.find(name: value) }
|
118
240
|
|
241
|
+
# NOTE: for method-based finalizetion use `your_method(value)` isntance method of your class;
|
242
|
+
# NOTE: for dynamic default values use `proc` objects and `lambda` objects;
|
243
|
+
|
119
244
|
params :name, :password
|
120
245
|
options :metadata, :enabled
|
121
246
|
end
|
122
247
|
|
123
|
-
|
248
|
+
# with correct types (incorrect types will raise SmartCore::Initializer::IncorrectTypeError)
|
249
|
+
object = User.new(1, 'kek123', 'John', 'test123', role: :admin, metadata: {}, enabled: false)
|
250
|
+
|
251
|
+
# attribute accessing:
|
252
|
+
object.user_id # => 1
|
253
|
+
object.login # => 'kek123'
|
254
|
+
object.name # => 'John'
|
255
|
+
object.password # => 'test123'
|
256
|
+
object.role # => :admin
|
257
|
+
object.metadata # => {}
|
258
|
+
object.enabled # => false
|
259
|
+
|
260
|
+
# attribute mutation (only mutable attributes have a mutator):
|
261
|
+
object.login = 123 # => (type vlaidation error) raises SmartCore::Initializer::IncorrectTypeError (expected String, got Integer)
|
262
|
+
object.login # => 'kek123'
|
263
|
+
object.login = 'pek456'
|
264
|
+
object.login # => 'pek456'
|
124
265
|
```
|
125
266
|
|
126
267
|
---
|
@@ -152,27 +293,65 @@ user.__attributes__ # => { first_name: 'Rustam', second_name: 'Ibragimov', age:
|
|
152
293
|
|
153
294
|
## Configuration
|
154
295
|
|
155
|
-
-
|
296
|
+
- **configuration setitngs**:
|
297
|
+
- `:default_type_system` - default type system (`smart_types` by default);
|
298
|
+
- `:strict_options` - fail on extra kwarg-attributes passed to the constructor (`true` by default);
|
299
|
+
- `:auto_cast` - type-cast all values to the declared attribute type (`false` by default);
|
300
|
+
- by default, all classes uses and inherits the Global configuration;
|
156
301
|
- you can read config values via `[]` or `.config.settings` or `.config[key]`;
|
157
|
-
-
|
158
|
-
|
159
|
-
|
302
|
+
- each class can be configured separately (in `include` invocation);
|
303
|
+
- global configuration affects classes used the default global configs in run-time;
|
304
|
+
- each class can be re-configured separately in run-time;
|
305
|
+
- based on `Qonfig` gem;
|
160
306
|
|
161
307
|
```ruby
|
162
|
-
#
|
308
|
+
# Global configuration:
|
309
|
+
|
163
310
|
SmartCore::Initializer::Configuration.configure do |config|
|
164
311
|
config.default_type_system = :smart_types # default setting value
|
165
312
|
config.strict_options = true # default setting value
|
313
|
+
config.auto_cast = false # default setting value
|
166
314
|
end
|
167
315
|
```
|
168
316
|
|
169
317
|
```ruby
|
170
|
-
#
|
318
|
+
# Read configs:
|
319
|
+
|
171
320
|
SmartCore::Initializer::Configuration[:default_type_system]
|
172
321
|
SmartCore::Initializer::Configuration.config[:default_type_system]
|
173
322
|
SmartCore::Initializer::Configuration.config.settings.default_type_system
|
174
323
|
```
|
175
324
|
|
325
|
+
```ruby
|
326
|
+
# per-class configuration:
|
327
|
+
|
328
|
+
class Parameters
|
329
|
+
include SmartCore::Initializer(auto_cast: true, strict_options: false)
|
330
|
+
# 1. use globally configured `smart_types` (default value)
|
331
|
+
# 2. type-cast all attributes by default (auto_cast: true)
|
332
|
+
# 3. ignore extra kwarg-attributes passed to the constructor (strict_options: false)
|
333
|
+
end
|
334
|
+
|
335
|
+
class User
|
336
|
+
include SmartCore::Initializer(type_system: :thy_types)
|
337
|
+
# 1. use :thy_types isntead of pre-configured :smart_types
|
338
|
+
# 2. use pre-configured auto_cast (false by default above)
|
339
|
+
# 3. use pre-configured strict_options ()
|
340
|
+
end
|
341
|
+
```
|
342
|
+
|
343
|
+
```ruby
|
344
|
+
# debug class-related configurations:
|
345
|
+
|
346
|
+
class SomeClass
|
347
|
+
include SmartCore::Initializer(type_system: :thy_types)
|
348
|
+
end
|
349
|
+
|
350
|
+
SomeClass.__initializer_settings__[:type_system] # => :thy_types
|
351
|
+
SomeClass.__initializer_settings__[:auto_cast] # => false
|
352
|
+
SomeClass.__initializer_settings__[:strict_options] # => true
|
353
|
+
```
|
354
|
+
|
176
355
|
---
|
177
356
|
|
178
357
|
## Type aliasing
|
@@ -208,6 +387,63 @@ SmartCore::Initializer::TypeSystem::ThyTypes.type_aliases
|
|
208
387
|
|
209
388
|
---
|
210
389
|
|
390
|
+
## Type-casting
|
391
|
+
|
392
|
+
- make param/option as type-castable:
|
393
|
+
|
394
|
+
```ruby
|
395
|
+
class Order
|
396
|
+
include SmartCore::Initializer
|
397
|
+
|
398
|
+
param :manager, 'string' # cast: false is used by default
|
399
|
+
param :amount, 'float', cast: true
|
400
|
+
|
401
|
+
option :status, :symbol # cast: false is used by default
|
402
|
+
option :is_processed, 'boolean', cast: true
|
403
|
+
option :processed_at, 'time', cast: true
|
404
|
+
end
|
405
|
+
|
406
|
+
order = Order.new(
|
407
|
+
'Daiver',
|
408
|
+
'123.456',
|
409
|
+
status: :pending,
|
410
|
+
is_processed: nil,
|
411
|
+
processed_at: '2021-01-01'
|
412
|
+
)
|
413
|
+
|
414
|
+
order.manager # => 'Daiver'
|
415
|
+
order.amount # => 123.456 (type casted)
|
416
|
+
order.status # => :pending
|
417
|
+
order.is_processed # => false (type casted)
|
418
|
+
order.processed_at # => 2021-01-01 00:00:00 +0300 (type casted)
|
419
|
+
```
|
420
|
+
|
421
|
+
- configure automatic type casting:
|
422
|
+
|
423
|
+
```ruby
|
424
|
+
# per class
|
425
|
+
|
426
|
+
class User
|
427
|
+
include SmartCore::Initializer(auto_cast: true) # auto type cast every attribute
|
428
|
+
|
429
|
+
param :x, 'string'
|
430
|
+
param :y, 'numeric', cast: false # disable type-casting
|
431
|
+
|
432
|
+
option :b, 'integer', cast: false # disable type-casting
|
433
|
+
option :c, 'boolean'
|
434
|
+
end
|
435
|
+
```
|
436
|
+
|
437
|
+
```ruby
|
438
|
+
# globally
|
439
|
+
|
440
|
+
SmartCore::Initializer::Configuration.configure do |config|
|
441
|
+
config.auto_cast = true # false by default
|
442
|
+
end
|
443
|
+
```
|
444
|
+
|
445
|
+
---
|
446
|
+
|
211
447
|
## Initialization extension
|
212
448
|
|
213
449
|
- `ext_init(&block)`:
|
@@ -291,9 +527,12 @@ User.new(123, 'test', { admin: true, age: 22 })
|
|
291
527
|
|
292
528
|
## Roadmap
|
293
529
|
|
294
|
-
- (
|
295
|
-
-
|
296
|
-
-
|
530
|
+
- More semantic attribute declaration errors (more domain-related attribute error objects);
|
531
|
+
- incorrect `:finalize` argument type: `ArgumentError` => `FinalizeArgumentError`;
|
532
|
+
- incorrect `:as` argument type: `ArguemntError` => `AsArgumentError`;
|
533
|
+
- etc;
|
534
|
+
- Support for `RSpec` doubles and instance_doubles inside the type system integration;
|
535
|
+
- Specs restructuring;
|
297
536
|
- Migrate from `TravisCI` to `GitHub Actions`;
|
298
537
|
- Extract `Type Interop` system to `smart_type-system`;
|
299
538
|
|
@@ -349,6 +588,12 @@ bundle exec rake rubocop -A
|
|
349
588
|
|
350
589
|
Released under MIT License.
|
351
590
|
|
591
|
+
## Supporting
|
592
|
+
|
593
|
+
<a target="_blank" href="https://github.com/Cado-Labs">
|
594
|
+
<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%;">
|
595
|
+
</a>
|
596
|
+
|
352
597
|
## Authors
|
353
598
|
|
354
599
|
[Rustam Ibragimov](https://github.com/0exp)
|