smart_initializer 0.0.0 → 0.1.0.alpha1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d1b4aa0c7cf388c9c8850de3e66fd99ff3d71089c9124fa3171021b9ac4bdf55
4
- data.tar.gz: bf210ab1832172055ea2161f4768880f771cb16a9caecd4fcca3ee1435173061
3
+ metadata.gz: cd7d1a7f5aa327457a601a1b1a0110d8178e6bd83b557a53365e0cf96d336080
4
+ data.tar.gz: 1487df01e94537cf79292f293f525f9ecde081edb0438e61d9674c7b2ac2cf6b
5
5
  SHA512:
6
- metadata.gz: 559533da54f15b415903c2ff29f52195b5679e7a1e38e2d7670f7694a08d4d65d1a427b5aab2315939edc6a56daed0f9a1b51f644826cf11a921e571d0901b46
7
- data.tar.gz: 5b7d885e1ded34497140189aa8fb0247324232cc3fababd59cfea2516163c8fda37b4aa25e2e649ed3a344a017ec9233d84c2144b274c2b58380703f5428169c
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.4)
6
- smart_types (~> 0.1.0.alpha)
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.4.0)
64
- smart_types (0.1.0.alpha)
65
- smart_engine (~> 0.4)
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, privacy, finalize, cast, dynamic_options)
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 [String]
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.to_s
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
- # @pai private
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
- def call(value, instance)
22
- instance.instance_exec(value, &finalizer)
23
- end
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
- private
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
- # @return [NilClass, Any]
28
- #
29
- # @api private
30
- # @since 0.1.0
31
- attr_reader :finalizer
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
- # @pai private
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
- def call(value, instance)
22
- instance.send(finalizer, value)
23
- end
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
- private
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
- # @return [NilClass, Any]
28
- #
29
- # @api private
30
- # @since 0.1.0
31
- attr_reader :finalizer
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 [String]
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
- # @param name [String]
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
- private
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 [Hash<Symbol,Any>]
106
+ # @return [Any]
107
+ #
108
+ # @raise [SmartCore::Initializer::NoDefaultValueError]
93
109
  #
94
110
  # @api private
95
111
  # @since 0.1.0
96
- attr_reader :dynamic_options
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
- # @retirn [String]
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
- # @retirn [SmartCore::Types::Primitive]
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
- # @retirn [Symbol]
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
- # @retirn [SmartCore::Initializer::Attribute::Finalizer::AnonymousBlock/InstanceMethod]
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
- # @retirn [Boolean]
39
+ # @return [Boolean]
40
40
  #
41
+ # @pai private
41
42
  # @since 0.1.0
42
- # @version 0.1.0
43
- def_delegator :parameters, :cast
43
+ def_delegators :parameters, :cast, :cast?
44
44
 
45
- # @param name [String]
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 included(base_klass)
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
@@ -6,6 +6,6 @@ module SmartCore
6
6
  #
7
7
  # @api public
8
8
  # @since 0.1.0
9
- VERSION = '0.0.0'
9
+ VERSION = '0.1.0.alpha1'
10
10
  end
11
11
  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.include(SmartCore::Initializer::DSL)
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
@@ -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.4'
31
- spec.add_dependency 'smart_types', '~> 0.1.0.alpha'
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.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-21 00:00:00.000000000 Z
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.4'
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.4'
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.alpha
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.alpha
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: '0'
169
+ version: 1.3.1
165
170
  requirements: []
166
171
  rubygems_version: 3.1.2
167
172
  signing_key: