smart_initializer 0.0.0 → 0.1.0.alpha1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +5 -5
- data/README.md +18 -0
- data/lib/smart_core/initializer/attribute/definer.rb +2 -2
- data/lib/smart_core/initializer/attribute/factory.rb +8 -4
- data/lib/smart_core/initializer/attribute/finalizer/abstract.rb +37 -0
- data/lib/smart_core/initializer/attribute/finalizer/anonymous_block.rb +27 -25
- data/lib/smart_core/initializer/attribute/finalizer/instance_method.rb +27 -25
- data/lib/smart_core/initializer/attribute/finalizer.rb +1 -6
- data/lib/smart_core/initializer/attribute/list.rb +28 -0
- data/lib/smart_core/initializer/attribute/parameters.rb +30 -6
- data/lib/smart_core/initializer/attribute.rb +40 -13
- data/lib/smart_core/initializer/constructor.rb +158 -0
- data/lib/smart_core/initializer/dsl/inheritance.rb +18 -0
- data/lib/smart_core/initializer/dsl.rb +36 -2
- data/lib/smart_core/initializer/errors.rb +16 -0
- data/lib/smart_core/initializer/type_aliasing/alias_list.rb +102 -0
- data/lib/smart_core/initializer/type_aliasing.rb +50 -0
- data/lib/smart_core/initializer/version.rb +1 -1
- data/lib/smart_core/initializer.rb +22 -1
- data/smart_initializer.gemspec +2 -2
- metadata +13 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cd7d1a7f5aa327457a601a1b1a0110d8178e6bd83b557a53365e0cf96d336080
|
4
|
+
data.tar.gz: 1487df01e94537cf79292f293f525f9ecde081edb0438e61d9674c7b2ac2cf6b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7395f7428558b2a891090376c455c0a2cd4a8d730e615d69a1d33aeac2703bae64642e9a0024072c2efbdc4dfdff9bbe8ae26481ea6706e8355825fb30bf8559
|
7
|
+
data.tar.gz: 662340beb7c3d1980d6870b9a9d555e8e86191c08fda50c9925ed99ba065b99e2bb6d6de9b906521298fa1add43a955ee5cd9f2bd9bdad67f04e58a7ee72be5f
|
data/Gemfile.lock
CHANGED
@@ -2,8 +2,8 @@ PATH
|
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
4
|
smart_initializer (0.1.0)
|
5
|
-
smart_engine (~> 0.
|
6
|
-
smart_types (~> 0.1.0.
|
5
|
+
smart_engine (~> 0.5)
|
6
|
+
smart_types (~> 0.1.0.alpha4)
|
7
7
|
|
8
8
|
GEM
|
9
9
|
remote: https://rubygems.org/
|
@@ -60,9 +60,9 @@ GEM
|
|
60
60
|
json (>= 1.8, < 3)
|
61
61
|
simplecov-html (~> 0.10.0)
|
62
62
|
simplecov-html (0.10.2)
|
63
|
-
smart_engine (0.
|
64
|
-
smart_types (0.1.0.
|
65
|
-
smart_engine (~> 0.
|
63
|
+
smart_engine (0.5.0)
|
64
|
+
smart_types (0.1.0.alpha4)
|
65
|
+
smart_engine (~> 0.5)
|
66
66
|
unicode-display_width (1.6.1)
|
67
67
|
|
68
68
|
PLATFORMS
|
data/README.md
CHANGED
@@ -36,6 +36,24 @@ end
|
|
36
36
|
User.new(1, 'John', 'test123', role: :admin, metadata: {}, enabled: false)
|
37
37
|
```
|
38
38
|
|
39
|
+
**Limitations**:
|
40
|
+
|
41
|
+
- `param` has no :default option (at all);
|
42
|
+
- last hash argument will be treated as `kwarg`s;
|
43
|
+
|
44
|
+
**Type aliasing**:
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
SmartCore::Initializer.type_alias(:hash, SmartCore::Types::Value::Hash)
|
48
|
+
|
49
|
+
class User
|
50
|
+
include SmartCore::Initializer
|
51
|
+
|
52
|
+
param :data, :hash
|
53
|
+
option :metadata, :hash
|
54
|
+
end
|
55
|
+
```
|
56
|
+
|
39
57
|
---
|
40
58
|
|
41
59
|
## Contributing
|
@@ -41,7 +41,7 @@ class SmartCore::Initializer::Attribute::Definer
|
|
41
41
|
names.map do |name|
|
42
42
|
build_attribute(
|
43
43
|
name,
|
44
|
-
SmartCore::Types::Any,
|
44
|
+
SmartCore::Types::Value::Any,
|
45
45
|
SmartCore::Initializer::Attribute::Parameters::DEFAULT_PRIVACY_MODE,
|
46
46
|
SmartCore::Initializer::Attribute::Parameters::DEFAULT_FINALIZER,
|
47
47
|
SmartCore::Initializer::Attribute::Parameters::DEFAULT_CAST_BEHAVIOUR,
|
@@ -83,7 +83,7 @@ class SmartCore::Initializer::Attribute::Definer
|
|
83
83
|
names.map do |name|
|
84
84
|
build_attribute(
|
85
85
|
name,
|
86
|
-
SmartCore::Types::Any,
|
86
|
+
SmartCore::Types::Value::Any,
|
87
87
|
SmartCore::Initializer::Attribute::Parameters::DEFAULT_PRIVACY_MODE,
|
88
88
|
SmartCore::Initializer::Attribute::Parameters::DEFAULT_FINALIZER,
|
89
89
|
SmartCore::Initializer::Attribute::Parameters::DEFAULT_CAST_BEHAVIOUR,
|
@@ -14,7 +14,7 @@ class SmartCore::Initializer::Attribute::Factory
|
|
14
14
|
#
|
15
15
|
# @api private
|
16
16
|
# @since 0.1.0
|
17
|
-
def create(name, type,
|
17
|
+
def create(name, type, privacy, finalize, cast, dynamic_options)
|
18
18
|
name = prepare_name_param(name)
|
19
19
|
type = prepare_type_param(type)
|
20
20
|
privacy = prepare_privacy_param(privacy)
|
@@ -28,7 +28,7 @@ class SmartCore::Initializer::Attribute::Factory
|
|
28
28
|
private
|
29
29
|
|
30
30
|
# @param name [String, Symbol]
|
31
|
-
# @return [
|
31
|
+
# @return [Symbol]
|
32
32
|
#
|
33
33
|
# @api private
|
34
34
|
# @since 0.1.0
|
@@ -39,7 +39,7 @@ class SmartCore::Initializer::Attribute::Factory
|
|
39
39
|
ERROR_MESSAGE
|
40
40
|
end
|
41
41
|
|
42
|
-
name.
|
42
|
+
name.to_sym
|
43
43
|
end
|
44
44
|
|
45
45
|
# @param type [String, Symbol, SmartCore::Types::Primitive]
|
@@ -54,7 +54,11 @@ class SmartCore::Initializer::Attribute::Factory
|
|
54
54
|
ERROR_MESSAGE
|
55
55
|
end
|
56
56
|
|
57
|
-
type
|
57
|
+
if type.is_a?(String) || type.is_a?(Symbol)
|
58
|
+
SmartCore::Initializer.type_from_alias(type)
|
59
|
+
else
|
60
|
+
type
|
61
|
+
end
|
58
62
|
end
|
59
63
|
|
60
64
|
# @param cast [Boolean]
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.1.0
|
5
|
+
class SmartCore::Initializer::Attribute::Finalizer::Abstract
|
6
|
+
# @param finalizer [Any]
|
7
|
+
# @return [void]
|
8
|
+
#
|
9
|
+
# @api private
|
10
|
+
# @since 0.1.0
|
11
|
+
def initialize(finalizer)
|
12
|
+
@finalizer = finalizer
|
13
|
+
end
|
14
|
+
|
15
|
+
# @param value [Any]
|
16
|
+
# @param instance [Any]
|
17
|
+
# @return [Any]
|
18
|
+
#
|
19
|
+
# @api private
|
20
|
+
# @since 0.1.0
|
21
|
+
def call(value, instance)
|
22
|
+
raise NoMethodError
|
23
|
+
end
|
24
|
+
|
25
|
+
# @return [SmartCore::Initializer::Attribute::Finalizer::Abstract]
|
26
|
+
def dup
|
27
|
+
self.class.new(finalizer)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
# @return [Any]
|
33
|
+
#
|
34
|
+
# @api private
|
35
|
+
# @since 0.1.0
|
36
|
+
attr_reader :finalizer
|
37
|
+
end
|
@@ -1,32 +1,34 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
# @since 0.1.0
|
5
|
-
class SmartCore::Initializer::Attribute::Finalizer::AnonymousBlock
|
6
|
-
# @param finalizer [Proc]
|
7
|
-
# @return [void]
|
8
|
-
#
|
9
|
-
# @api private
|
10
|
-
# @since 0.1.0
|
11
|
-
def initialize(finalizer)
|
12
|
-
@finalizer = finalizer
|
13
|
-
end
|
14
|
-
|
15
|
-
# @param value [Any]
|
16
|
-
# @param isntance [Any]
|
17
|
-
# @return [value]
|
18
|
-
#
|
3
|
+
module SmartCore::Initializer::Attribute::Finalizer
|
19
4
|
# @pai private
|
20
5
|
# @since 0.1.0
|
21
|
-
|
22
|
-
|
23
|
-
|
6
|
+
class AnonymousBlock < Abstract
|
7
|
+
# @param finalizer [Proc]
|
8
|
+
# @return [void]
|
9
|
+
#
|
10
|
+
# @api private
|
11
|
+
# @since 0.1.0
|
12
|
+
def initialize(finalizer)
|
13
|
+
@finalizer = finalizer
|
14
|
+
end
|
24
15
|
|
25
|
-
|
16
|
+
# @param value [Any]
|
17
|
+
# @param instance [Any]
|
18
|
+
# @return [value]
|
19
|
+
#
|
20
|
+
# @pai private
|
21
|
+
# @since 0.1.0
|
22
|
+
def call(value, instance)
|
23
|
+
instance.instance_exec(value, &finalizer)
|
24
|
+
end
|
26
25
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
26
|
+
private
|
27
|
+
|
28
|
+
# @return [NilClass, Any]
|
29
|
+
#
|
30
|
+
# @api private
|
31
|
+
# @since 0.1.0
|
32
|
+
attr_reader :finalizer
|
33
|
+
end
|
32
34
|
end
|
@@ -1,32 +1,34 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
# @since 0.1.0
|
5
|
-
class SmartCore::Initializer::Attribute::Finalizer::InstanceMethod
|
6
|
-
# @param finalizer [String, Symbol]
|
7
|
-
# @return [void]
|
8
|
-
#
|
9
|
-
# @api private
|
10
|
-
# @since 0.1.0
|
11
|
-
def initialize(finalizer)
|
12
|
-
@finalizer = finalizer
|
13
|
-
end
|
14
|
-
|
15
|
-
# @param value [Any]
|
16
|
-
# @param instance [Any]
|
17
|
-
# @return [value]
|
18
|
-
#
|
3
|
+
module SmartCore::Initializer::Attribute::Finalizer
|
19
4
|
# @pai private
|
20
5
|
# @since 0.1.0
|
21
|
-
|
22
|
-
|
23
|
-
|
6
|
+
class InstanceMethod < Abstract
|
7
|
+
# @param finalizer [String, Symbol]
|
8
|
+
# @return [void]
|
9
|
+
#
|
10
|
+
# @api private
|
11
|
+
# @since 0.1.0
|
12
|
+
def initialize(finalizer)
|
13
|
+
@finalizer = finalizer
|
14
|
+
end
|
24
15
|
|
25
|
-
|
16
|
+
# @param value [Any]
|
17
|
+
# @param instance [Any]
|
18
|
+
# @return [value]
|
19
|
+
#
|
20
|
+
# @pai private
|
21
|
+
# @since 0.1.0
|
22
|
+
def call(value, instance)
|
23
|
+
instance.send(finalizer, value)
|
24
|
+
end
|
26
25
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
26
|
+
private
|
27
|
+
|
28
|
+
# @return [NilClass, Any]
|
29
|
+
#
|
30
|
+
# @api private
|
31
|
+
# @since 0.1.0
|
32
|
+
attr_reader :finalizer
|
33
|
+
end
|
32
34
|
end
|
@@ -3,15 +3,10 @@
|
|
3
3
|
# @api private
|
4
4
|
# @since 0.1.0
|
5
5
|
module SmartCore::Initializer::Attribute::Finalizer
|
6
|
+
require_relative 'finalizer/abstract'
|
6
7
|
require_relative 'finalizer/instance_method'
|
7
8
|
require_relative 'finalizer/anonymous_block'
|
8
9
|
|
9
|
-
# @return [Proc]
|
10
|
-
#
|
11
|
-
# @api private
|
12
|
-
# @since 0.1.0
|
13
|
-
DEFAULT_FINALIZER = proc { |value| value }.freeze
|
14
|
-
|
15
10
|
class << self
|
16
11
|
# @param finalization_approach [String, Symbol, Proc]
|
17
12
|
# @return [SmartCore::Initializer::Attribute::Finalizer::InstanceMethod]
|
@@ -25,6 +25,17 @@ class SmartCore::Initializer::Attribute::List
|
|
25
25
|
end
|
26
26
|
alias_method :<<, :add
|
27
27
|
|
28
|
+
# @param list [SmartCore::Initializer::Attribute::List]
|
29
|
+
# @return [void]
|
30
|
+
#
|
31
|
+
# @api private
|
32
|
+
# @since 0.1.0
|
33
|
+
def concat(list)
|
34
|
+
thread_safe do
|
35
|
+
list.each { |attribute| add(attribute.dup) }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
28
39
|
# @param attribute [SmartCore::Initializer::Attribute]
|
29
40
|
# @return [void]
|
30
41
|
#
|
@@ -45,6 +56,23 @@ class SmartCore::Initializer::Attribute::List
|
|
45
56
|
end
|
46
57
|
end
|
47
58
|
|
59
|
+
# @return [Integer]
|
60
|
+
#
|
61
|
+
# @api private
|
62
|
+
# @since 0.1.0
|
63
|
+
def size
|
64
|
+
thread_safe { attributes.size }
|
65
|
+
end
|
66
|
+
|
67
|
+
# @param block [Block]
|
68
|
+
# @return [Integer]
|
69
|
+
#
|
70
|
+
# @api private
|
71
|
+
# @since 0.1.0
|
72
|
+
def count(&block)
|
73
|
+
thread_safe { attributes.values.count(&block) }
|
74
|
+
end
|
75
|
+
|
48
76
|
private
|
49
77
|
|
50
78
|
# @return [Hash<String,SmartCore::Initializer::Attribute>]
|
@@ -10,7 +10,7 @@ class SmartCore::Initializer::Attribute::Parameters
|
|
10
10
|
PRIVACY_MODES = {
|
11
11
|
public: :public,
|
12
12
|
protected: :protected,
|
13
|
-
private: :private
|
13
|
+
private: :private
|
14
14
|
}.freeze
|
15
15
|
|
16
16
|
# @return [Symbol]
|
@@ -37,7 +37,7 @@ class SmartCore::Initializer::Attribute::Parameters
|
|
37
37
|
# @since 0.1.0
|
38
38
|
DEFAULT_DYNAMIC_OPTIONS = {}.freeze
|
39
39
|
|
40
|
-
# @return [
|
40
|
+
# @return [Symbol]
|
41
41
|
#
|
42
42
|
# @api private
|
43
43
|
# @since 0.1.0
|
@@ -67,13 +67,21 @@ class SmartCore::Initializer::Attribute::Parameters
|
|
67
67
|
# @api private
|
68
68
|
# @since 0.1.0
|
69
69
|
attr_reader :cast
|
70
|
+
alias_method :cast?, :cast
|
70
71
|
|
71
|
-
# @
|
72
|
+
# @return [Hash<Symbol,Any>]
|
73
|
+
#
|
74
|
+
# @api private
|
75
|
+
# @since 0.1.0
|
76
|
+
attr_reader :dynamic_options
|
77
|
+
|
78
|
+
# @param name [Symbol]
|
72
79
|
# @param type [SmartCore::Types::Primitive]
|
73
80
|
# @param privacy [Symbol]
|
74
81
|
# @param finalizer [SmartCore::Initializer::Attribute::AnonymousBlock/InstanceMethod]
|
75
82
|
# @param cast [Boolean]
|
76
83
|
# @param dynamic_options [Hash<Symbol,Any>]
|
84
|
+
# - :default - default value (Proc value will be called)
|
77
85
|
# @return [void]
|
78
86
|
#
|
79
87
|
# @api private
|
@@ -87,11 +95,27 @@ class SmartCore::Initializer::Attribute::Parameters
|
|
87
95
|
@dynamic_options = dynamic_options
|
88
96
|
end
|
89
97
|
|
90
|
-
|
98
|
+
# @return [Boolean]
|
99
|
+
#
|
100
|
+
# @api private
|
101
|
+
# @since 0.1.0
|
102
|
+
def has_default?
|
103
|
+
dynamic_options.key?(:default)
|
104
|
+
end
|
91
105
|
|
92
|
-
# @return [
|
106
|
+
# @return [Any]
|
107
|
+
#
|
108
|
+
# @raise [SmartCore::Initializer::NoDefaultValueError]
|
93
109
|
#
|
94
110
|
# @api private
|
95
111
|
# @since 0.1.0
|
96
|
-
|
112
|
+
def default
|
113
|
+
default_value = dynamic_options.fetch(:default) do
|
114
|
+
raise(SmartCore::Initializer::NoDefaultValueError, <<~ERROR_MESSAGE)
|
115
|
+
Attribute #{name} has no default value
|
116
|
+
ERROR_MESSAGE
|
117
|
+
end
|
118
|
+
|
119
|
+
defalut_value.is_a?(Proc) ? default_value.call : default_value
|
120
|
+
end
|
97
121
|
end
|
@@ -10,39 +10,51 @@ class SmartCore::Initializer::Attribute
|
|
10
10
|
require_relative 'attribute/factory'
|
11
11
|
|
12
12
|
# @since 0.1.0
|
13
|
-
extend Forwardable
|
13
|
+
extend ::Forwardable
|
14
14
|
|
15
|
-
# @
|
15
|
+
# @return [Symbol]
|
16
16
|
#
|
17
|
+
# @pai private
|
17
18
|
# @since 0.1.0
|
18
|
-
# @version 0.1.0
|
19
19
|
def_delegator :parameters, :name
|
20
20
|
|
21
|
-
# @
|
21
|
+
# @return [SmartCore::Types::Primitive]
|
22
22
|
#
|
23
|
+
# @pai private
|
23
24
|
# @since 0.1.0
|
24
|
-
# @version 0.1.0
|
25
25
|
def_delegator :parameters, :type
|
26
26
|
|
27
|
-
# @
|
27
|
+
# @return [Symbol]
|
28
28
|
#
|
29
|
+
# @pai private
|
29
30
|
# @since 0.1.0
|
30
|
-
# @version 0.1.0
|
31
31
|
def_delegator :parameters, :privacy
|
32
32
|
|
33
|
-
# @
|
33
|
+
# @return [SmartCore::Initializer::Attribute::Finalizer::AnonymousBlock/InstanceMethod]
|
34
34
|
#
|
35
|
+
# @pai private
|
35
36
|
# @since 0.1.0
|
36
|
-
# @version 0.1.0
|
37
37
|
def_delegator :parameters, :finalizer
|
38
38
|
|
39
|
-
# @
|
39
|
+
# @return [Boolean]
|
40
40
|
#
|
41
|
+
# @pai private
|
41
42
|
# @since 0.1.0
|
42
|
-
|
43
|
-
def_delegator :parameters, :cast
|
43
|
+
def_delegators :parameters, :cast, :cast?
|
44
44
|
|
45
|
-
# @
|
45
|
+
# @return [Any]
|
46
|
+
#
|
47
|
+
# @api private
|
48
|
+
# @since 0.1.0
|
49
|
+
def_delegator :parameters, :default
|
50
|
+
|
51
|
+
# @return [Boolean]
|
52
|
+
#
|
53
|
+
# @api private
|
54
|
+
# @since 0.1.0
|
55
|
+
def_delegator :parameters, :has_default?
|
56
|
+
|
57
|
+
# @param name [Symbol]
|
46
58
|
# @param type [SmartCore::Types::Primitive]
|
47
59
|
# @param privacy [Symbol]
|
48
60
|
# @param finalizer [SmartCore::Initializer::Attribute::Finalizer::AnonymousBlock/InstanceMethod]
|
@@ -58,6 +70,21 @@ class SmartCore::Initializer::Attribute
|
|
58
70
|
)
|
59
71
|
end
|
60
72
|
|
73
|
+
# @return [SmartCore::Initializer::Attribute]
|
74
|
+
#
|
75
|
+
# @api private
|
76
|
+
# @since 0.1.0
|
77
|
+
def dup
|
78
|
+
self.class.new(
|
79
|
+
parameters.name.dup,
|
80
|
+
parameters.type,
|
81
|
+
parameters.privacy,
|
82
|
+
parameters.finalizer.dup,
|
83
|
+
parameters.cast,
|
84
|
+
parameters.dynamic_options.dup
|
85
|
+
)
|
86
|
+
end
|
87
|
+
|
61
88
|
private
|
62
89
|
|
63
90
|
# @return [SmartCore::Initializer::Attribute::Parameters]
|
@@ -0,0 +1,158 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.1.0
|
5
|
+
class SmartCore::Initializer::Constructor
|
6
|
+
# @param klass [Class<SmartCore::Initializer>]
|
7
|
+
# @param arguments [Array<Any>]
|
8
|
+
# @param block [Proc, NilClass]
|
9
|
+
# @return [void]
|
10
|
+
#
|
11
|
+
# @api private
|
12
|
+
# @since 0.1.0
|
13
|
+
def initialize(klass, arguments, block)
|
14
|
+
@klass = klass
|
15
|
+
@arguments = arguments
|
16
|
+
@passed_parameters, @passed_options = extract_attributes(arguments)
|
17
|
+
@passed_block = block
|
18
|
+
end
|
19
|
+
|
20
|
+
# @return [Any]
|
21
|
+
#
|
22
|
+
# @api private
|
23
|
+
# @since 0.1.0
|
24
|
+
def construct
|
25
|
+
allocate_klass_instance.tap do |instance|
|
26
|
+
prevent_attribute_insufficiency
|
27
|
+
initialize_parameters(instance)
|
28
|
+
initialize_options(instance)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
# @return [Class]
|
35
|
+
#
|
36
|
+
# @api private
|
37
|
+
# @since 0.1.0
|
38
|
+
attr_reader :klass
|
39
|
+
|
40
|
+
# @return [Array<Any>]
|
41
|
+
#
|
42
|
+
# @api private
|
43
|
+
# @since 0.1.0
|
44
|
+
attr_reader :arguments
|
45
|
+
|
46
|
+
# @return [Array<Any>]
|
47
|
+
#
|
48
|
+
# @api private
|
49
|
+
# @since 0.1.0
|
50
|
+
attr_reader :passed_parameters
|
51
|
+
|
52
|
+
# @return [Hash<Symbol,Any>]
|
53
|
+
#
|
54
|
+
# @api private
|
55
|
+
# @since 0.1.0
|
56
|
+
attr_reader :passed_options
|
57
|
+
|
58
|
+
# @return [Proc, NilClass]
|
59
|
+
#
|
60
|
+
# @api private
|
61
|
+
# @since 0.1.0
|
62
|
+
attr_reader :passed_block
|
63
|
+
|
64
|
+
# @return [void]
|
65
|
+
#
|
66
|
+
# @raise [SmartCore::Initializer::ParameterArgumentError]
|
67
|
+
# @raise [SmartCore::Initializer::OptionArgumentError]
|
68
|
+
#
|
69
|
+
# @api private
|
70
|
+
# @since 0.1.0
|
71
|
+
def prevent_attribute_insufficiency
|
72
|
+
required_options = klass.__options__.reject(&:has_default?).map(&:name)
|
73
|
+
required_parameter_count = klass.__params__.size
|
74
|
+
|
75
|
+
raise(
|
76
|
+
SmartCore::Initializer::ParameterArgumentError,
|
77
|
+
"Wrong number of parameters " \
|
78
|
+
"(given #{passed_parameters.size}, expected #{required_parameter_count})"
|
79
|
+
) unless passed_parameters.size == required_parameter_count
|
80
|
+
|
81
|
+
missing_options = required_options.reject { |option| passed_options.key?(option) }
|
82
|
+
|
83
|
+
raise(
|
84
|
+
SmartCore::Initializer::OptionArgumentError,
|
85
|
+
"Missing options: #{missing_options.join(', ')}"
|
86
|
+
) if missing_options.any?
|
87
|
+
end
|
88
|
+
|
89
|
+
# @return [Any]
|
90
|
+
#
|
91
|
+
# @api private
|
92
|
+
# @since 0.1.0
|
93
|
+
def allocate_klass_instance
|
94
|
+
klass.allocate
|
95
|
+
end
|
96
|
+
|
97
|
+
# @param instance [Any]
|
98
|
+
# @return [void]
|
99
|
+
#
|
100
|
+
# @api private
|
101
|
+
# @since 0.1.0
|
102
|
+
def initialize_parameters(instance)
|
103
|
+
parameter_definitions = Hash[klass.__params__.zip(passed_parameters)]
|
104
|
+
|
105
|
+
parameter_definitions.each_pair do |attribute, parameter_value|
|
106
|
+
parameter_value = attribute.type.cast(parameter_value) if attribute.cast?
|
107
|
+
|
108
|
+
# TODO: fail with SmartCore::Initializer::ArgumentError
|
109
|
+
# (isntead of SmartCore::Types::TypeError)
|
110
|
+
attribute.type.validate!(parameter_value)
|
111
|
+
|
112
|
+
final_value = attribute.finalizer.call(parameter_value, instance)
|
113
|
+
instance.instance_variable_set("@#{attribute.name}", final_value)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# @param instance [Any]
|
118
|
+
# @return [void]
|
119
|
+
#
|
120
|
+
# @api private
|
121
|
+
# @since 0.1.0
|
122
|
+
def initialize_options(instance)
|
123
|
+
klass.__options__.each do |attribute|
|
124
|
+
option_value = passed_options.fetch(attribute.name) { attribute.default }
|
125
|
+
option_value = attribute.type.cast(option_value) if attribute.cast?
|
126
|
+
|
127
|
+
# TODO: fail with SmartCore::Initializer::ArgumentError
|
128
|
+
# (isntead of SmartCore::Types::TypeError)
|
129
|
+
attribute.type.validate!(option_value)
|
130
|
+
|
131
|
+
final_value = attribute.finalizer.call(option_value, instance)
|
132
|
+
instance.instance_variable_set("@#{attribute.name}", final_value)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
# @param arguments [Array<Any>]
|
137
|
+
# @return [Array<Array<Any>,Hash<Symbol,Any>>]
|
138
|
+
#
|
139
|
+
# @api private
|
140
|
+
# @since 0.1.0
|
141
|
+
def extract_attributes(arguments)
|
142
|
+
parameters = []
|
143
|
+
options = {}
|
144
|
+
|
145
|
+
if (
|
146
|
+
klass.__options__.size >= 1 &&
|
147
|
+
arguments.last.is_a?(Hash) &&
|
148
|
+
arguments.last.keys.all? { |key| key.is_a?(Symbol) }
|
149
|
+
)
|
150
|
+
parameters = arguments[0..-2]
|
151
|
+
options = arguments.last
|
152
|
+
else
|
153
|
+
parameters = arguments
|
154
|
+
end
|
155
|
+
|
156
|
+
[parameters, options]
|
157
|
+
end
|
158
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.1.0
|
5
|
+
module SmartCore::Initializer::DSL::Inheritance
|
6
|
+
class << self
|
7
|
+
# @param base [Class]
|
8
|
+
# @param child [Class]
|
9
|
+
# @return [void]
|
10
|
+
#
|
11
|
+
# @api private
|
12
|
+
# @since 0.1.0
|
13
|
+
def inherit(base:, child:)
|
14
|
+
child.__params__.concat(base.__params__)
|
15
|
+
child.__options__.concat(base.__options__)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -3,20 +3,44 @@
|
|
3
3
|
# @api private
|
4
4
|
# @since 0.1.0
|
5
5
|
module SmartCore::Initializer::DSL
|
6
|
+
require_relative 'dsl/inheritance'
|
7
|
+
|
6
8
|
class << self
|
7
9
|
# @param base_klass [Class]
|
8
10
|
# @return [void]
|
9
11
|
#
|
10
12
|
# @api private
|
11
13
|
# @since 0.1.0
|
12
|
-
def
|
14
|
+
def extended(base_klass)
|
13
15
|
base_klass.instance_eval do
|
14
16
|
instance_variable_set(:@__params__, SmartCore::Initializer::Attribute::List.new)
|
15
17
|
instance_variable_set(:@__options__, SmartCore::Initializer::Attribute::List.new)
|
16
18
|
instance_variable_set(:@__definer__, SmartCore::Initializer::Attribute::Definer.new(self))
|
19
|
+
instance_variable_set(:@__deflock__, SmartCore::Engine::Lock.new)
|
17
20
|
end
|
18
|
-
|
19
21
|
base_klass.extend(ClassMethods)
|
22
|
+
base_klass.singleton_class.prepend(ClassInheritance)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# @api private
|
27
|
+
# @since 0.1.0
|
28
|
+
module ClassInheritance
|
29
|
+
# @param child_klass [Class]
|
30
|
+
# @return [void]
|
31
|
+
#
|
32
|
+
# @api private
|
33
|
+
# @since 0.1.0
|
34
|
+
def inherited(child_klass)
|
35
|
+
child_klass.instance_eval do
|
36
|
+
instance_variable_set(:@__params__, SmartCore::Initializer::Attribute::List.new)
|
37
|
+
instance_variable_set(:@__options__, SmartCore::Initializer::Attribute::List.new)
|
38
|
+
instance_variable_set(:@__definer__, SmartCore::Initializer::Attribute::Definer.new(self))
|
39
|
+
instance_variable_set(:@__deflock__, SmartCore::Engine::Lock.new)
|
40
|
+
end
|
41
|
+
child_klass.extend(ClassMethods)
|
42
|
+
SmartCore::Initializer::DSL::Inheritance.inherit(base: self, child: child_klass)
|
43
|
+
super
|
20
44
|
end
|
21
45
|
end
|
22
46
|
|
@@ -47,6 +71,16 @@ module SmartCore::Initializer::DSL
|
|
47
71
|
@__definer__
|
48
72
|
end
|
49
73
|
|
74
|
+
# @param arguments [Array]
|
75
|
+
# @param block [Block]
|
76
|
+
# @return [Any]
|
77
|
+
#
|
78
|
+
# @api public
|
79
|
+
# @since 0.1.0
|
80
|
+
def new(*arguments, &block)
|
81
|
+
SmartCore::Initializer::Constructor.new(self, arguments, block).construct
|
82
|
+
end
|
83
|
+
|
50
84
|
# @param name [String, Symbol]
|
51
85
|
# @param type [String, Symbol, SmartCore::Types::Primitive]
|
52
86
|
# @option cast [Boolean]
|
@@ -9,6 +9,18 @@ module SmartCore::Initializer
|
|
9
9
|
# @since 0.1.0
|
10
10
|
ArgumentError = Class.new(SmartCore::ArgumentError)
|
11
11
|
|
12
|
+
# @api public
|
13
|
+
# @since 0.1.0
|
14
|
+
ParameterArgumentError = Class.new(ArgumentError)
|
15
|
+
|
16
|
+
# @api public
|
17
|
+
# @since 0.1.0
|
18
|
+
OptionArgumentError = Class.new(ArgumentError)
|
19
|
+
|
20
|
+
# @api public
|
21
|
+
# @since 0.1.0
|
22
|
+
NoDefaultValueError = Class.new(Error)
|
23
|
+
|
12
24
|
# @api public
|
13
25
|
# @since 0.1.0
|
14
26
|
OptionOverlapError = Class.new(ArgumentError)
|
@@ -16,4 +28,8 @@ module SmartCore::Initializer
|
|
16
28
|
# @api public
|
17
29
|
# @since 0.1.0
|
18
30
|
ParameterOverlapError = Class.new(ArgumentError)
|
31
|
+
|
32
|
+
# @api public
|
33
|
+
# @since 0.1.0
|
34
|
+
NoTypeAliasError = Class.new(Error)
|
19
35
|
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.1.0
|
5
|
+
class SmartCore::Initializer::TypeAliasing::AliasList
|
6
|
+
# @return [void]
|
7
|
+
#
|
8
|
+
# @api private
|
9
|
+
# @since 0.1.0
|
10
|
+
def initialize
|
11
|
+
@list = {}
|
12
|
+
@lock = SmartCore::Engine::Lock.new
|
13
|
+
end
|
14
|
+
|
15
|
+
# @param alias_name [String, Symbol]
|
16
|
+
# @param type [SmartCore::Types::Primitive]
|
17
|
+
# @return [void]
|
18
|
+
#
|
19
|
+
# @api private
|
20
|
+
# @since 0.1.0
|
21
|
+
def associate(alias_name, type)
|
22
|
+
raise(
|
23
|
+
SmartCore::Initializer::ArgumentError,
|
24
|
+
'Type alias should be a type of string or symbol'
|
25
|
+
) unless alias_name.is_a?(String) || alias_name.is_a?(Symbol)
|
26
|
+
|
27
|
+
raise(
|
28
|
+
SmartCore::Initializer::ArgumentError,
|
29
|
+
'Type object should be a type of SmartCore::Types::Primitive'
|
30
|
+
) unless type.is_a?(SmartCore::Types::Primitive)
|
31
|
+
|
32
|
+
thread_safe { set_alias(alias_name, type) }
|
33
|
+
end
|
34
|
+
|
35
|
+
# @param alias_name [String, Symbol]
|
36
|
+
# @return [SmartCore::Types::Primitive]
|
37
|
+
#
|
38
|
+
# @api private
|
39
|
+
# @since 0.1.0
|
40
|
+
def resolve(alias_name)
|
41
|
+
raise(
|
42
|
+
SmartCore::Initializer::ArgumentError,
|
43
|
+
'Type alias should be a type of string or symbol'
|
44
|
+
) unless alias_name.is_a?(String) || alias_name.is_a?(Symbol)
|
45
|
+
|
46
|
+
thread_safe { get_alias(alias_name) }
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
# @return [Hash<String,SmartCore::Types::Primitive>]
|
52
|
+
#
|
53
|
+
# @api private
|
54
|
+
# @since 0.1.0
|
55
|
+
attr_reader :list
|
56
|
+
|
57
|
+
# @param block [Block]
|
58
|
+
# @return [Any]
|
59
|
+
#
|
60
|
+
# @api private
|
61
|
+
# @since 0.1.0
|
62
|
+
def thread_safe(&block)
|
63
|
+
@lock.synchronize(&block)
|
64
|
+
end
|
65
|
+
|
66
|
+
# @param alias_name [String, Symbol]
|
67
|
+
# @param type [SmartCore::Types::Primitive]
|
68
|
+
# @return [void]
|
69
|
+
#
|
70
|
+
# @api private
|
71
|
+
# @since 0.1.0
|
72
|
+
def set_alias(alias_name, type)
|
73
|
+
alias_name = normalized_alias(alias_name)
|
74
|
+
::Warning.warn( # TODO: SmartCore::Engine::Instrumenting
|
75
|
+
"[SmartCore::Initializer] Type alias with name \"#{alias_name}\"" \
|
76
|
+
' is already exists and shadowed by new type.'
|
77
|
+
) if list.key?(alias_name)
|
78
|
+
list[normalized_alias(alias_name)] = type
|
79
|
+
end
|
80
|
+
|
81
|
+
# @param alias_name [String, Symbol]
|
82
|
+
# @return [SmartCore::Types::Primitive]
|
83
|
+
#
|
84
|
+
# @api private
|
85
|
+
# @since 0.1.0
|
86
|
+
def get_alias(alias_name)
|
87
|
+
list.fetch(normalized_alias(alias_name)) do
|
88
|
+
raise(SmartCore::Initializer::NoTypeAliasError, <<~ERROR_MESSAGE)
|
89
|
+
Alias with name "#{alias_name}" does not exist
|
90
|
+
ERROR_MESSAGE
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# @param alias_name [String, Symbol]
|
95
|
+
# @return [String]
|
96
|
+
#
|
97
|
+
# @api private
|
98
|
+
# @since 0.1.0
|
99
|
+
def normalized_alias(alias_name)
|
100
|
+
alias_name.to_s
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.1.0
|
5
|
+
module SmartCore::Initializer::TypeAliasing
|
6
|
+
require_relative 'type_aliasing/alias_list'
|
7
|
+
|
8
|
+
class << self
|
9
|
+
# @param base_klass [Class]
|
10
|
+
# @return [void]
|
11
|
+
#
|
12
|
+
# @api private
|
13
|
+
# @since 0.1.0
|
14
|
+
def extended(base_klass)
|
15
|
+
base_klass.instance_variable_set(:@__type_aliases__, AliasList.new)
|
16
|
+
base_klass.extend(ClassMethods)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# @api private
|
21
|
+
# @since 0.1.0
|
22
|
+
module ClassMethods
|
23
|
+
# @return [SmartCore::Initializer::TypeAliasing::AliasList]
|
24
|
+
#
|
25
|
+
# @api private
|
26
|
+
# @since 0.1.0
|
27
|
+
def __type_aliases__
|
28
|
+
@__type_aliases__
|
29
|
+
end
|
30
|
+
|
31
|
+
# @param alias_name [String, Symbol]
|
32
|
+
# @param type [SmartCore::Types::Primitive]
|
33
|
+
# @return [void]
|
34
|
+
#
|
35
|
+
# @api public
|
36
|
+
# @since 0.1.0
|
37
|
+
def type_alias(alias_name, type)
|
38
|
+
__type_aliases__.associate(alias_name, type)
|
39
|
+
end
|
40
|
+
|
41
|
+
# @param alias_name [String, Symbol]
|
42
|
+
# @return [SmartCore::Types::Primitive]
|
43
|
+
#
|
44
|
+
# @api public
|
45
|
+
# @since 0.1.0
|
46
|
+
def type_from_alias(alias_name)
|
47
|
+
__type_aliases__.resolve(alias_name)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'smart_core'
|
4
4
|
require 'smart_core/types'
|
5
|
+
require 'forwardable'
|
5
6
|
|
6
7
|
# @api public
|
7
8
|
# @since 0.1.0
|
@@ -9,7 +10,12 @@ module SmartCore::Initializer
|
|
9
10
|
require_relative 'initializer/version'
|
10
11
|
require_relative 'initializer/errors'
|
11
12
|
require_relative 'initializer/attribute'
|
13
|
+
require_relative 'initializer/constructor'
|
12
14
|
require_relative 'initializer/dsl'
|
15
|
+
require_relative 'initializer/type_aliasing'
|
16
|
+
|
17
|
+
# @since 0.1.0
|
18
|
+
extend SmartCore::Initializer::TypeAliasing
|
13
19
|
|
14
20
|
class << self
|
15
21
|
# @param base_klass [Class]
|
@@ -18,7 +24,22 @@ module SmartCore::Initializer
|
|
18
24
|
# @api private
|
19
25
|
# @since 0.1.0
|
20
26
|
def included(base_klass)
|
21
|
-
base_klass.
|
27
|
+
base_klass.extend(SmartCore::Initializer::DSL)
|
22
28
|
end
|
23
29
|
end
|
30
|
+
|
31
|
+
type_alias(:nil, SmartCore::Types::Value::Nil)
|
32
|
+
type_alias(:string, SmartCore::Types::Value::String)
|
33
|
+
type_alias(:symbol, SmartCore::Types::Value::Symbol)
|
34
|
+
type_alias(:text, SmartCore::Types::Value::Text)
|
35
|
+
type_alias(:integer, SmartCore::Types::Value::Integer)
|
36
|
+
type_alias(:float, SmartCore::Types::Value::Float)
|
37
|
+
type_alias(:numeric, SmartCore::Types::Value::Numeric)
|
38
|
+
type_alias(:boolean, SmartCore::Types::Value::Boolean)
|
39
|
+
type_alias(:array, SmartCore::Types::Value::Array)
|
40
|
+
type_alias(:hash, SmartCore::Types::Value::Hash)
|
41
|
+
type_alias(:proc, SmartCore::Types::Value::Proc)
|
42
|
+
type_alias(:class, SmartCore::Types::Value::Class)
|
43
|
+
type_alias(:module, SmartCore::Types::Value::Module)
|
44
|
+
type_alias(:any, SmartCore::Types::Value::Any)
|
24
45
|
end
|
data/smart_initializer.gemspec
CHANGED
@@ -27,8 +27,8 @@ Gem::Specification.new do |spec|
|
|
27
27
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
28
28
|
spec.require_paths = ['lib']
|
29
29
|
|
30
|
-
spec.add_dependency 'smart_engine', '~> 0.
|
31
|
-
spec.add_dependency 'smart_types', '~> 0.1.0.
|
30
|
+
spec.add_dependency 'smart_engine', '~> 0.5'
|
31
|
+
spec.add_dependency 'smart_types', '~> 0.1.0.alpha4'
|
32
32
|
|
33
33
|
spec.add_development_dependency 'bundler', '~> 2.1'
|
34
34
|
spec.add_development_dependency 'rake', '~> 13.0'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: smart_initializer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.1.0.alpha1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rustam Ibragimov
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-01-
|
11
|
+
date: 2020-01-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: smart_engine
|
@@ -16,28 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '0.
|
19
|
+
version: '0.5'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '0.
|
26
|
+
version: '0.5'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: smart_types
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 0.1.0.
|
33
|
+
version: 0.1.0.alpha4
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 0.1.0.
|
40
|
+
version: 0.1.0.alpha4
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: bundler
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -133,12 +133,17 @@ files:
|
|
133
133
|
- lib/smart_core/initializer/attribute/definer.rb
|
134
134
|
- lib/smart_core/initializer/attribute/factory.rb
|
135
135
|
- lib/smart_core/initializer/attribute/finalizer.rb
|
136
|
+
- lib/smart_core/initializer/attribute/finalizer/abstract.rb
|
136
137
|
- lib/smart_core/initializer/attribute/finalizer/anonymous_block.rb
|
137
138
|
- lib/smart_core/initializer/attribute/finalizer/instance_method.rb
|
138
139
|
- lib/smart_core/initializer/attribute/list.rb
|
139
140
|
- lib/smart_core/initializer/attribute/parameters.rb
|
141
|
+
- lib/smart_core/initializer/constructor.rb
|
140
142
|
- lib/smart_core/initializer/dsl.rb
|
143
|
+
- lib/smart_core/initializer/dsl/inheritance.rb
|
141
144
|
- lib/smart_core/initializer/errors.rb
|
145
|
+
- lib/smart_core/initializer/type_aliasing.rb
|
146
|
+
- lib/smart_core/initializer/type_aliasing/alias_list.rb
|
142
147
|
- lib/smart_core/initializer/version.rb
|
143
148
|
- smart_initializer.gemspec
|
144
149
|
homepage: https://github.com/smart-rb/smart_initialier
|
@@ -159,9 +164,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
159
164
|
version: 2.4.9
|
160
165
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
161
166
|
requirements:
|
162
|
-
- - "
|
167
|
+
- - ">"
|
163
168
|
- !ruby/object:Gem::Version
|
164
|
-
version:
|
169
|
+
version: 1.3.1
|
165
170
|
requirements: []
|
166
171
|
rubygems_version: 3.1.2
|
167
172
|
signing_key:
|