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,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SmartCore::Container::DependencyCompatability
|
4
|
+
# @api private
|
5
|
+
# @since 0.5.0
|
6
|
+
class CommandSet < Abstract
|
7
|
+
class << self
|
8
|
+
# @param command_set [SmartCore::Container::CommandSet]
|
9
|
+
# @param dependency_name [String]
|
10
|
+
# @return [Boolean]
|
11
|
+
#
|
12
|
+
# @api private
|
13
|
+
# @since 0.5.0
|
14
|
+
def potential_namespace_overlap?(command_set, dependency_name)
|
15
|
+
command_set.any? do |command|
|
16
|
+
next unless command.is_a?(SmartCore::Container::Commands::Namespace)
|
17
|
+
command.namespace_name == dependency_name
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# @param command_set [SmartCore::Container::CommandSet]
|
22
|
+
# @param namespace_name [String]
|
23
|
+
# @return [Boolean]
|
24
|
+
#
|
25
|
+
# @api private
|
26
|
+
# @since 0.5.0
|
27
|
+
def potential_dependency_overlap?(command_set, namespace_name)
|
28
|
+
command_set.any? do |command|
|
29
|
+
next unless command.is_a?(SmartCore::Container::Commands::Register)
|
30
|
+
command.dependency_name == namespace_name
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SmartCore::Container::DependencyCompatability
|
4
|
+
# @api private
|
5
|
+
# @since 0.5.0
|
6
|
+
class Registry < Abstract
|
7
|
+
class << self
|
8
|
+
# @param registry [SmartCore::Container::Regsitry]
|
9
|
+
# @param dependency_name [String]
|
10
|
+
# @return [Boolean]
|
11
|
+
#
|
12
|
+
# @api private
|
13
|
+
# @since 0.5.0
|
14
|
+
def potential_namespace_overlap?(registry, dependency_name)
|
15
|
+
registry.any? do |registered_dependency|
|
16
|
+
next unless registered_dependency.is_a?(SmartCore::Container::Namespace)
|
17
|
+
# NOTE: registered_dependency is a namespace
|
18
|
+
registered_dependency.external_name == dependency_name
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# @param registry [SmartCore::Container::Regsitry]
|
23
|
+
# @param namespace_name [String]
|
24
|
+
# @return [Boolean]
|
25
|
+
#
|
26
|
+
# @api private
|
27
|
+
# @since 0.5.0
|
28
|
+
def potential_dependency_overlap?(registry, namespace_name)
|
29
|
+
registry.any? do |registered_dependency|
|
30
|
+
next unless registered_dependency.is_a?(SmartCore::Container::Dependency)
|
31
|
+
# NOTE: registered_dependency is a dependency/memoized dependency
|
32
|
+
registered_dependency.external_name == namespace_name
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.5.0
|
5
|
+
module SmartCore::Container::DependencyCompatability
|
6
|
+
require_relative 'dependency_compatability/abstract'
|
7
|
+
require_relative 'dependency_compatability/command_set'
|
8
|
+
require_relative 'dependency_compatability/registry'
|
9
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.5.0
|
5
|
+
module SmartCore::Container::DependencyResolver
|
6
|
+
class << self
|
7
|
+
# @param registry [SmartCore::Container::Registry]
|
8
|
+
# @return [Any]
|
9
|
+
#
|
10
|
+
# @api private
|
11
|
+
# @since 0.5.0
|
12
|
+
def resolve(registry, dependency_path)
|
13
|
+
registry.resolve(dependency_path).call
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.5.0
|
5
|
+
class SmartCore::Container::Entity
|
6
|
+
# @return [String]
|
7
|
+
#
|
8
|
+
# @api private
|
9
|
+
# @since 0.5.0
|
10
|
+
attr_reader :external_name
|
11
|
+
|
12
|
+
# @param external_name [String]
|
13
|
+
# @return [void]
|
14
|
+
#
|
15
|
+
# @api private
|
16
|
+
# @since 0.5.0
|
17
|
+
def initialize(external_name)
|
18
|
+
@external_name = external_name
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [void]
|
22
|
+
#
|
23
|
+
# @api private
|
24
|
+
# @since 0.5.0
|
25
|
+
def call; end
|
26
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class SmartCore::Container
|
4
|
+
# @api public
|
5
|
+
# @since 0.5.0
|
6
|
+
Error = Class.new(SmartCore::Error)
|
7
|
+
|
8
|
+
# @api public
|
9
|
+
# @since 0.5.0
|
10
|
+
ArgumentError = Class.new(SmartCore::ArgumentError)
|
11
|
+
|
12
|
+
# @api public
|
13
|
+
# @since 0.5.0
|
14
|
+
NamespaceOverlapError = Class.new(Error)
|
15
|
+
|
16
|
+
# @api public
|
17
|
+
# @since 0.5.0
|
18
|
+
DependencyOverlapError = Class.new(Error)
|
19
|
+
|
20
|
+
# @api public
|
21
|
+
# @since 0.5.0
|
22
|
+
UnexistentDependencyError = Class.new(Error)
|
23
|
+
|
24
|
+
# @api public
|
25
|
+
# @since 0.5.0
|
26
|
+
FrozenRegistryError = Class.new(SmartCore::FrozenError)
|
27
|
+
|
28
|
+
# @api private
|
29
|
+
# @since 0.5.0
|
30
|
+
IncompatibleDependencyTree = Class.new(Error)
|
31
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api priavate
|
4
|
+
# @since 0.5.0
|
5
|
+
module SmartCore::Container::KeyGuard
|
6
|
+
class << self
|
7
|
+
# @param key [Symbol, String]
|
8
|
+
# @return [void]
|
9
|
+
#
|
10
|
+
# @raise [SmartCore::Container::ArgumentError]
|
11
|
+
#
|
12
|
+
# @api private
|
13
|
+
# @since 0.5.0
|
14
|
+
def prevent_incomparabilities!(key)
|
15
|
+
raise(
|
16
|
+
SmartCore::Container::ArgumentError,
|
17
|
+
'Namespace/Dependency name should be a symbol or a string'
|
18
|
+
) unless key.is_a?(String) || key.is_a?(Symbol)
|
19
|
+
end
|
20
|
+
|
21
|
+
# @param key [Symbol, String]
|
22
|
+
# @return [String]
|
23
|
+
#
|
24
|
+
# @api private
|
25
|
+
# @since 0.5.0
|
26
|
+
def indifferently_accessable_key(key)
|
27
|
+
prevent_incomparabilities!(key)
|
28
|
+
key.to_s
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.5.0
|
5
|
+
class SmartCore::Container::MemoizedDependency < SmartCore::Container::Dependency
|
6
|
+
# @param external_name [String]
|
7
|
+
# @param dependency_definition [Proc]
|
8
|
+
# @param options [Hash<Symbol,Any>]
|
9
|
+
# @return [void]
|
10
|
+
#
|
11
|
+
# @todo option list
|
12
|
+
# @see [SmartCore::Container::Dependency]
|
13
|
+
#
|
14
|
+
# @api private
|
15
|
+
# @since 0.5.0
|
16
|
+
def initialize(external_name, dependency_definition, **options)
|
17
|
+
@memoized_call = nil
|
18
|
+
super
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [Any]
|
22
|
+
#
|
23
|
+
# @api private
|
24
|
+
# @since 0.5.0
|
25
|
+
def call
|
26
|
+
thread_safe { @memoized_call ||= dependency_definition.call }
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api public
|
4
|
+
# @since 0.5.0
|
5
|
+
module SmartCore::Container::Mixin
|
6
|
+
class << self
|
7
|
+
# @param base_klass [Class]
|
8
|
+
# @return [void]
|
9
|
+
#
|
10
|
+
# @api private
|
11
|
+
# @since 0.5.0
|
12
|
+
def included(base_klass)
|
13
|
+
# rubocop:disable Metrics/LineLength
|
14
|
+
base_klass.instance_variable_set(:@__smart_core_container_access_lock__, Mutex.new)
|
15
|
+
base_klass.instance_variable_set(:@__smart_core_container_definition_lock__, Mutex.new)
|
16
|
+
base_klass.instance_variable_set(:@__smart_core_container_klass__, Class.new(SmartCore::Container))
|
17
|
+
base_klass.instance_variable_set(:@__smart_core_container__, nil)
|
18
|
+
# rubocop:enable Metrics/LineLength
|
19
|
+
|
20
|
+
base_klass.extend(ClassMethods)
|
21
|
+
base_klass.include(InstanceMethods)
|
22
|
+
base_klass.singleton_class.prepend(ClassInheritance)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# @api private
|
27
|
+
# @since 0.5.0
|
28
|
+
module ClassInheritance
|
29
|
+
# @param child_klass [CLass]
|
30
|
+
# @return [void]
|
31
|
+
#
|
32
|
+
# @api private
|
33
|
+
# @since 0.5.0
|
34
|
+
def inherited(child_klass)
|
35
|
+
inherited_container_klass = Class.new(@__smart_core_container_klass__)
|
36
|
+
|
37
|
+
child_klass.instance_variable_set(:@__smart_core_container_access_lock__, Mutex.new)
|
38
|
+
child_klass.instance_variable_set(:@__smart_core_container_definition_lock__, Mutex.new)
|
39
|
+
child_klass.instance_variable_set(:@__smart_core_container_klass__, inherited_container_klass)
|
40
|
+
child_klass.instance_variable_set(:@__smart_core_container__, nil)
|
41
|
+
|
42
|
+
super
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# @api private
|
47
|
+
# @since 0.5.0
|
48
|
+
module ClassMethods
|
49
|
+
# @param block [Proc]
|
50
|
+
# @return [void]
|
51
|
+
#
|
52
|
+
# @api public
|
53
|
+
# @since 0.5.0
|
54
|
+
def dependencies(&block)
|
55
|
+
@__smart_core_container_definition_lock__.synchronize do
|
56
|
+
@__smart_core_container_klass__.instance_eval(&block) if block_given?
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# @return [SmartCore::Container]
|
61
|
+
#
|
62
|
+
# @api public
|
63
|
+
# @since 0.5.0
|
64
|
+
def container
|
65
|
+
@__smart_core_container_definition_lock__.synchronize do
|
66
|
+
@__smart_core_container__ ||= @__smart_core_container_klass__.new
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# @api private
|
72
|
+
# @since 0.5.0
|
73
|
+
module InstanceMethods
|
74
|
+
# @return [SmartCore::Container]
|
75
|
+
#
|
76
|
+
# @api public
|
77
|
+
# @since 0.5.0
|
78
|
+
def container
|
79
|
+
self.class.container
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.5.0
|
5
|
+
class SmartCore::Container::Namespace < SmartCore::Container::Entity
|
6
|
+
# @param external_name [String]
|
7
|
+
# @return [void]
|
8
|
+
#
|
9
|
+
# @api private
|
10
|
+
# @since 0.5.0
|
11
|
+
def initialize(external_name)
|
12
|
+
@container = Class.new(SmartCore::Container)
|
13
|
+
@container_instance = nil
|
14
|
+
@access_lock = Mutex.new
|
15
|
+
super(external_name)
|
16
|
+
end
|
17
|
+
|
18
|
+
# @param dependency_definitions [Proc]
|
19
|
+
# @return [void]
|
20
|
+
#
|
21
|
+
# @api private
|
22
|
+
# @since 0.5.0
|
23
|
+
def append_definitions(dependency_definitions)
|
24
|
+
container.instance_eval(&dependency_definitions)
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [SmartCore::Container]
|
28
|
+
#
|
29
|
+
# @api private
|
30
|
+
# @since 0.5.0
|
31
|
+
def call
|
32
|
+
thread_safe { @container_instance ||= container.new }
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
# @return [Class<SmartCore::Container>]
|
38
|
+
#
|
39
|
+
# @api private
|
40
|
+
# @since 0.5.0
|
41
|
+
attr_reader :container
|
42
|
+
|
43
|
+
# @param block [Proc]
|
44
|
+
# @return [Any]
|
45
|
+
#
|
46
|
+
# @api private
|
47
|
+
# @since 0.5.0
|
48
|
+
def thread_safe(&block)
|
49
|
+
@access_lock.synchronize(&block)
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,227 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class SmartCore::Container
|
4
|
+
# @api private
|
5
|
+
# @since 0.5.0
|
6
|
+
class Registry
|
7
|
+
# @since 0.5.0
|
8
|
+
include Enumerable
|
9
|
+
|
10
|
+
# @return [void]
|
11
|
+
#
|
12
|
+
# @api private
|
13
|
+
# @since 0.5.0
|
14
|
+
def initialize
|
15
|
+
@access_lock = Mutex.new
|
16
|
+
@registry = {}
|
17
|
+
end
|
18
|
+
|
19
|
+
# @return [void]
|
20
|
+
#
|
21
|
+
# @api private
|
22
|
+
# @since 0.5.0
|
23
|
+
def freeze
|
24
|
+
thread_safe { freeze_state }
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [void]
|
28
|
+
#
|
29
|
+
# @api private
|
30
|
+
# @since 0.5.0
|
31
|
+
def frozen?
|
32
|
+
thread_safe { state_frozen? }
|
33
|
+
end
|
34
|
+
|
35
|
+
# @param dependency_path [String, Symbol]
|
36
|
+
# @return [SmartCore::Container::Namespace, SmartCore::Container::Dependnecy]
|
37
|
+
#
|
38
|
+
# @api private
|
39
|
+
# @since 0.5.0
|
40
|
+
def resolve(dependency_path)
|
41
|
+
thread_safe { fetch_dependency(dependency_path) }
|
42
|
+
end
|
43
|
+
|
44
|
+
# @param name [String, Symbol]
|
45
|
+
# @param options [Hash<Symbol,Any>]
|
46
|
+
# @param dependency_definition [Block]
|
47
|
+
# @return [void]
|
48
|
+
#
|
49
|
+
# @todo option list
|
50
|
+
#
|
51
|
+
# @api private
|
52
|
+
# @since 0.5.0
|
53
|
+
def register(name, **options, &dependency_definition)
|
54
|
+
thread_safe do
|
55
|
+
raise(
|
56
|
+
SmartCore::Container::FrozenRegistryError,
|
57
|
+
'Can not modify frozen registry'
|
58
|
+
) if state_frozen?
|
59
|
+
|
60
|
+
append_dependency(name, dependency_definition, **options)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# @param name [String, Symbol]
|
65
|
+
# @param dependency_definitions [Block]
|
66
|
+
# @return [void]
|
67
|
+
#
|
68
|
+
# @api private
|
69
|
+
# @since 0.5.0
|
70
|
+
def namespace(name, &dependency_definitions)
|
71
|
+
thread_safe do
|
72
|
+
raise(
|
73
|
+
SmartCore::Container::FrozenRegistryError,
|
74
|
+
'Can not modify frozen registry'
|
75
|
+
) if state_frozen?
|
76
|
+
|
77
|
+
append_namespace(name, dependency_definitions)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# @param block [Block]
|
82
|
+
# @return [Enumerable]
|
83
|
+
#
|
84
|
+
# @api private
|
85
|
+
# @since 0.5.0
|
86
|
+
def each(&block)
|
87
|
+
thread_safe { block_given? ? registry.each_value(&block) : registry.each_value }
|
88
|
+
end
|
89
|
+
|
90
|
+
# @return [Hash<Symbol,Any>]
|
91
|
+
#
|
92
|
+
# @api private
|
93
|
+
# @since 0.5.0
|
94
|
+
def to_h
|
95
|
+
# TODO: implement :)
|
96
|
+
end
|
97
|
+
|
98
|
+
private
|
99
|
+
|
100
|
+
# @return [Mutex]
|
101
|
+
#
|
102
|
+
# @api private
|
103
|
+
# @since 0.5.0
|
104
|
+
attr_reader :access_lock
|
105
|
+
|
106
|
+
# @return [Hash<Symbol,SmartCore::Container::Entity>]
|
107
|
+
#
|
108
|
+
# @api private
|
109
|
+
# @since 0.5.0
|
110
|
+
attr_reader :registry
|
111
|
+
|
112
|
+
# @return [Boolean]
|
113
|
+
#
|
114
|
+
# @api private
|
115
|
+
# @since 0.5.0
|
116
|
+
def state_frozen?
|
117
|
+
registry.frozen?
|
118
|
+
end
|
119
|
+
|
120
|
+
# @return [void]
|
121
|
+
#
|
122
|
+
# @api private
|
123
|
+
# @since 0.5.0
|
124
|
+
def freeze_state
|
125
|
+
registry.freeze
|
126
|
+
end
|
127
|
+
|
128
|
+
# @paramm dependency_path [String, Symbol]
|
129
|
+
# @return [SmartCore::Container::Namespace, SmartCore::Container::Dependency]
|
130
|
+
#
|
131
|
+
# @api private
|
132
|
+
# @since 0.5.0
|
133
|
+
def fetch_dependency(dependency_path)
|
134
|
+
# TODO: rabbit style dependnecy path
|
135
|
+
name = indifferently_accessable_name(dependency_path)
|
136
|
+
registry.fetch(name)
|
137
|
+
rescue KeyError
|
138
|
+
raise(
|
139
|
+
SmartCore::Container::UnexistentDependencyError,
|
140
|
+
"Dependencny with '#{name}' name does not exist!"
|
141
|
+
)
|
142
|
+
end
|
143
|
+
|
144
|
+
# @param dependency_name [String, Symbol]
|
145
|
+
# @param dependency_definition [Proc]
|
146
|
+
# @param options [Hash<Symbol,Any>]
|
147
|
+
# @return [void]
|
148
|
+
#
|
149
|
+
# @todo option list
|
150
|
+
# @raise [SmartCore::Container::NamespaceOverlapError]
|
151
|
+
#
|
152
|
+
# @api private
|
153
|
+
# @since 0.5.0
|
154
|
+
def append_dependency(dependency_name, dependency_definition, **options)
|
155
|
+
dependency_name = indifferently_accessable_name(dependency_name)
|
156
|
+
prevent_namespace_overlap!(dependency_name)
|
157
|
+
dependency = DependencyBuilder.build(dependency_name, dependency_definition, **options)
|
158
|
+
|
159
|
+
registry[dependency_name] = dependency
|
160
|
+
end
|
161
|
+
|
162
|
+
# @param namespace_name [String, Symbol]
|
163
|
+
# @param dependency_definitions [Proc]
|
164
|
+
# @return [void]
|
165
|
+
#
|
166
|
+
# @raise [SmartCore::Container::DependencyOverlapError]
|
167
|
+
#
|
168
|
+
# @api private
|
169
|
+
# @since 0.5.0
|
170
|
+
def append_namespace(namespace_name, dependency_definitions)
|
171
|
+
namespace_name = indifferently_accessable_name(namespace_name)
|
172
|
+
prevent_dependency_overlap!(namespace_name)
|
173
|
+
|
174
|
+
# rubocop:disable Layout/RescueEnsureAlignment
|
175
|
+
namespace = begin
|
176
|
+
registry.fetch(namespace_name)
|
177
|
+
rescue KeyError
|
178
|
+
registry[namespace_name] = SmartCore::Container::Namespace.new(namespace_name)
|
179
|
+
end
|
180
|
+
# rubocop:enable Layout/RescueEnsureAlignment
|
181
|
+
|
182
|
+
namespace.append_definitions(dependency_definitions)
|
183
|
+
end
|
184
|
+
|
185
|
+
# @param name [String, Symbol]
|
186
|
+
# @return [void]
|
187
|
+
#
|
188
|
+
# @see [SmartCore::Container::KeyGuard]
|
189
|
+
#
|
190
|
+
# @api private
|
191
|
+
# @since 0.5.0
|
192
|
+
def indifferently_accessable_name(name)
|
193
|
+
SmartCore::Container::KeyGuard.indifferently_accessable_key(name)
|
194
|
+
end
|
195
|
+
|
196
|
+
# @param dependency_name [String]
|
197
|
+
# @retrun [void]
|
198
|
+
#
|
199
|
+
# @api private
|
200
|
+
# @since 0.5.0
|
201
|
+
def prevent_namespace_overlap!(dependency_name)
|
202
|
+
DependencyCompatability::Registry.prevent_namespace_overlap!(
|
203
|
+
self, dependency_name
|
204
|
+
)
|
205
|
+
end
|
206
|
+
|
207
|
+
# @param namespace_name [String]
|
208
|
+
# @return [void]
|
209
|
+
#
|
210
|
+
# @api private
|
211
|
+
# @since 0.5.0
|
212
|
+
def prevent_dependency_overlap!(namespace_name)
|
213
|
+
DependencyCompatability::Registry.prevent_dependency_overlap!(
|
214
|
+
self, namespace_name
|
215
|
+
)
|
216
|
+
end
|
217
|
+
|
218
|
+
# @param block [Proc]
|
219
|
+
# @return [Any]
|
220
|
+
#
|
221
|
+
# @api private
|
222
|
+
# @since 0.5.0
|
223
|
+
def thread_safe(&block)
|
224
|
+
@access_lock.synchronize(&block)
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.5.0
|
5
|
+
module SmartCore::Container::RegistryBuilder
|
6
|
+
class << self
|
7
|
+
# @param commands [SmartCore::Container::CommandSet]
|
8
|
+
# @return [SmartCore::Container::Registry]
|
9
|
+
#
|
10
|
+
# @api private
|
11
|
+
# @since 0.5.0
|
12
|
+
def build(commands)
|
13
|
+
SmartCore::Container::Registry.new.tap do |registry|
|
14
|
+
commands.each { |command| command.call(registry) }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|