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 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: