smart_initializer 0.7.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/CHANGELOG.md +46 -3
  4. data/Gemfile.lock +40 -39
  5. data/README.md +286 -41
  6. data/bin/console +2 -2
  7. data/gemfiles/with_external_deps.gemfile.lock +40 -39
  8. data/gemfiles/without_external_deps.gemfile.lock +39 -40
  9. data/lib/smart_core/initializer/attribute/factory/base.rb +154 -0
  10. data/lib/smart_core/initializer/attribute/factory/option.rb +107 -0
  11. data/lib/smart_core/initializer/attribute/factory/param.rb +63 -0
  12. data/lib/smart_core/initializer/attribute/factory.rb +5 -199
  13. data/lib/smart_core/initializer/attribute/finalizer/abstract.rb +2 -0
  14. data/lib/smart_core/initializer/attribute/finalizer/instance_method.rb +1 -1
  15. data/lib/smart_core/initializer/attribute/finalizer.rb +5 -5
  16. data/lib/smart_core/initializer/attribute/list.rb +20 -0
  17. data/lib/smart_core/initializer/attribute/{parameters.rb → value/base.rb} +35 -65
  18. data/lib/smart_core/initializer/attribute/value/option.rb +101 -0
  19. data/lib/smart_core/initializer/attribute/value/param.rb +24 -0
  20. data/lib/smart_core/initializer/attribute/value.rb +9 -0
  21. data/lib/smart_core/initializer/attribute.rb +3 -125
  22. data/lib/smart_core/initializer/configuration.rb +7 -3
  23. data/lib/smart_core/initializer/constructor/definer.rb +135 -46
  24. data/lib/smart_core/initializer/constructor.rb +28 -14
  25. data/lib/smart_core/initializer/dsl.rb +38 -24
  26. data/lib/smart_core/initializer/errors.rb +20 -4
  27. data/lib/smart_core/initializer/functionality.rb +7 -8
  28. data/lib/smart_core/initializer/settings/auto_cast.rb +40 -0
  29. data/lib/smart_core/initializer/settings/base.rb +49 -0
  30. data/lib/smart_core/initializer/settings/duplicator.rb +5 -0
  31. data/lib/smart_core/initializer/settings/strict_options.rb +40 -0
  32. data/lib/smart_core/initializer/settings/type_system.rb +10 -28
  33. data/lib/smart_core/initializer/settings.rb +40 -0
  34. data/lib/smart_core/initializer/type_system/registry.rb +2 -1
  35. data/lib/smart_core/initializer/type_system/smart_types.rb +2 -2
  36. data/lib/smart_core/initializer/version.rb +2 -2
  37. data/lib/smart_core/initializer.rb +14 -4
  38. data/smart_initializer.gemspec +2 -2
  39. metadata +16 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 84aa6ce59c1c73432c01015a595c6a20c2e11344d2d6464aa63920c288f3b51f
4
- data.tar.gz: '0819287ddbd9cfc21fac709a848205230036dd2b724df4568ed90b36bbd0316e'
3
+ metadata.gz: '0298953ea16ae53d51961bc46a26eefcba667f4a7d07d9d09e7d59b33f68760e'
4
+ data.tar.gz: 1cdd0cde6871dcccc17641ad2870d71da26e4385f8e2df93affb96577d67f6b4
5
5
  SHA512:
6
- metadata.gz: e6b1f6664ae3e519b4fe516e565b959987f459d145d0f5de4a7d26e8b9d32ed103567eb11d7d050ef1b3d7ad2fa05e430223060f7638552dfe24edd3d8999644
7
- data.tar.gz: 7ee572ea83d433095f1fd3a27a127543eb22fbbafde515e052e6d1a3360914c828a8dd983f8659501a7fbca08499cec11a34a18e4c43ac9702acd39af5235663
6
+ metadata.gz: 4c3cf5f55e9d79003a48d655eac65470029d2b7b2565e19dee0114168585c32a4b101405635492d5431e8e8041b2d09f7a805574ea356561d12470d321878a9a
7
+ data.tar.gz: 558a0037b339802ee10a9a4a60b2841cc8f6256bfa3d8576e65351d531c393cbd9542e988a5c49ecb7d30e3cae27a7b57b6f1dbb643cd56771fa3cdbb6e17315
data/.rubocop.yml CHANGED
@@ -5,7 +5,7 @@ inherit_gem:
5
5
  - lib/rubocop.rspec.yml
6
6
 
7
7
  AllCops:
8
- TargetRubyVersion: 3.0.0
8
+ TargetRubyVersion: 3.1
9
9
  NewCops: enable
10
10
  Include:
11
11
  - lib/**/*.rb
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
- ## Added
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
- ## Added
52
+ ### Added
10
53
  - Validation messages for incorrect attribute types;
11
54
 
12
55
  ## [0.5.0] - 2021-01-18
13
- ## Changed
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.6.1)
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.2)
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.8.1)
19
- rubocop (= 1.8.1)
20
- rubocop-performance (= 1.9.2)
21
- rubocop-rails (= 2.9.1)
22
- rubocop-rake (= 0.5.1)
23
- rubocop-rspec (= 2.1.0)
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.8)
26
+ concurrent-ruby (1.1.9)
27
27
  diff-lcs (1.4.4)
28
- docile (1.3.5)
29
- i18n (1.8.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.3)
33
- parallel (1.20.1)
34
- parser (3.0.0.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.0)
36
+ pry (0.14.1)
37
37
  coderay (~> 1.1)
38
38
  method_source (~> 1.0)
39
- qonfig (0.25.0)
39
+ qonfig (0.27.0)
40
40
  rack (2.2.3)
41
41
  rainbow (3.0.0)
42
- rake (13.0.3)
43
- regexp_parser (2.0.3)
44
- rexml (3.2.4)
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.2)
58
- rubocop (1.8.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.2.0, < 2.0)
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.4.1)
68
- parser (>= 2.7.1.5)
69
- rubocop-performance (1.9.2)
70
- rubocop (>= 0.90.0, < 2.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.9.1)
72
+ rubocop-rails (2.12.4)
73
73
  activesupport (>= 4.2.0)
74
74
  rack (>= 1.1)
75
- rubocop (>= 0.90.0, < 2.0)
76
- rubocop-rake (0.5.1)
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
- rubocop-ast (>= 1.1.0)
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.2)
88
- smart_engine (0.11.0)
89
- smart_types (0.4.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.0.0)
94
- zeitwerk (2.4.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.7)
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.19
111
+ 2.2.32
data/README.md CHANGED
@@ -1,8 +1,14 @@
1
- # SmartCore::Initializer &middot; [![Gem Version](https://badge.fury.io/rb/smart_initializer.svg)](https://badge.fury.io/rb/smart_initializer)
1
+ # SmartCore::Initializer &middot; <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> &middot; [![Gem Version](https://badge.fury.io/rb/smart_initializer.svg)](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
- **Initialization flow**:
58
+ #### Initialization flow
41
59
 
42
- 1. Parameter + Option definitioning;
43
- 2. Original #initialize invokation;
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
- **Constructor definition**:
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
- - `param` - defines name-like attribute:
49
- - `cast` - type-cast received value if value has invalid type;
50
- - `privacy` - reader incapsulation level;
51
- - `finalize` - value post-processing (receives method name or proc);
52
- - `type_system` - differently chosen type system for the current attribute;
53
- - (limitation) param has no `:default` option;
54
- - `option` - defined kwarg-like attribute:
55
- - `cast` - type-cast received value if value has invalid type;
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
+ - 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
- # with pre-configured type system (:smart_types, see Configuration doc)
81
+ # without :default
66
82
 
67
- class MyStructure
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 manually chosen type system
92
+ # with :default
74
93
 
75
- class MyStructure
76
- include SmartCore::Initializer(type_system: :smart_types)
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
- class AnotherStructure
80
- include SmartCore::Initializer(type_system: :thy_types)
81
- end
99
+ User.new.age # => '0_years'
82
100
  ```
83
101
 
84
- #### `param` signautre:
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
- #### `option` signature:
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
- Example:
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
- User.new(1, 'John', 'test123', role: :admin, metadata: {}, enabled: false)
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
- - based on `Qonfig` gem;
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
- - setitngs:
158
- - `default_type_system` - default type system (`smart_types` by default);
159
- - `strict_options` - raise an error when got unknown options if true (`true` by default);
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
- # configure:
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
- # read:
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
- - (in development) Attribue Definition DSL
295
- - Support for specifying the attribute accessor type (`read_only` parameter);
296
- - Support for attribute aliasing (`as` parameter);
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)
data/bin/console CHANGED
@@ -2,7 +2,7 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'bundler/setup'
5
- require 'smart_core'
6
-
5
+ require 'smart_core/initializer'
7
6
  require 'pry'
7
+
8
8
  Pry.start