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.
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