smart_initializer 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.rspec +3 -0
- data/.rubocop.yml +19 -0
- data/.travis.yml +20 -0
- data/CHANGELOG.md +2 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +80 -0
- data/LICENSE.txt +21 -0
- data/README.md +55 -0
- data/Rakefile +21 -0
- data/bin/console +8 -0
- data/bin/setup +8 -0
- data/lib/smart_core/initializer.rb +24 -0
- data/lib/smart_core/initializer/attribute.rb +68 -0
- data/lib/smart_core/initializer/attribute/definer.rb +180 -0
- data/lib/smart_core/initializer/attribute/factory.rb +140 -0
- data/lib/smart_core/initializer/attribute/finalizer.rb +37 -0
- data/lib/smart_core/initializer/attribute/finalizer/anonymous_block.rb +32 -0
- data/lib/smart_core/initializer/attribute/finalizer/instance_method.rb +32 -0
- data/lib/smart_core/initializer/attribute/list.rb +64 -0
- data/lib/smart_core/initializer/attribute/parameters.rb +97 -0
- data/lib/smart_core/initializer/dsl.rb +110 -0
- data/lib/smart_core/initializer/errors.rb +19 -0
- data/lib/smart_core/initializer/version.rb +11 -0
- data/smart_initializer.gemspec +38 -0
- metadata +170 -0
@@ -0,0 +1,180 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.1.0
|
5
|
+
class SmartCore::Initializer::Attribute::Definer
|
6
|
+
# @param klass [Class]
|
7
|
+
# @return [void]
|
8
|
+
#
|
9
|
+
# @api private
|
10
|
+
# @since 0.1.0
|
11
|
+
def initialize(klass)
|
12
|
+
@klass = klass
|
13
|
+
@lock = SmartCore::Engine::Lock.new
|
14
|
+
end
|
15
|
+
|
16
|
+
# @param name [String, Symbol]
|
17
|
+
# @param type [String, Symbol, SmartCore::Types::Primitive]
|
18
|
+
# @param privacy [String, Symbol]
|
19
|
+
# @param finalize [String, Symbol, Proc]
|
20
|
+
# @param cast [Boolean]
|
21
|
+
# @param dynamic_options [Hash<Symbol,Any>]
|
22
|
+
# @return [void]
|
23
|
+
#
|
24
|
+
# @api private
|
25
|
+
# @since 0.1.0
|
26
|
+
def define_parameter(name, type, privacy, finalize, cast, dynamic_options)
|
27
|
+
thread_safe do
|
28
|
+
attribute = build_attribute(name, type, privacy, finalize, cast, dynamic_options)
|
29
|
+
prevent_option_overlap(attribute)
|
30
|
+
add_parameter(attribute)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# @param names [Array<String, Symbol>]
|
35
|
+
# @return [void]
|
36
|
+
#
|
37
|
+
# @api private
|
38
|
+
# @since 0.1.0
|
39
|
+
def define_parameters(*names)
|
40
|
+
thread_safe do
|
41
|
+
names.map do |name|
|
42
|
+
build_attribute(
|
43
|
+
name,
|
44
|
+
SmartCore::Types::Any,
|
45
|
+
SmartCore::Initializer::Attribute::Parameters::DEFAULT_PRIVACY_MODE,
|
46
|
+
SmartCore::Initializer::Attribute::Parameters::DEFAULT_FINALIZER,
|
47
|
+
SmartCore::Initializer::Attribute::Parameters::DEFAULT_CAST_BEHAVIOUR,
|
48
|
+
SmartCore::Initializer::Attribute::Parameters::DEFAULT_DYNAMIC_OPTIONS.dup
|
49
|
+
).tap do |attribute|
|
50
|
+
prevent_option_overlap(attribute)
|
51
|
+
end
|
52
|
+
end.each do |attribute|
|
53
|
+
add_parameter(attribute)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# @param name [String, Symbol]
|
59
|
+
# @param type [String, Symbol, SmartCore::Types::Primitive]
|
60
|
+
# @param privacy [String, Symbol]
|
61
|
+
# @param finalize [String, Symbol, Proc]
|
62
|
+
# @param cast [Boolean]
|
63
|
+
# @param dynamic_options [Hash<Symbol,Any>]
|
64
|
+
# @return [void]
|
65
|
+
#
|
66
|
+
# @api private
|
67
|
+
# @since 0.1.0
|
68
|
+
def define_option(name, type, privacy, finalize, cast, dynamic_options)
|
69
|
+
thread_safe do
|
70
|
+
attribute = build_attribute(name, type, privacy, finalize, cast, dynamic_options)
|
71
|
+
prevent_parameter_overlap(attribute)
|
72
|
+
add_option(attribute)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# @param names [Array<String, Symbol>]
|
77
|
+
# @return [void]
|
78
|
+
#
|
79
|
+
# @api private
|
80
|
+
# @since 0.1.0
|
81
|
+
def define_options(*names)
|
82
|
+
thread_safe do
|
83
|
+
names.map do |name|
|
84
|
+
build_attribute(
|
85
|
+
name,
|
86
|
+
SmartCore::Types::Any,
|
87
|
+
SmartCore::Initializer::Attribute::Parameters::DEFAULT_PRIVACY_MODE,
|
88
|
+
SmartCore::Initializer::Attribute::Parameters::DEFAULT_FINALIZER,
|
89
|
+
SmartCore::Initializer::Attribute::Parameters::DEFAULT_CAST_BEHAVIOUR,
|
90
|
+
SmartCore::Initializer::Attribute::Parameters::DEFAULT_DYNAMIC_OPTIONS.dup
|
91
|
+
).tap do |attribute|
|
92
|
+
prevent_parameter_overlap(attribute)
|
93
|
+
end
|
94
|
+
end.each do |attribute|
|
95
|
+
add_option(attribute)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
|
102
|
+
# @return [Class]
|
103
|
+
#
|
104
|
+
# @api private
|
105
|
+
# @since 0.1.0
|
106
|
+
attr_reader :klass
|
107
|
+
|
108
|
+
# @param name [String, Symbol]
|
109
|
+
# @param type [String, Symbol, SmartCore::Types::Primitive]
|
110
|
+
# @param privacy [String, Symbol]
|
111
|
+
# @param finalize [String, Symbol, Proc]
|
112
|
+
# @param cast [Boolean]
|
113
|
+
# @param dynamic_options [Hash<Symbol,Any>]
|
114
|
+
# @return [SmartCore::Initializer::Attribute]
|
115
|
+
#
|
116
|
+
# @api private
|
117
|
+
# @since 0.1.0
|
118
|
+
def build_attribute(name, type, privacy, finalize, cast, dynamic_options)
|
119
|
+
SmartCore::Initializer::Attribute::Factory.create(
|
120
|
+
name, type, privacy, finalize, cast, dynamic_options
|
121
|
+
)
|
122
|
+
end
|
123
|
+
|
124
|
+
# @param parameter [SmartCore::Initializer::Attribute]
|
125
|
+
# @return [void]
|
126
|
+
#
|
127
|
+
# @api private
|
128
|
+
# @since 0.1.0
|
129
|
+
def add_parameter(parameter)
|
130
|
+
klass.__params__ << parameter
|
131
|
+
klass.send(:attr_reader, parameter.name)
|
132
|
+
klass.send(parameter.privacy, parameter.name)
|
133
|
+
end
|
134
|
+
|
135
|
+
# @param option [SmartCore::Initializer::Attribute]
|
136
|
+
# @return [void]
|
137
|
+
#
|
138
|
+
# @api private
|
139
|
+
# @since 0.1.0
|
140
|
+
def add_option(option)
|
141
|
+
klass.__options__ << option
|
142
|
+
klass.send(:attr_reader, option.name)
|
143
|
+
klass.send(option.privacy, option.name)
|
144
|
+
end
|
145
|
+
|
146
|
+
# @param parameter [SmartCore::Initializer::Attribute]
|
147
|
+
# @return [void]
|
148
|
+
#
|
149
|
+
# @api private
|
150
|
+
# @since 0.1.0
|
151
|
+
def prevent_option_overlap(parameter)
|
152
|
+
if klass.__options__.include?(parameter)
|
153
|
+
raise(SmartCore::Initializer::OptionOverlapError, <<~ERROR_MESSAGE)
|
154
|
+
You have already defined option with name :#{parameter.name}
|
155
|
+
ERROR_MESSAGE
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
# @param option [SmartCore::Initializer::Attribute]
|
160
|
+
# @return [void]
|
161
|
+
#
|
162
|
+
# @api private
|
163
|
+
# @since 0.1.0
|
164
|
+
def prevent_parameter_overlap(option)
|
165
|
+
if klass.__params__.include?(option)
|
166
|
+
raise(SmartCore::Initializer::ParameterOverlapError, <<~ERROR_MESSAGE)
|
167
|
+
You have already defined parameter with name :#{option.name}
|
168
|
+
ERROR_MESSAGE
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
# @param block [Block]
|
173
|
+
# @return [Any]
|
174
|
+
#
|
175
|
+
# @api private
|
176
|
+
# @since 0.1.0
|
177
|
+
def thread_safe(&block)
|
178
|
+
@lock.synchronize(&block)
|
179
|
+
end
|
180
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.1.0
|
5
|
+
class SmartCore::Initializer::Attribute::Factory
|
6
|
+
class << self
|
7
|
+
# @param name [String, Symbol]
|
8
|
+
# @param type [String, Symbol, SmartCore::Types::Primitive]
|
9
|
+
# @param privacy [String, Symbol]
|
10
|
+
# @param finalize [String, Symbol, Proc]
|
11
|
+
# @param cast [Boolean]
|
12
|
+
# @param dynamic_options [Hash<Symbol,Any>]
|
13
|
+
# @return [SmartCore::Initializer::Attribute]
|
14
|
+
#
|
15
|
+
# @api private
|
16
|
+
# @since 0.1.0
|
17
|
+
def create(name, type, privacy, finalize, cast, dynamic_options)
|
18
|
+
name = prepare_name_param(name)
|
19
|
+
type = prepare_type_param(type)
|
20
|
+
privacy = prepare_privacy_param(privacy)
|
21
|
+
finalize = prepare_finalize_param(finalize)
|
22
|
+
cast = prepare_cast_param(cast)
|
23
|
+
dynamic_options = prepare_dynamic_options_param(dynamic_options)
|
24
|
+
|
25
|
+
create_attribute(name, type, privacy, finalize, cast, dynamic_options)
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
# @param name [String, Symbol]
|
31
|
+
# @return [String]
|
32
|
+
#
|
33
|
+
# @api private
|
34
|
+
# @since 0.1.0
|
35
|
+
def prepare_name_param(name)
|
36
|
+
unless name.is_a?(String) || name.is_a?(Symbol)
|
37
|
+
raise(SmartCore::Initializer::ArgumentError, <<~ERROR_MESSAGE)
|
38
|
+
Attribute name should be a type of String or Symbol
|
39
|
+
ERROR_MESSAGE
|
40
|
+
end
|
41
|
+
|
42
|
+
name.to_s
|
43
|
+
end
|
44
|
+
|
45
|
+
# @param type [String, Symbol, SmartCore::Types::Primitive]
|
46
|
+
# @return [SmartCore::Types::Primitive]
|
47
|
+
#
|
48
|
+
# @api private
|
49
|
+
# @since 0.1.0
|
50
|
+
def prepare_type_param(type)
|
51
|
+
unless type.is_a?(String) || type.is_a?(Symbol) || type.is_a?(SmartCore::Types::Primitive)
|
52
|
+
raise(SmartCore::Initializer::ArgumentError, <<~ERROR_MESSAGE)
|
53
|
+
Attribute type should be a type of String, Symbol or SmartCore::Types::Primitive
|
54
|
+
ERROR_MESSAGE
|
55
|
+
end
|
56
|
+
|
57
|
+
type
|
58
|
+
end
|
59
|
+
|
60
|
+
# @param cast [Boolean]
|
61
|
+
# @return [Boolean]
|
62
|
+
#
|
63
|
+
# @api private
|
64
|
+
# @since 0.1.0
|
65
|
+
def prepare_cast_param(cast)
|
66
|
+
unless cast.is_a?(TrueClass) || cast.is_a?(FalseClass)
|
67
|
+
raise(SmartCore::Initializer::ArgumentError, <<~ERROR_MESSAGE)
|
68
|
+
Attribute cast should be a type of boolean
|
69
|
+
ERROR_MESSAGE
|
70
|
+
end
|
71
|
+
|
72
|
+
cast
|
73
|
+
end
|
74
|
+
|
75
|
+
# @param privacy [String, Symbol]
|
76
|
+
# @return [Symbol]
|
77
|
+
#
|
78
|
+
# @api private
|
79
|
+
# @since 0.1.0
|
80
|
+
def prepare_privacy_param(privacy)
|
81
|
+
unless privacy.is_a?(String) || privacy.is_a?(Symbol)
|
82
|
+
raise(SmartCore::Initializer::ArgumentError, <<~ERROR_MESSAGE)
|
83
|
+
Attribute privacy should be a type of String or Symbol
|
84
|
+
ERROR_MESSAGE
|
85
|
+
end
|
86
|
+
|
87
|
+
SmartCore::Initializer::Attribute::Parameters::PRIVACY_MODES.fetch(privacy.to_sym) do
|
88
|
+
raise(SmartCore::Initializer::ArgumentError, <<~ERROR_MESSAGE)
|
89
|
+
Incorrect attribute privacy identifier "#{privacy}"
|
90
|
+
ERROR_MESSAGE
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# @param finalize [String, Symbol, Proc]
|
95
|
+
# @return [SmartCore::Initializer::Attribute::Finalizer::AnonymousBlock/InstanceMethod]
|
96
|
+
#
|
97
|
+
# @api private
|
98
|
+
# @since 0.1.0
|
99
|
+
def prepare_finalize_param(finalize)
|
100
|
+
unless finalize.is_a?(String) || finalize.is_a?(Symbol) || finalize.is_a?(Proc)
|
101
|
+
raise(SmartCore::Initializer::ArgumentError, <<~ERROR_MESSAGE)
|
102
|
+
Attribute finalizer should be a type of String, Symbol or Proc
|
103
|
+
ERROR_MESSAGE
|
104
|
+
end
|
105
|
+
|
106
|
+
SmartCore::Initializer::Attribute::Finalizer.create(finalize)
|
107
|
+
end
|
108
|
+
|
109
|
+
# @param dynamic_options [Hash<Symbol,Any>]
|
110
|
+
# @return [Hash<Symbol,Any>]
|
111
|
+
#
|
112
|
+
# @api private
|
113
|
+
# @since 0.1.0
|
114
|
+
def prepare_dynamic_options_param(dynamic_options)
|
115
|
+
# :nocov:
|
116
|
+
unless dynamic_options.is_a?(Hash)
|
117
|
+
raise(SmartCore::Initializer::ArgumentError, <<~ERROR_MESSAGE)
|
118
|
+
Attribute dynamic options should be a type of Hash
|
119
|
+
ERROR_MESSAGE
|
120
|
+
end
|
121
|
+
# :nocov:
|
122
|
+
|
123
|
+
dynamic_options
|
124
|
+
end
|
125
|
+
|
126
|
+
# @param name [String]
|
127
|
+
# @param type [SmartCore::Types::Primitive]
|
128
|
+
# @param privacy [Symbol]
|
129
|
+
# @param finalize [SmartCore::Initializer::Attribute::Finalizer::AnonymousBlock/InstanceMethod]
|
130
|
+
# @param cast [Boolean]
|
131
|
+
# @param dynamic_options [Hash<Symbol,String>]
|
132
|
+
# @return [SmartCore::Initializer::Attribute]
|
133
|
+
#
|
134
|
+
# @api private
|
135
|
+
# @since 0.1.0
|
136
|
+
def create_attribute(name, type, privacy, finalize, cast, dynamic_options)
|
137
|
+
SmartCore::Initializer::Attribute.new(name, type, privacy, finalize, cast, dynamic_options)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.1.0
|
5
|
+
module SmartCore::Initializer::Attribute::Finalizer
|
6
|
+
require_relative 'finalizer/instance_method'
|
7
|
+
require_relative 'finalizer/anonymous_block'
|
8
|
+
|
9
|
+
# @return [Proc]
|
10
|
+
#
|
11
|
+
# @api private
|
12
|
+
# @since 0.1.0
|
13
|
+
DEFAULT_FINALIZER = proc { |value| value }.freeze
|
14
|
+
|
15
|
+
class << self
|
16
|
+
# @param finalization_approach [String, Symbol, Proc]
|
17
|
+
# @return [SmartCore::Initializer::Attribute::Finalizer::InstanceMethod]
|
18
|
+
# @return [SmartCore::Initializer::Attribute::Finalizer::AnonymousBlock]
|
19
|
+
#
|
20
|
+
# @api private
|
21
|
+
# @since 0.1.0
|
22
|
+
def create(finalization_approach)
|
23
|
+
case finalization_approach
|
24
|
+
when String, Symbol
|
25
|
+
InstanceMethod.new(finalization_approach)
|
26
|
+
when Proc
|
27
|
+
AnonymousBlock.new(finalization_approach)
|
28
|
+
else
|
29
|
+
# :nocov:
|
30
|
+
raise(SmartCore::Initializer::ArgumentError, <<~ERROR_MESSAGE)
|
31
|
+
Finalization approach should be a type of Proc, Symbol or String'
|
32
|
+
ERROR_MESSAGE
|
33
|
+
# :nocov:
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
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
|
+
#
|
19
|
+
# @pai private
|
20
|
+
# @since 0.1.0
|
21
|
+
def call(value, instance)
|
22
|
+
instance.instance_exec(value, &finalizer)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
# @return [NilClass, Any]
|
28
|
+
#
|
29
|
+
# @api private
|
30
|
+
# @since 0.1.0
|
31
|
+
attr_reader :finalizer
|
32
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
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
|
+
#
|
19
|
+
# @pai private
|
20
|
+
# @since 0.1.0
|
21
|
+
def call(value, instance)
|
22
|
+
instance.send(finalizer, value)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
# @return [NilClass, Any]
|
28
|
+
#
|
29
|
+
# @api private
|
30
|
+
# @since 0.1.0
|
31
|
+
attr_reader :finalizer
|
32
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.1.0
|
5
|
+
class SmartCore::Initializer::Attribute::List
|
6
|
+
# @since 0.1.0
|
7
|
+
include Enumerable
|
8
|
+
|
9
|
+
# @return [void]
|
10
|
+
#
|
11
|
+
# @api private
|
12
|
+
# @since 0.1.0
|
13
|
+
def initialize
|
14
|
+
@attributes = {}
|
15
|
+
@lock = SmartCore::Engine::Lock.new
|
16
|
+
end
|
17
|
+
|
18
|
+
# @param attribute [SmartCore::Initializer::Attribute]
|
19
|
+
# @return [void]
|
20
|
+
#
|
21
|
+
# @api private
|
22
|
+
# @since 0.1.0
|
23
|
+
def add(attribute)
|
24
|
+
thread_safe { attributes[attribute.name] = attribute }
|
25
|
+
end
|
26
|
+
alias_method :<<, :add
|
27
|
+
|
28
|
+
# @param attribute [SmartCore::Initializer::Attribute]
|
29
|
+
# @return [void]
|
30
|
+
#
|
31
|
+
# @api private
|
32
|
+
# @since 0.1.0
|
33
|
+
def include?(attribute)
|
34
|
+
thread_safe { attributes.key?(attribute.name) }
|
35
|
+
end
|
36
|
+
|
37
|
+
# @param block [Block]
|
38
|
+
# @return [Enumerable]
|
39
|
+
#
|
40
|
+
# @api private
|
41
|
+
# @since 0.1.0
|
42
|
+
def each(&block)
|
43
|
+
thread_safe do
|
44
|
+
block_given? ? attributes.values.each(&block) : attributes.values.each
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
# @return [Hash<String,SmartCore::Initializer::Attribute>]
|
51
|
+
#
|
52
|
+
# @api private
|
53
|
+
# @since 0.1.0
|
54
|
+
attr_reader :attributes
|
55
|
+
|
56
|
+
# @param block [Block]
|
57
|
+
# @return [Any]
|
58
|
+
#
|
59
|
+
# @api private
|
60
|
+
# @since 0.1.0
|
61
|
+
def thread_safe(&block)
|
62
|
+
@lock.synchronize(&block)
|
63
|
+
end
|
64
|
+
end
|