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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/CHANGELOG.md +46 -1
  4. data/Gemfile.lock +45 -44
  5. data/LICENSE.txt +1 -1
  6. data/README.md +283 -40
  7. data/bin/console +2 -2
  8. data/gemfiles/with_external_deps.gemfile.lock +38 -38
  9. data/gemfiles/without_external_deps.gemfile.lock +50 -45
  10. data/lib/smart_core/initializer/attribute/factory/base.rb +145 -0
  11. data/lib/smart_core/initializer/attribute/factory/option.rb +107 -0
  12. data/lib/smart_core/initializer/attribute/factory/param.rb +63 -0
  13. data/lib/smart_core/initializer/attribute/factory.rb +5 -199
  14. data/lib/smart_core/initializer/attribute/finalizer/abstract.rb +2 -0
  15. data/lib/smart_core/initializer/attribute/finalizer/instance_method.rb +1 -1
  16. data/lib/smart_core/initializer/attribute/finalizer.rb +5 -5
  17. data/lib/smart_core/initializer/attribute/list.rb +20 -0
  18. data/lib/smart_core/initializer/attribute/{parameters.rb → value/base.rb} +35 -65
  19. data/lib/smart_core/initializer/attribute/value/option.rb +101 -0
  20. data/lib/smart_core/initializer/attribute/value/param.rb +24 -0
  21. data/lib/smart_core/initializer/attribute/value.rb +9 -0
  22. data/lib/smart_core/initializer/attribute.rb +3 -112
  23. data/lib/smart_core/initializer/configuration.rb +9 -0
  24. data/lib/smart_core/initializer/constructor/definer.rb +135 -46
  25. data/lib/smart_core/initializer/constructor.rb +29 -14
  26. data/lib/smart_core/initializer/dsl.rb +38 -24
  27. data/lib/smart_core/initializer/errors.rb +20 -0
  28. data/lib/smart_core/initializer/functionality.rb +7 -8
  29. data/lib/smart_core/initializer/plugins/thy_types/thy_types/abstract_factory.rb +13 -2
  30. data/lib/smart_core/initializer/settings/auto_cast.rb +40 -0
  31. data/lib/smart_core/initializer/settings/base.rb +49 -0
  32. data/lib/smart_core/initializer/settings/duplicator.rb +5 -0
  33. data/lib/smart_core/initializer/settings/strict_options.rb +40 -0
  34. data/lib/smart_core/initializer/settings/type_system.rb +10 -28
  35. data/lib/smart_core/initializer/settings.rb +40 -0
  36. data/lib/smart_core/initializer/type_system/interop/abstract_factory.rb +12 -2
  37. data/lib/smart_core/initializer/type_system/interop.rb +10 -1
  38. data/lib/smart_core/initializer/type_system/registry.rb +2 -1
  39. data/lib/smart_core/initializer/type_system/smart_types/abstract_factory.rb +13 -2
  40. data/lib/smart_core/initializer/type_system/smart_types.rb +2 -2
  41. data/lib/smart_core/initializer/version.rb +2 -2
  42. data/lib/smart_core/initializer.rb +14 -4
  43. data/smart_initializer.gemspec +3 -3
  44. metadata +18 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e7a9f30c8b223f8e66bc1ac23dfd183cd80d32c0620fd929ecdc42a534381635
4
- data.tar.gz: eee561816ebbacf1a4f583d5038da3bb3478c10790a95e6c01ca8569a065174d
3
+ metadata.gz: 9ef704918e8e3d81bfb2dd551b96f4e68f2a0f2cefacfdbced95ae9cce1a6b0b
4
+ data.tar.gz: 3960c509958efb9a0886d959ff3a55b6965bb916f80bd32bf04e0977d58b7560
5
5
  SHA512:
6
- metadata.gz: 2e1c9e0b9f6b84cf6ad9fc5e84107fcddcc684ea80fb4c7f4fcf93f388d95cee0d7f36cae96106d19766964b79ae247f24c263ce51df81dabbef482204c04da8
7
- data.tar.gz: 1ecac9ea5d30974515fdc8b3aac16d4b72c922f3d1c837353006200167f203ccb5ee8c94f8b6ea517dad9b86c80deb8818ae18471ad098339595b15d7aa6ee07
6
+ metadata.gz: 329ebcfc66cab98ab6e35b392c425df04eb5d03260b3bcefceb6c9cffa8863bad1fafce5d3b822c4fd0d39e0caab36a502b38a8ed15ecba1f0157908a6bbbc0d
7
+ data.tar.gz: 31f8259c26367c56961dc70cd086dcae7e96f3eafa206b3395b2f4afc0cb25afc3bba6d55a94251d1495bb13fd27c3c590ca67ace17bba1af226b48ceacfb7a9
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,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
- ## Changed
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.5.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.7.0.1)
19
- rubocop (= 1.7.0)
20
- rubocop-performance (= 1.9.1)
21
- rubocop-rails (= 2.9.1)
22
- rubocop-rake (= 0.5.1)
23
- rubocop-rspec (= 2.1.0)
24
- ast (2.4.1)
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.7)
26
+ concurrent-ruby (1.1.9)
27
27
  diff-lcs (1.4.4)
28
- docile (1.3.5)
29
- i18n (1.8.7)
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.13.1)
36
+ pry (0.14.1)
37
37
  coderay (~> 1.1)
38
38
  method_source (~> 1.0)
39
- qonfig (0.25.0)
39
+ qonfig (0.26.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)
@@ -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.1)
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.1)
58
- rubocop (1.7.0)
57
+ rspec-support (3.10.3)
58
+ rubocop (1.23.0)
59
59
  parallel (~> 1.10)
60
- parser (>= 2.7.1.5)
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
- unicode-display_width (>= 1.4.0, < 2.0)
67
- rubocop-ast (1.4.0)
68
- parser (>= 2.7.1.5)
69
- rubocop-performance (1.9.1)
70
- rubocop (>= 0.90.0, < 2.0)
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.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 (1.7.0)
94
- zeitwerk (2.4.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.7)
101
+ armitage-rubocop (~> 1.23)
101
102
  bundler (~> 2.2)
102
- pry (~> 0.13)
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.3
110
+ 2.2.32
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2020 Rustam Ibragimov
3
+ Copyright (c) 2020-2021 Rustam Ibragimov
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
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,92 @@ 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
+ **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
- # with pre-configured type system (:smart_types, see Configuration doc)
78
+ # without :default
66
79
 
67
- class MyStructure
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 manually chosen type system
89
+ # with :default
74
90
 
75
- class MyStructure
76
- include SmartCore::Initializer(type_system: :smart_types)
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
- class AnotherStructure
80
- include SmartCore::Initializer(type_system: :thy_types)
81
- end
96
+ User.new.age # => '0_years'
82
97
  ```
83
98
 
84
- #### `param` signautre:
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
- #### `option` signature:
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
- Example:
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
- User.new(1, 'John', 'test123', role: :admin, metadata: {}, enabled: false)
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
- - based on `Qonfig` gem;
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
- - setitngs:
158
- - `default_type_system` - default type system (`smart_types` by default);
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
- # configure:
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
- # read:
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
- - (in development) Attribue Definition DSL
293
- - Support for specifying the attribute accessor type (`read_only` parameter);
294
- - Support for attribute aliasing (`as` parameter);
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)