smart_core 0.4.0 → 0.5.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 +4 -4
- data/.rubocop.yml +2 -2
- data/.travis.yml +3 -3
- data/CHANGELOG.md +3 -0
- data/Gemfile +0 -3
- data/README.md +5 -33
- data/Rakefile +2 -0
- data/lib/smart_core/container/command_definer.rb +117 -0
- data/lib/smart_core/container/command_set.rb +82 -0
- data/lib/smart_core/container/commands/base.rb +12 -0
- data/lib/smart_core/container/commands/namespace.rb +53 -0
- data/lib/smart_core/container/commands/register.rb +63 -0
- data/lib/smart_core/container/commands.rb +9 -0
- data/lib/smart_core/container/definition_dsl.rb +66 -0
- data/lib/smart_core/container/dependency.rb +44 -0
- data/lib/smart_core/container/dependency_builder.rb +48 -0
- data/lib/smart_core/container/dependency_compatability/abstract.rb +59 -0
- data/lib/smart_core/container/dependency_compatability/command_set.rb +35 -0
- data/lib/smart_core/container/dependency_compatability/registry.rb +37 -0
- data/lib/smart_core/container/dependency_compatability.rb +9 -0
- data/lib/smart_core/container/dependency_resolver.rb +16 -0
- data/lib/smart_core/container/entity.rb +26 -0
- data/lib/smart_core/container/exceptions.rb +31 -0
- data/lib/smart_core/container/key_guard.rb +31 -0
- data/lib/smart_core/container/memoized_dependency.rb +28 -0
- data/lib/smart_core/container/mixin.rb +82 -0
- data/lib/smart_core/container/namespace.rb +51 -0
- data/lib/smart_core/container/registry.rb +227 -0
- data/lib/smart_core/container/registry_builder.rb +18 -0
- data/lib/smart_core/container.rb +123 -0
- data/lib/smart_core/exceptions.rb +23 -0
- data/lib/smart_core/initializer/attribute/builder.rb +99 -0
- data/lib/smart_core/initializer/attribute/value_finalizer/lambda.rb +32 -0
- data/lib/smart_core/initializer/attribute/value_finalizer/method.rb +32 -0
- data/lib/smart_core/initializer/attribute/value_finalizer.rb +24 -0
- data/lib/smart_core/initializer/attribute.rb +123 -0
- data/lib/smart_core/initializer/attribute_definer.rb +162 -0
- data/lib/smart_core/{operation → initializer}/attribute_set.rb +17 -17
- data/lib/smart_core/initializer/exceptions.rb +47 -0
- data/lib/smart_core/initializer/extension.rb +39 -0
- data/lib/smart_core/initializer/extension_definer.rb +62 -0
- data/lib/smart_core/initializer/extension_set.rb +75 -0
- data/lib/smart_core/{operation → initializer}/initialization_dsl.rb +82 -42
- data/lib/smart_core/initializer/instance_attribute_accessing.rb +49 -0
- data/lib/smart_core/initializer/instance_builder.rb +164 -0
- data/lib/smart_core/initializer/type.rb +49 -0
- data/lib/smart_core/initializer/type_set.rb +52 -0
- data/lib/smart_core/initializer.rb +89 -0
- data/lib/smart_core/injector.rb +6 -0
- data/lib/smart_core/operation/exceptions.rb +4 -20
- data/lib/smart_core/operation/instance_builder.rb +16 -124
- data/lib/smart_core/operation/state.rb +7 -0
- data/lib/smart_core/operation/step.rb +43 -0
- data/lib/smart_core/operation/step_set.rb +73 -0
- data/lib/smart_core/operation/success.rb +11 -0
- data/lib/smart_core/operation.rb +10 -12
- data/lib/smart_core/schema.rb +6 -0
- data/lib/smart_core/validator/commands.rb +2 -0
- data/lib/smart_core/validator/exceptions.rb +1 -1
- data/lib/smart_core/version.rb +1 -1
- data/lib/smart_core.rb +5 -0
- data/smart_core.gemspec +14 -14
- metadata +57 -15
- data/lib/smart_core/operation/attribute.rb +0 -66
- data/lib/smart_core/operation/attribute_definer.rb +0 -160
@@ -0,0 +1,123 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api public
|
4
|
+
# @since 0.5.0
|
5
|
+
class SmartCore::Container
|
6
|
+
require_relative 'container/exceptions'
|
7
|
+
require_relative 'container/commands'
|
8
|
+
require_relative 'container/command_set'
|
9
|
+
require_relative 'container/key_guard'
|
10
|
+
require_relative 'container/entity'
|
11
|
+
require_relative 'container/dependency'
|
12
|
+
require_relative 'container/memoized_dependency'
|
13
|
+
require_relative 'container/namespace'
|
14
|
+
require_relative 'container/dependency_builder'
|
15
|
+
require_relative 'container/registry'
|
16
|
+
require_relative 'container/registry_builder'
|
17
|
+
require_relative 'container/dependency_compatability'
|
18
|
+
require_relative 'container/dependency_resolver'
|
19
|
+
require_relative 'container/definition_dsl'
|
20
|
+
require_relative 'container/mixin'
|
21
|
+
|
22
|
+
# TODO: container composition
|
23
|
+
# TODO: #merge / #merge!
|
24
|
+
|
25
|
+
# @since 0.5.0
|
26
|
+
include DefinitionDSL
|
27
|
+
|
28
|
+
# @return [void]
|
29
|
+
#
|
30
|
+
# @api public
|
31
|
+
# @since 0.5.0
|
32
|
+
def initialize
|
33
|
+
build_registry
|
34
|
+
@access_lock = Mutex.new
|
35
|
+
end
|
36
|
+
|
37
|
+
# @param dependency_name [String, Symbol]
|
38
|
+
# @param options [Hash<Symbol,Any>]
|
39
|
+
# @param dependency_definition [Block]
|
40
|
+
# @return [void]
|
41
|
+
#
|
42
|
+
# @todo option list
|
43
|
+
#
|
44
|
+
# @api public
|
45
|
+
# @since 0.5.0
|
46
|
+
def register(dependency_name, **options, &dependency_definition)
|
47
|
+
thread_safe do
|
48
|
+
registry.register(dependency_name, **options, &dependency_definition)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# @return [void]
|
53
|
+
#
|
54
|
+
# @api public
|
55
|
+
# @since 0.5.0
|
56
|
+
def freeze
|
57
|
+
thread_safe { registry.freeze }
|
58
|
+
end
|
59
|
+
|
60
|
+
# @return [Boolean]
|
61
|
+
#
|
62
|
+
# @api public
|
63
|
+
# @since 0.5.0
|
64
|
+
def frozen?
|
65
|
+
thread_safe { registry.frozen? }
|
66
|
+
end
|
67
|
+
|
68
|
+
# @param namespace_name [String, Symbol]
|
69
|
+
# @param dependency_definitions [Block]
|
70
|
+
# @return [void]
|
71
|
+
#
|
72
|
+
# @api public
|
73
|
+
# @since 0.5.0
|
74
|
+
def namespace(namespace_name, &dependency_definitions)
|
75
|
+
thread_safe do
|
76
|
+
registry.namespace(namespace_name, &dependency_definitions)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# @param dependency_path [String, Symbol]
|
81
|
+
# @return [Any]
|
82
|
+
#
|
83
|
+
# @api public
|
84
|
+
# @since 0.5.0
|
85
|
+
def resolve(dependency_path)
|
86
|
+
thread_safe do
|
87
|
+
DependencyResolver.resolve(registry, dependency_path)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# @return [void]
|
92
|
+
#
|
93
|
+
# @api public
|
94
|
+
# @since 0.5.0
|
95
|
+
def reload!
|
96
|
+
thread_safe { build_registry }
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
# @return [SmartCore::Container::Registry]
|
102
|
+
#
|
103
|
+
# @api private
|
104
|
+
# @since 0.5.0
|
105
|
+
attr_reader :registry
|
106
|
+
|
107
|
+
# @return [void]
|
108
|
+
#
|
109
|
+
# @api private
|
110
|
+
# @since 0.5.0
|
111
|
+
def build_registry
|
112
|
+
@registry = RegistryBuilder.build(self.class.__commands__)
|
113
|
+
end
|
114
|
+
|
115
|
+
# @param block [Proc]
|
116
|
+
# @return [Any]
|
117
|
+
#
|
118
|
+
# @api private
|
119
|
+
# @since 0.5.0
|
120
|
+
def thread_safe(&block)
|
121
|
+
@access_lock.synchronize(&block)
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SmartCore
|
4
|
+
# @api public
|
5
|
+
# @since 0.5.0
|
6
|
+
Error = Class.new(StandardError)
|
7
|
+
|
8
|
+
# @api public
|
9
|
+
# @since 0.5.0
|
10
|
+
ArgumentError = Class.new(::ArgumentError)
|
11
|
+
|
12
|
+
# @api public
|
13
|
+
# @since 0.5.0
|
14
|
+
FrozenError = begin # rubocop:disable Naming/ConstantName
|
15
|
+
# :nocov:
|
16
|
+
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.5.0')
|
17
|
+
Class.new(::FrozenError)
|
18
|
+
else
|
19
|
+
Class.new(::RuntimeError)
|
20
|
+
end
|
21
|
+
# :nocov:
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.5.0
|
5
|
+
class SmartCore::Initializer::Attribute
|
6
|
+
module Builder
|
7
|
+
class << self
|
8
|
+
# @return [Proc]
|
9
|
+
#
|
10
|
+
# @api private
|
11
|
+
# @since 0.5.0
|
12
|
+
DEFAULT_FINALIZE = -> (value) { value }.freeze
|
13
|
+
|
14
|
+
# @param name [String, Symbol]
|
15
|
+
# @option type [Symbol]
|
16
|
+
# @option privacy [Symbol, String]
|
17
|
+
# @param options [Hash<Symbol,Any>]
|
18
|
+
# - :default (see SmartCore::Initializer::Attribute#initialize)
|
19
|
+
# - :finalize (see SmartCore::Initializer::Attribute#initialize)
|
20
|
+
# @return [SmartCore::Initializer::Attribute]
|
21
|
+
#
|
22
|
+
# @raise [SmartCore::Initializer::IncorrectAttributeNameError]
|
23
|
+
# @raise [SmartCore::Initializer::UnregisteredTypeError]
|
24
|
+
# @raise [SmartCore::Initializer::AttributeError]
|
25
|
+
#
|
26
|
+
# @api private
|
27
|
+
# @since 0.5.0
|
28
|
+
def build(name, type: :__any__, privacy: :default, finalize: DEFAULT_FINALIZE, **options)
|
29
|
+
name = represent_name_attr(name)
|
30
|
+
type = represent_type_attr(type)
|
31
|
+
privacy = represent_privacy_attr(privacy)
|
32
|
+
finalizer = represent_finalizer_attr(finalize)
|
33
|
+
|
34
|
+
SmartCore::Initializer::Attribute.new(name, type, privacy, finalizer, **options)
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
# @param finalize [Proc, String, Symbol]
|
40
|
+
# @return [SmartCore::Initializer::Attribute::ValueFinalizer::Lambda]
|
41
|
+
# @return [SmartCore::Initializer::Attribute::ValueFinalizer::Method]
|
42
|
+
#
|
43
|
+
# @api private
|
44
|
+
# @since 0.5.0
|
45
|
+
def represent_finalizer_attr(finalize)
|
46
|
+
raise(
|
47
|
+
SmartCore::Initializer::IncompatibleFinalizerTypeError,
|
48
|
+
':finalize should be a symbol/string or a proc/lambda'
|
49
|
+
) unless finalize.is_a?(Proc) || finalize.is_a?(Symbol) || finalize.is_a?(String)
|
50
|
+
|
51
|
+
ValueFinalizer.build(finalize)
|
52
|
+
end
|
53
|
+
|
54
|
+
# @param privacy [Symbol, String]
|
55
|
+
# @return [Symbol]
|
56
|
+
#
|
57
|
+
# @api private
|
58
|
+
# @since 0.5.0
|
59
|
+
def represent_privacy_attr(privacy)
|
60
|
+
begin
|
61
|
+
PRIVACY_MODES.fetch(privacy.to_sym)
|
62
|
+
rescue KeyError
|
63
|
+
raise(
|
64
|
+
SmartCore::Initializer::UnsupportedAttributePrivacyError,
|
65
|
+
"Required :#{privacy} privacy mode is not supported!"
|
66
|
+
)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# @param name [Symbol, String]
|
71
|
+
# @return [Symbol, String]
|
72
|
+
#
|
73
|
+
# @api private
|
74
|
+
# @since 0.5.0
|
75
|
+
def represent_name_attr(name)
|
76
|
+
name.tap do |value|
|
77
|
+
raise(
|
78
|
+
SmartCore::Initializer::IncorrectAttributeNameError,
|
79
|
+
'Attribute name should be a symbol or a string'
|
80
|
+
) unless value.is_a?(Symbol) || value.is_a?(String)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# @param type [String]
|
85
|
+
# @return [Symbol]
|
86
|
+
#
|
87
|
+
# @api private
|
88
|
+
# @since 0.5.0
|
89
|
+
def represent_type_attr(type)
|
90
|
+
type.tap do |value|
|
91
|
+
raise(
|
92
|
+
SmartCore::Initializer::UnregisteredTypeError,
|
93
|
+
"type :#{value} is not registered!"
|
94
|
+
) unless SmartCore::Initializer.types.has_type?(value)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.5.0
|
5
|
+
class SmartCore::Initializer::Attribute::ValueFinalizer::Lambda
|
6
|
+
# @param finalizer [Proc]
|
7
|
+
# @return [void]
|
8
|
+
#
|
9
|
+
# @api private
|
10
|
+
# @since 0.5.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.5.0
|
21
|
+
def finalize(value, instance)
|
22
|
+
finalizer.call(value)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
# @return [Proc]
|
28
|
+
#
|
29
|
+
# @api private
|
30
|
+
# @since 0.5.0
|
31
|
+
attr_reader :finalizer
|
32
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.5.0
|
5
|
+
class SmartCore::Initializer::Attribute::ValueFinalizer::Method
|
6
|
+
# @param finalizer [String, Symbol]
|
7
|
+
# @return [void]
|
8
|
+
#
|
9
|
+
# @api private
|
10
|
+
# @since 0.5.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.5.0
|
21
|
+
def finalize(value, instance)
|
22
|
+
instance.send(finalizer, value)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
# @return [String, Symbol]
|
28
|
+
#
|
29
|
+
# @api private
|
30
|
+
# @since 0.5.0
|
31
|
+
attr_reader :finalizer
|
32
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SmartCore::Initializer::Attribute::ValueFinalizer
|
4
|
+
require_relative 'value_finalizer/lambda'
|
5
|
+
require_relative 'value_finalizer/method'
|
6
|
+
|
7
|
+
class << self
|
8
|
+
# @param finalize [Proc, String, Symbol]
|
9
|
+
# @return [SmartCore::Initializer::Attribute::ValueFinalizer::Lambda]
|
10
|
+
# @return [SmartCore::Initializer::Attribute::ValueFinalizer::Method]
|
11
|
+
#
|
12
|
+
# @api private
|
13
|
+
# @since 0.5.0
|
14
|
+
def build(finalize)
|
15
|
+
case finalize
|
16
|
+
when Symbol, String
|
17
|
+
Method.new(finalize)
|
18
|
+
when Proc
|
19
|
+
Lambda.new(finalize)
|
20
|
+
end
|
21
|
+
# NOTE: other variants are impossible (by SmartCore::Initializer::Attribute::Builder)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.5.0
|
5
|
+
class SmartCore::Initializer::Attribute
|
6
|
+
require_relative 'attribute/builder'
|
7
|
+
require_relative 'attribute/value_finalizer'
|
8
|
+
|
9
|
+
# @return [Hash<Symbol,Symbol>]
|
10
|
+
#
|
11
|
+
# @api private
|
12
|
+
# @since 0.5.0
|
13
|
+
PRIVACY_MODES = {
|
14
|
+
private: :private,
|
15
|
+
protected: :protected,
|
16
|
+
public: :public,
|
17
|
+
default: :public
|
18
|
+
}.freeze
|
19
|
+
|
20
|
+
# @return [Symbol]
|
21
|
+
#
|
22
|
+
# @api private
|
23
|
+
# @since 0.5.0
|
24
|
+
attr_reader :name
|
25
|
+
|
26
|
+
# @return [String, Symbol]
|
27
|
+
#
|
28
|
+
# @api private
|
29
|
+
# @since 0.5.0
|
30
|
+
attr_reader :type
|
31
|
+
|
32
|
+
# @return [Symbol]
|
33
|
+
#
|
34
|
+
# @api private
|
35
|
+
# @since 0.5.0
|
36
|
+
attr_reader :privacy
|
37
|
+
|
38
|
+
# @return [SmartCore::Initializer::Attribute::ValueFinalizer::Lambda]
|
39
|
+
# @return [SmartCore::Initializer::Attribute::ValueFinalizer::Method]
|
40
|
+
#
|
41
|
+
# @api private
|
42
|
+
# @since 0.5.0
|
43
|
+
attr_reader :finalizer
|
44
|
+
|
45
|
+
# @return [Hash<Symbol,Any>]
|
46
|
+
#
|
47
|
+
# @api private
|
48
|
+
# @since 0.5.0
|
49
|
+
attr_reader :options
|
50
|
+
|
51
|
+
# @param name [String, Symbol]
|
52
|
+
# @param type [Symbol] (see SmartCore::Initializer::TypeSet, SmartCore::Initializer::Type)
|
53
|
+
# @param privacy [Symbol
|
54
|
+
# @param finalizer [SmartCore::Initializer::Attribute::ValueFinalizer::Lambda/Method]
|
55
|
+
# @param options [HAsh<Symbol,Any>] Supported options:
|
56
|
+
# - :default [Proc] see #default_value
|
57
|
+
# @return [void]
|
58
|
+
#
|
59
|
+
# @api private
|
60
|
+
# @since 0.5.0
|
61
|
+
def initialize(name, type, privacy, finalizer, **options)
|
62
|
+
@name = name
|
63
|
+
@type = type
|
64
|
+
@privacy = privacy
|
65
|
+
@finalizer = finalizer
|
66
|
+
@options = options
|
67
|
+
end
|
68
|
+
|
69
|
+
# @return [Boolean]
|
70
|
+
#
|
71
|
+
# @api private
|
72
|
+
# @since 0.5.0
|
73
|
+
def has_default_value?
|
74
|
+
options.key?(:default)
|
75
|
+
end
|
76
|
+
|
77
|
+
# @param value [Any]
|
78
|
+
# @return [void]
|
79
|
+
#
|
80
|
+
# @api private
|
81
|
+
# @since 0.5.0
|
82
|
+
def validate_value_type!(value)
|
83
|
+
type_checker = SmartCore::Initializer.get_type(type)
|
84
|
+
|
85
|
+
raise(
|
86
|
+
SmartCore::Initializer::ArgumentError,
|
87
|
+
"Incorrect type of <#{name}> attribute " \
|
88
|
+
"(given: #{value.class}, expected: :#{type_checker.name})"
|
89
|
+
) unless type_checker.comparable?(value)
|
90
|
+
end
|
91
|
+
|
92
|
+
# @return [Any]
|
93
|
+
#
|
94
|
+
# @raise [SmartCore::Initializer::ArgumentError]
|
95
|
+
#
|
96
|
+
# @api private
|
97
|
+
# @since 0.5.0
|
98
|
+
def default_value
|
99
|
+
default_value = options.fetch(:default) do
|
100
|
+
raise(SmartCore::Initializer::ArgumentError, 'Default value is not provided.')
|
101
|
+
end
|
102
|
+
|
103
|
+
default_value.is_a?(Proc) ? default_value.call : default_value
|
104
|
+
end
|
105
|
+
|
106
|
+
# @param value [Any]
|
107
|
+
# @param instance [Any]
|
108
|
+
# @return [Any]
|
109
|
+
#
|
110
|
+
# @api private
|
111
|
+
# @since 0.5.0
|
112
|
+
def finalize(value, instance)
|
113
|
+
finalizer.finalize(value, instance)
|
114
|
+
end
|
115
|
+
|
116
|
+
# @return [SmartCore::Intializer::Attribute]
|
117
|
+
#
|
118
|
+
# @api private
|
119
|
+
# @since 0.5.0
|
120
|
+
def dup
|
121
|
+
self.class.new(name, type, privacy, finalizer, **options)
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.5.0
|
5
|
+
class SmartCore::Initializer::AttributeDefiner
|
6
|
+
# @param processed_klass [Class]
|
7
|
+
# @return [void]
|
8
|
+
#
|
9
|
+
# @api private
|
10
|
+
# @since 0.5.0
|
11
|
+
def initialize(processed_klass)
|
12
|
+
@processed_klass = processed_klass
|
13
|
+
@definition_lock = Mutex.new
|
14
|
+
end
|
15
|
+
|
16
|
+
# @param param_name [Symbol, String]
|
17
|
+
# @param param_type [String, Symbol]
|
18
|
+
# @return [void]
|
19
|
+
#
|
20
|
+
# @api private
|
21
|
+
# @since 0.5.0
|
22
|
+
def define_param(param_name, param_type = :__any__, **options)
|
23
|
+
thread_safe do
|
24
|
+
parameter = build_attribute(param_name, param_type, **options)
|
25
|
+
prevent_intersection_with_already_defined_option(parameter)
|
26
|
+
append_parameter(parameter)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# @param param_names [Array<String, Symbol>]
|
31
|
+
# @return [void]
|
32
|
+
#
|
33
|
+
# @api private
|
34
|
+
# @since 0.5.0
|
35
|
+
def define_params(*param_names)
|
36
|
+
thread_safe do
|
37
|
+
parameters = param_names.map do |param_name|
|
38
|
+
build_attribute(param_name).tap do |parameter|
|
39
|
+
prevent_intersection_with_already_defined_option(parameter)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
parameters.each { |parameter| append_parameter(parameter) }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# @param option_name [Symbol, String]
|
48
|
+
# @param option_type [String, Symbol]
|
49
|
+
# @return [void]
|
50
|
+
#
|
51
|
+
# @api private
|
52
|
+
# @since 0.5.0
|
53
|
+
def define_option(option_name, option_type = :__any__, **options)
|
54
|
+
thread_safe do
|
55
|
+
option = build_attribute(option_name, option_type, **options)
|
56
|
+
prevent_intersection_with_already_defined_param(option)
|
57
|
+
|
58
|
+
append_option(option)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# @param option_names [Array<String, Symbol>]
|
63
|
+
# @return [void]
|
64
|
+
#
|
65
|
+
# @api private
|
66
|
+
# @since 0.5.0
|
67
|
+
def define_options(*option_names)
|
68
|
+
thread_safe do
|
69
|
+
options = option_names.map do |option_name|
|
70
|
+
build_attribute(option_name).tap do |option|
|
71
|
+
prevent_intersection_with_already_defined_param(option)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
options.each { |option| append_option(option) }
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
# @return [Class]
|
82
|
+
#
|
83
|
+
# @api private
|
84
|
+
# @since 0.5.0
|
85
|
+
attr_reader :processed_klass
|
86
|
+
|
87
|
+
# @param attribute_name [Symbol, String]
|
88
|
+
# @param attribute_type [String, Symbol]
|
89
|
+
# @param attribute_options [Hash<Symbol,Any>]
|
90
|
+
# @return [SmartCore::Initializer::Attribute]
|
91
|
+
#
|
92
|
+
# @api private
|
93
|
+
# @since 0.5.0
|
94
|
+
def build_attribute(attribute_name, attribute_type = :__any__, **attribute_options)
|
95
|
+
SmartCore::Initializer::Attribute::Builder.build(
|
96
|
+
attribute_name, type: attribute_type, **attribute_options
|
97
|
+
)
|
98
|
+
end
|
99
|
+
|
100
|
+
# @param parameter [SmartCore::Initializer::Attribute]
|
101
|
+
# @return [void]
|
102
|
+
#
|
103
|
+
# @api private
|
104
|
+
# @since 0.5.0
|
105
|
+
def append_parameter(parameter)
|
106
|
+
processed_klass.__params__ << parameter
|
107
|
+
processed_klass.send(:attr_reader, parameter.name)
|
108
|
+
processed_klass.send(parameter.privacy, parameter.name)
|
109
|
+
end
|
110
|
+
|
111
|
+
# @param option [SmartCore::Initializer::Attribute]
|
112
|
+
# @return [void]
|
113
|
+
#
|
114
|
+
# @api private
|
115
|
+
# @since 0.5.0
|
116
|
+
def append_option(option)
|
117
|
+
processed_klass.__options__ << option
|
118
|
+
processed_klass.send(:attr_reader, option.name)
|
119
|
+
processed_klass.send(option.privacy, option.name)
|
120
|
+
end
|
121
|
+
|
122
|
+
# @param parameter [SmartCore::Initializer::Attribute]
|
123
|
+
# @return [void]
|
124
|
+
#
|
125
|
+
# @raise [SmartCore::Initializer::OptionOverlapError]
|
126
|
+
#
|
127
|
+
# @api private
|
128
|
+
# @since 0.5.0
|
129
|
+
def prevent_intersection_with_already_defined_option(parameter)
|
130
|
+
if processed_klass.__options__.conflicts_with?(parameter)
|
131
|
+
raise(
|
132
|
+
SmartCore::Initializer::OptionOverlapError,
|
133
|
+
"You have already defined option with name :#{parameter.name}"
|
134
|
+
)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
# @param option [SmartCore::Initializer::Attribute]
|
139
|
+
# @return [void]
|
140
|
+
#
|
141
|
+
# @raise [SmartCore::Initializer::ParamOverlapError]
|
142
|
+
#
|
143
|
+
# @api private
|
144
|
+
# @since 0.5.0
|
145
|
+
def prevent_intersection_with_already_defined_param(option)
|
146
|
+
if processed_klass.__params__.conflicts_with?(option)
|
147
|
+
raise(
|
148
|
+
SmartCore::Initializer::ParamOverlapError,
|
149
|
+
"You have already defined param with name :#{option.name}"
|
150
|
+
)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
# @param block [Proc]
|
155
|
+
# @return [Any]
|
156
|
+
#
|
157
|
+
# @api private
|
158
|
+
# @since 0.5.0
|
159
|
+
def thread_safe(&block)
|
160
|
+
@definition_lock.synchronize(&block)
|
161
|
+
end
|
162
|
+
end
|