smart_initializer 0.5.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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)