smart_initializer 0.4.0 → 0.8.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 -4
  4. data/Gemfile.lock +46 -45
  5. data/LICENSE.txt +1 -1
  6. data/README.md +262 -45
  7. data/bin/console +2 -2
  8. data/gemfiles/with_external_deps.gemfile.lock +40 -40
  9. data/gemfiles/without_external_deps.gemfile.lock +30 -23
  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 +31 -12
  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 +4 -4
  44. metadata +20 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a8963960f317fc7217bedf7a6974970a4380043edbee19061f08ff6d51505147
4
- data.tar.gz: 9bb224a8135f877c610e9a9941e9f0101c2dd8752d34e2834a60abbe59a6ca3f
3
+ metadata.gz: e16ae20c546597ce7c44382a790934260b44b1ebff59a51c7c7eb366205d969f
4
+ data.tar.gz: 14af5a449ae56ecf8b38d22c3ea0957f4896070556fec3c280a4b265e78f63de
5
5
  SHA512:
6
- metadata.gz: 2113967924a39041db63a8686ecbeb47c322f39a751bb7f8ceb563f34342c6db02a65db666b65962720ff93e22e34872d1df43b38ca19daa738a98d340d9efe6
7
- data.tar.gz: a6df46968cd156ebf62bd410fedba372fab4f5319cdc7df0224343729e44ef477bf0eff2ec4bbc2d1aa3c5a39cfd532ea759ef2a71d4f41eecd95e1fae7ebbd3
6
+ metadata.gz: cecc3bc1e93570d2c8cb0cc11c1b409c24d6b401a9a8225de4676a10915c7e08a1bf869315650f9ddf66c7b5dc4602e96d2a0717a83289b6fec79cb795d5dde9
7
+ data.tar.gz: 6ed53102d9c016fbdad65a3f4ad2b2aec6ad567596ec3e255f33a55f979eab5180138ae496f1ff5eafae3ae71019229ea8840d9fc1608ddcbb821a6f2aeffae5
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,11 +1,53 @@
1
1
  # Changelog
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
- ## [0.4.0] - 2020-01-18
4
+ ## [0.8.0] - 2021-12-04
5
+ ### Added
6
+ - New options for option and param attributes:
7
+ - Support for attribute **aliasing** (`:as` parameter);
8
+ - supports: `option`, `param`;
9
+ - Support for attribute **auto-casting** (`:auto_cast` parameter);
10
+ - supports: `option`, `param`;
11
+ - Support for **mutable** attributes (`:mutable` parameter) with type-validation inside;
12
+ - supports: `option`, `options`, `param`, `params`;
13
+ - Support for **optional** attributes (`:optional` parameter);
14
+ - supports: `option`;
15
+ - **SmartCore::Initializer::Configuration**:
16
+ - Configuration setting `strict_options` now works separately "per-class" in all configs manner
17
+ (each class shares the global state but has own state too)
18
+ - Support for per-class/global `:auto_cast` configuration;
19
+ - provides a global/per-class behavior for `:cast` option (`false` by default);
20
+ - `options` declaration now supports `privacy` option;
21
+ - `params` declaration now supports `privacy` option;
22
+
23
+ ### Changed
24
+ - Drop support of **Ruby@2.4**;
25
+ - `:default` attribute parameter now duplicates the passed value during object instantiation;
26
+ - `:default` attribute parameter only works with `option` attribute (`param` can't have `default` parameter now);
27
+ - Attribute values generated by `:finalize` are type-validated now too;
28
+ - Now lambda-based `:finalize` attributes are being checked for the signature during attribute declaration;
29
+ - Some error messages have become more readable;
30
+
31
+ ## Fixed
32
+ - `send` method overlaping/rewriting: otions and params named as `send` breaks the internal
33
+ framework-related invocations of the attribute definitioning inside the custom object constructor
34
+ (this name rewrites internal Ruby's `send` method and brokes some things);
35
+
36
+ ## [0.7.0] - 2021-06-23
37
+ ### Added
38
+ - `strict_options` config option for non-strict checking of passed options;
39
+
40
+ ## [0.6.0] - 2021-06-23
41
+ ### Added
42
+ - Validation messages for incorrect attribute types;
43
+
44
+ ## [0.5.0] - 2021-01-18
45
+ ### Changed
46
+ - Updated `smart_types` dependency (`~> 0.4.0`) to guarantee **Ruby@3** compatibility;
47
+ - Updated development dependencies;
48
+
49
+ ## [0.4.0] - 2021-01-18
5
50
  ### Added
6
- - Attribue Definition DSL
7
- - Support for specifying the attribute accessor type (`read_only` parameter);
8
- - Support for attribute aliasing (`as` parameter);
9
51
  - Support for **Ruby 3**;
10
52
 
11
53
  ### Changed
data/Gemfile.lock CHANGED
@@ -1,47 +1,47 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- smart_initializer (0.4.0)
4
+ smart_initializer (0.8.0)
5
5
  qonfig (~> 0.24)
6
6
  smart_engine (~> 0.11)
7
- smart_types (~> 0.1)
7
+ smart_types (~> 0.4)
8
8
 
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)
86
+ simplecov_json_formatter (0.1.3)
88
87
  smart_engine (0.11.0)
89
- smart_types (0.3.0)
90
- smart_engine (~> 0.10)
88
+ smart_types (0.7.0)
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.31
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](#constructor-definition)
36
+ - [param](#param)
37
+ - [option](#option)
38
+ - [params](#params)
39
+ - [options](#options)
40
+ - [param and params signature](#param-and-params-signature)
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 auto-casting](#type-auto-casting)
30
48
  - [Initialization extension](#initialization-extension)
31
49
  - [Plugins](#plugins)
32
50
  - [thy-types](#plugin-thy-types)
@@ -37,51 +55,69 @@ 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;
61
+ 2. Original **#initialize** invokation;
44
62
  3. Initialization extensions invokation;
45
63
 
46
- **Constructor definition**:
64
+ **NOTE!**: original constructor is called after **SmarteCore::Initializer**'s constructor
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)
67
+
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
+ ---
75
+
76
+ ### Constructor definition DSL
77
+
78
+ **NOTE**: last `Hash` argument will be treated as `kwarg`s;
79
+
80
+ #### param
47
81
 
48
82
  - `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;
83
+ - `cast` (optional) - type-cast received value if value has invalid type;
84
+ - `privacy` (optional) - reader incapsulation level;
85
+ - `finalize` (optional) - value post-processing (receives method name or proc) (the result value type is also validate);
86
+ - `type_system` (optional) - differently chosen type system for the current attribute;
87
+ - `as` (optional)- attribute alias (be careful with naming aliases that overlap the names of other attributes);
88
+ - `mutable` (optional) - generate type-validated attr_writer in addition to attr_reader (`false` by default)
89
+ - (**limitation**) param has no `:default` option;
61
90
 
62
- #### initializer integration
91
+ #### option
63
92
 
64
- ```ruby
65
- # with pre-configured type system (:smart_types, see Configuration doc)
93
+ - `option` - defined kwarg-like attribute:
94
+ - `cast` (optional) - type-cast received value if value has invalid type;
95
+ - `privacy` (optional) - reader incapsulation level;
96
+ - `as` (optional) - attribute alias (be careful with naming aliases that overlap the names of other attributes);
97
+ - `mutable` (optional) - generate type-validated attr_writer in addition to attr_reader (`false` by default)
98
+ - `optional` (optional) - mark attribut as optional (you can may not initialize optional attributes,
99
+ their values will be initialized with `nil` or by `default:` parameter);
100
+ - `finalize` (optional) - value post-processing (receives method name or proc) (the result value type is also validate);
101
+ - expects `Proc` object or `symbol`/`string` isntance method;
102
+ - `default` (optional) - defalut value (if an attribute is not provided);
103
+ - expects `Proc` object or a simple value of any type;
104
+ - non-proc values will be `dup`licate during initialization;
105
+ - `type_system` (optional) - differently chosen type system for the current attribute;
66
106
 
67
- class MyStructure
68
- include SmartCore::Initializer
69
- end
70
- ```
107
+ #### params
71
108
 
72
- ```ruby
73
- # with manually chosen type system
109
+ - `params` - define a series of parameters;
110
+ - `:mutable` (optional) - (`false` by default);
111
+ - `:privacy` (optional) - (`:public` by default);
74
112
 
75
- class MyStructure
76
- include SmartCore::Initializer(type_system: :smart_types)
77
- end
113
+ #### options
78
114
 
79
- class AnotherStructure
80
- include SmartCore::Initializer(type_system: :thy_types)
81
- end
82
- ```
115
+ - `options` - define a series of options;
116
+ - `:mutable` (optional) - (`false` by default);
117
+ - `:privacy` (optional) - (`:public` by default);
83
118
 
84
- #### `param` signautre:
119
+
120
+ #### `param` and `params` signautre:
85
121
 
86
122
  ```ruby
87
123
  param <attribute_name>,
@@ -89,10 +125,19 @@ param <attribute_name>,
89
125
  cast: false, # false by default
90
126
  privacy: :public, # :public by default
91
127
  finalize: proc { |value| value }, # no finalization by default
128
+ finalize: :some_method, # use this apporiach in order to finalize by `some_method(value)` instance method
129
+ as: :some_alias, # define attribute alias
130
+ mutable: true, # (false by default) generate type-validated attr_writer in addition to attr_reader
92
131
  type_system: :smart_types # used by default
93
132
  ```
94
133
 
95
- #### `option` signature:
134
+ ```ruby
135
+ params <atribute_name1>, <attribute_name2>, <attribute_name3>, ...,
136
+ mutable: true, # generate type-validated attr_writer in addition to attr_reader (false by default);
137
+ privacy: :private # incapsulate all attributes as private
138
+ ```
139
+
140
+ #### `option` and `options` signature:
96
141
 
97
142
  ```ruby
98
143
  option <attribute_name>,
@@ -100,11 +145,58 @@ option <attribute_name>,
100
145
  cast: false, # false by default
101
146
  privacy: :public, # :public by default
102
147
  finalize: proc { |value| value }, # no finalization by default
148
+ finalize: :some_method, # use this apporiach in order to finalize by `some_method(value)` instance method
103
149
  default: 123, # no default value by default
150
+ default: proc { 123 }, # use proc/lambda object for dynamic initialization
151
+ as: :some_alias, # define attribute alias
152
+ mutable: true, # (false by default) generate type-validated attr_writer in addition to attr_reader
153
+ optional: true # (false by default) mark attribute as optional (attribute will be defined with `nil` or by `default:` value)
104
154
  type_system: :smart_types # used by default
105
155
  ```
106
156
 
107
- Example:
157
+ ```ruby
158
+ options <attribute_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
+ ---
164
+
165
+ ## Initializer integration
166
+
167
+ - supports per-class configurations;
168
+ - possible configurations:
169
+ - `:type_system` - chosen type-system (`smart_types` by default);
170
+ - `:strict_options` - fail extra kwarg-attributes, passed to the constructor (`true` by default);
171
+ - `:auto_cast` - type-cast all values to the declared attribute type (`false` by default);
172
+
173
+ ```ruby
174
+ # with pre-configured type system (:smart_types, see Configuration doc)
175
+
176
+ class MyStructure
177
+ include SmartCore::Initializer
178
+ end
179
+ ```
180
+
181
+ ```ruby
182
+ # with manually chosen settings
183
+
184
+ class MyStructure
185
+ include SmartCore::Initializer(
186
+ type_system: :smart_types, # use smart_types
187
+ auto_cast: true, # type-cast all values by default
188
+ strict_options: false # ignore extra kwargs passed to the constructor
189
+ )
190
+ end
191
+
192
+ class AnotherStructure
193
+ include SmartCore::Initializer(type_system: :thy_types) # use thy_types and global defaults
194
+ end
195
+ ```
196
+
197
+ ---
198
+
199
+ ### Basic Example:
108
200
 
109
201
 
110
202
  ```ruby
@@ -114,13 +206,34 @@ class User
114
206
  include SmartCore::Initializer(type_system: :smart_types)
115
207
 
116
208
  param :user_id, SmartCore::Types::Value::Integer, cast: false, privacy: :public
209
+ param :login, :string, mutable: true
210
+
117
211
  option :role, default: :user, finalize: -> { |value| Role.find(name: value) }
118
212
 
213
+ # NOTE: for method-based finalizetion use `your_method(value)` isntance method of your class;
214
+ # NOTE: for dynamic default values use `proc` objects and `lambda` objects;
215
+
119
216
  params :name, :password
120
217
  options :metadata, :enabled
121
218
  end
122
219
 
123
- User.new(1, 'John', 'test123', role: :admin, metadata: {}, enabled: false)
220
+ # with correct types (incorrect types will raise SmartCore::Initializer::IncorrectTypeError)
221
+ object = User.new(1, 'kek123', 'John', 'test123', role: :admin, metadata: {}, enabled: false)
222
+
223
+ # attribute accessing:
224
+ object.user_id # => 1
225
+ object.login # => 'kek123'
226
+ object.name # => 'John'
227
+ object.password # => 'test123'
228
+ object.role # => :admin
229
+ object.metadata # => {}
230
+ object.enabled # => false
231
+
232
+ # attribute mutation (only mutable attributes have a mutator):
233
+ object.login = 123 # => (type vlaidation error) raises SmartCore::Initializer::IncorrectTypeError (expected String, got Integer)
234
+ object.login # => 'kek123'
235
+ object.login = 'pek456'
236
+ object.login # => 'pek456'
124
237
  ```
125
238
 
126
239
  ---
@@ -152,25 +265,65 @@ user.__attributes__ # => { first_name: 'Rustam', second_name: 'Ibragimov', age:
152
265
 
153
266
  ## Configuration
154
267
 
155
- - based on `Qonfig` gem;
268
+ - **configuration setitngs**:
269
+ - `:default_type_system` - default type system (`smart_types` by default);
270
+ - `:strict_options` - fail on extra kwarg-attributes passed to the constructor (`true` by default);
271
+ - `:auto_cast` - type-cast all values to the declared attribute type (`false` by default);
272
+ - by default, all classes uses and inherits the Global configuration;
156
273
  - 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);
274
+ - each class can be configured separately (in `include` invocation);
275
+ - global configuration affects classes used the default global configs in run-time;
276
+ - each class can be re-configured separately in run-time;
277
+ - based on `Qonfig` gem;
159
278
 
160
279
  ```ruby
161
- # configure:
280
+ # Global configuration:
281
+
162
282
  SmartCore::Initializer::Configuration.configure do |config|
163
283
  config.default_type_system = :smart_types # default setting value
284
+ config.strict_options = true # default setting value
285
+ config.auto_cast = false # default setting value
164
286
  end
165
287
  ```
166
288
 
167
289
  ```ruby
168
- # read:
290
+ # Read configs:
291
+
169
292
  SmartCore::Initializer::Configuration[:default_type_system]
170
293
  SmartCore::Initializer::Configuration.config[:default_type_system]
171
294
  SmartCore::Initializer::Configuration.config.settings.default_type_system
172
295
  ```
173
296
 
297
+ ```ruby
298
+ # per-class configuration:
299
+
300
+ class Parameters
301
+ include SmartCore::Initializer(auto_cast: true, strict_options: false)
302
+ # 1. use globally configured `smart_types` (default value)
303
+ # 2. type-cast all attributes by default (auto_cast: true)
304
+ # 3. ignore extra kwarg-attributes passed to the constructor (strict_options: false)
305
+ end
306
+
307
+ class User
308
+ include SmartCore::Initializer(type_system: :thy_types)
309
+ # 1. use :thy_types isntead of pre-configured :smart_types
310
+ # 2. use pre-configured auto_cast (false by default above)
311
+ # 3. use pre-configured strict_options ()
312
+ end
313
+ ```
314
+
315
+ ```ruby
316
+ # debug class-related configurations:
317
+
318
+ class SomeClass
319
+ include SmartCore::Initializer(type_system: :thy_types)
320
+ end
321
+
322
+ SomeClass.__initializer_settings__[:type_system] # => :thy_types
323
+ SomeClass.__initializer_settings__[:auto_cast] # => false
324
+ SomeClass.__initializer_settings__[:strict_options] # => true
325
+ ```
326
+
174
327
  ---
175
328
 
176
329
  ## Type aliasing
@@ -206,6 +359,63 @@ SmartCore::Initializer::TypeSystem::ThyTypes.type_aliases
206
359
 
207
360
  ---
208
361
 
362
+ ## Type-casting
363
+
364
+ - make param/option as type-castable:
365
+
366
+ ```ruby
367
+ class Order
368
+ include SmartCore::Initializer
369
+
370
+ param :manager, 'string' # cast: false is used by default
371
+ param :amount, 'float', cast: true
372
+
373
+ option :status, :symbol # cast: false is used by default
374
+ option :is_processed, 'boolean', cast: true
375
+ option :processed_at, 'time', cast: true
376
+ end
377
+
378
+ order = Order.new(
379
+ 'Daiver',
380
+ '123.456',
381
+ status: :pending,
382
+ is_processed: nil,
383
+ processed_at: '2021-01-01'
384
+ )
385
+
386
+ order.manager # => 'Daiver'
387
+ order.amount # => 123.456 (type casted)
388
+ order.status # => :pending
389
+ order.is_processed # => false (type casted)
390
+ order.processed_at # => 2021-01-01 00:00:00 +0300 (type casted)
391
+ ```
392
+
393
+ - configure automatic type casting:
394
+
395
+ ```ruby
396
+ # per class
397
+
398
+ class User
399
+ include SmartCore::Initializer(auto_cast: true) # auto type cast every attribute
400
+
401
+ param :x, 'string'
402
+ param :y, 'numeric', cast: false # disable type-casting
403
+
404
+ option :b, 'integer', cast: false # disable type-casting
405
+ option :c, 'boolean'
406
+ end
407
+ ```
408
+
409
+ ```ruby
410
+ # globally
411
+
412
+ SmartCore::Initializer::Configuration.configure do |config|
413
+ config.auto_cast = true # false by default
414
+ end
415
+ ```
416
+
417
+ ---
418
+
209
419
  ## Initialization extension
210
420
 
211
421
  - `ext_init(&block)`:
@@ -289,10 +499,11 @@ User.new(123, 'test', { admin: true, age: 22 })
289
499
 
290
500
  ## Roadmap
291
501
 
292
- - Attribue Definition DSL
293
- - Support for specifying the attribute accessor type (`read_only` parameter);
294
- - Support for attribute aliasing (`as` parameter);
502
+ - (**thinking** / **discussing**) Finalize should be invoked on `mutable` attributes after mutation too;
503
+ - Support for `RSpec` doubles and instance_doubles inside the type system integration;
504
+ - Specs restructuring;
295
505
  - Migrate from `TravisCI` to `GitHub Actions`;
506
+ - Extract `Type Interop` system to `smart_type-system`;
296
507
 
297
508
  ---
298
509
 
@@ -346,6 +557,12 @@ bundle exec rake rubocop -A
346
557
 
347
558
  Released under MIT License.
348
559
 
560
+ ## Supporting
561
+
562
+ <a target="_blank" href="https://github.com/Cado-Labs">
563
+ <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%;">
564
+ </a>
565
+
349
566
  ## Authors
350
567
 
351
568
  [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