smart_container 0.4.0 → 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +2 -2
- data/.travis.yml +6 -5
- data/CHANGELOG.md +32 -0
- data/Gemfile.lock +46 -31
- data/README.md +248 -4
- data/Rakefile +2 -1
- data/lib/smart_core/container.rb +132 -7
- data/lib/smart_core/container/{arbitary_lock.rb → arbitrary_lock.rb} +1 -1
- data/lib/smart_core/container/definition_dsl.rb +2 -2
- data/lib/smart_core/container/definition_dsl/command_set.rb +1 -1
- data/lib/smart_core/container/definition_dsl/commands/definition/register.rb +1 -1
- data/lib/smart_core/container/dependency_resolver.rb +80 -6
- data/lib/smart_core/container/dependency_watcher.rb +151 -0
- data/lib/smart_core/container/dependency_watcher/observer.rb +46 -0
- data/lib/smart_core/container/entities/dependency.rb +3 -1
- data/lib/smart_core/container/entities/dependency_builder.rb +27 -59
- data/lib/smart_core/container/entities/memoized_dependency.rb +4 -2
- data/lib/smart_core/container/entities/namespace.rb +23 -6
- data/lib/smart_core/container/entities/namespace_builder.rb +14 -34
- data/lib/smart_core/container/host.rb +77 -0
- data/lib/smart_core/container/mixin.rb +2 -2
- data/lib/smart_core/container/registry.rb +15 -6
- data/lib/smart_core/container/version.rb +2 -2
- data/smart_container.gemspec +5 -5
- metadata +15 -12
data/Rakefile
CHANGED
@@ -4,6 +4,7 @@ require 'bundler/gem_tasks'
|
|
4
4
|
require 'rspec/core/rake_task'
|
5
5
|
require 'rubocop'
|
6
6
|
require 'rubocop/rake_task'
|
7
|
+
require 'rubocop-rails'
|
7
8
|
require 'rubocop-performance'
|
8
9
|
require 'rubocop-rspec'
|
9
10
|
require 'rubocop-rake'
|
@@ -11,8 +12,8 @@ require 'rubocop-rake'
|
|
11
12
|
RuboCop::RakeTask.new(:rubocop) do |t|
|
12
13
|
config_path = File.expand_path(File.join('.rubocop.yml'), __dir__)
|
13
14
|
t.options = ['--config', config_path]
|
14
|
-
t.requires << 'rubocop-performance'
|
15
15
|
t.requires << 'rubocop-rspec'
|
16
|
+
t.requires << 'rubocop-performance'
|
16
17
|
t.requires << 'rubocop-rake'
|
17
18
|
end
|
18
19
|
|
data/lib/smart_core/container.rb
CHANGED
@@ -7,10 +7,10 @@ require 'smart_core'
|
|
7
7
|
module SmartCore
|
8
8
|
# @api public
|
9
9
|
# @since 0.1.0
|
10
|
-
class Container
|
10
|
+
class Container # rubocop:disable Metrics/ClassLength
|
11
11
|
require_relative 'container/version'
|
12
12
|
require_relative 'container/errors'
|
13
|
-
require_relative 'container/
|
13
|
+
require_relative 'container/arbitrary_lock'
|
14
14
|
require_relative 'container/key_guard'
|
15
15
|
require_relative 'container/entities'
|
16
16
|
require_relative 'container/definition_dsl'
|
@@ -18,27 +18,77 @@ module SmartCore
|
|
18
18
|
require_relative 'container/registry'
|
19
19
|
require_relative 'container/registry_builder'
|
20
20
|
require_relative 'container/dependency_resolver'
|
21
|
+
require_relative 'container/dependency_watcher'
|
22
|
+
require_relative 'container/host'
|
21
23
|
require_relative 'container/mixin'
|
22
24
|
|
25
|
+
class << self
|
26
|
+
# @param initial_container_klass [Class<SmartCore::Container>]
|
27
|
+
# @param container_definitions [Block]
|
28
|
+
# @return [SmartCore::Container]
|
29
|
+
#
|
30
|
+
# @api public
|
31
|
+
# @since 0.7.0
|
32
|
+
def define(initial_container_klass = self, &container_definitions)
|
33
|
+
unless initial_container_klass <= SmartCore::Container
|
34
|
+
raise(SmartCore::Container::ArgumentError, <<~ERROR_MESSAGE)
|
35
|
+
Base class should be a type of SmartCore::Container
|
36
|
+
ERROR_MESSAGE
|
37
|
+
end
|
38
|
+
|
39
|
+
Class.new(initial_container_klass, &container_definitions).new
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
23
43
|
# @since 0.4.0
|
24
44
|
include ::Enumerable
|
25
45
|
|
26
46
|
# @since 0.1.0
|
27
47
|
include DefinitionDSL
|
28
48
|
|
49
|
+
# @return [NilClass]
|
50
|
+
#
|
51
|
+
# @api private
|
52
|
+
# @since 0.8.1
|
53
|
+
NO_HOST_CONTAINER = nil
|
54
|
+
|
55
|
+
# @return [NilClass]
|
56
|
+
#
|
57
|
+
# @api private
|
58
|
+
# @since 0.8.1
|
59
|
+
NO_HOST_PATH = nil
|
60
|
+
|
29
61
|
# @return [SmartCore::Container::Registry]
|
30
62
|
#
|
31
63
|
# @api private
|
32
64
|
# @since 0.1.0
|
33
65
|
attr_reader :registry
|
34
66
|
|
67
|
+
# @return [SmartCore::Container::Host]
|
68
|
+
#
|
69
|
+
# @api private
|
70
|
+
# @since 0.8.1
|
71
|
+
attr_reader :host
|
72
|
+
|
73
|
+
# @return [SmartCore::Container::DependencyWatcher]
|
74
|
+
#
|
75
|
+
# @api private
|
76
|
+
# @since 0.8.0
|
77
|
+
attr_reader :watcher
|
78
|
+
|
79
|
+
# @option host_container [SmartCore::Container, NilClass]
|
80
|
+
# @option host_path [String, NilClass]
|
35
81
|
# @return [void]
|
36
82
|
#
|
37
83
|
# @api public
|
38
84
|
# @since 0.1.0
|
39
|
-
|
85
|
+
# @version 0.8.1
|
86
|
+
def initialize(host_container: NO_HOST_CONTAINER, host_path: NO_HOST_PATH)
|
87
|
+
@host = SmartCore::Container::Host.build(host_container, host_path)
|
40
88
|
build_registry!
|
41
|
-
@
|
89
|
+
@watcher = SmartCore::Container::DependencyWatcher.new(self)
|
90
|
+
@host_path = host_path
|
91
|
+
@access_lock = ArbitraryLock.new
|
42
92
|
end
|
43
93
|
|
44
94
|
# @param dependency_name [String, Symbol]
|
@@ -47,8 +97,16 @@ module SmartCore
|
|
47
97
|
#
|
48
98
|
# @api public
|
49
99
|
# @sicne 0.1.0
|
50
|
-
|
51
|
-
|
100
|
+
# @version 0.8.0
|
101
|
+
def register(
|
102
|
+
dependency_name,
|
103
|
+
memoize: SmartCore::Container::Registry::DEFAULT_MEMOIZATION_BEHAVIOR,
|
104
|
+
&dependency_definition
|
105
|
+
)
|
106
|
+
thread_safe do
|
107
|
+
registry.register_dependency(dependency_name, memoize: memoize, &dependency_definition)
|
108
|
+
watcher.notify(dependency_name)
|
109
|
+
end
|
52
110
|
end
|
53
111
|
|
54
112
|
# @param namespace_name [String, Symbol]
|
@@ -57,8 +115,12 @@ module SmartCore
|
|
57
115
|
#
|
58
116
|
# @api public
|
59
117
|
# @since 0.1.0
|
118
|
+
# @version 0.8.0
|
60
119
|
def namespace(namespace_name, &dependencies_definition)
|
61
|
-
thread_safe
|
120
|
+
thread_safe do
|
121
|
+
registry.register_namespace(namespace_name, self, &dependencies_definition)
|
122
|
+
watcher.notify(namespace_name)
|
123
|
+
end
|
62
124
|
end
|
63
125
|
|
64
126
|
# @param dependency_path [String, Symbol]
|
@@ -114,6 +176,34 @@ module SmartCore
|
|
114
176
|
thread_safe { registry.keys(all_variants: all_variants) }
|
115
177
|
end
|
116
178
|
|
179
|
+
# @param key [String, Symbol]
|
180
|
+
# @return [Boolean]
|
181
|
+
#
|
182
|
+
# @api public
|
183
|
+
# @since 0.5.0
|
184
|
+
def key?(key)
|
185
|
+
thread_safe { DependencyResolver.key?(self, key) }
|
186
|
+
end
|
187
|
+
|
188
|
+
# @param namespace_path [String, Symbol]
|
189
|
+
# @return [Boolean]
|
190
|
+
#
|
191
|
+
# @api public
|
192
|
+
# @since 0.5.0
|
193
|
+
def namespace?(namespace_path)
|
194
|
+
thread_safe { DependencyResolver.namespace?(self, namespace_path) }
|
195
|
+
end
|
196
|
+
|
197
|
+
# @param dependency_path [String, Symbol]
|
198
|
+
# @option memoized [NilClass, Boolean]
|
199
|
+
# @return [Boolean]
|
200
|
+
#
|
201
|
+
# @api public
|
202
|
+
# @since 0.5.0
|
203
|
+
def dependency?(dependency_path, memoized: nil)
|
204
|
+
thread_safe { DependencyResolver.dependency?(self, dependency_path, memoized: memoized) }
|
205
|
+
end
|
206
|
+
|
117
207
|
# @option yield_all [Boolean]
|
118
208
|
# @param block [Block]
|
119
209
|
# @yield [dependency_name, dependency_value]
|
@@ -143,12 +233,47 @@ module SmartCore
|
|
143
233
|
alias_method :to_h, :hash_tree
|
144
234
|
alias_method :to_hash, :hash_tree
|
145
235
|
|
236
|
+
# @param entity_path [String]
|
237
|
+
# @param observer [Block]
|
238
|
+
# @yield [entity_path, container]
|
239
|
+
# @yieldparam entity_path [String]
|
240
|
+
# @yieldparam container [SmartCore::Container]
|
241
|
+
# @return [SmartCore::Container::DependencyWatcher::Observer]
|
242
|
+
#
|
243
|
+
# @api public
|
244
|
+
# @since 0.8.0
|
245
|
+
def observe(entity_path, &observer) # TODO: support for pattern-based pathes
|
246
|
+
thread_safe { watcher.watch(entity_path, &observer) }
|
247
|
+
end
|
248
|
+
alias_method :subscribe, :observe
|
249
|
+
|
250
|
+
# @param observer [SmartCore::Container::DependencyWatcher::Observer]
|
251
|
+
# @return [Boolean]
|
252
|
+
#
|
253
|
+
# @api public
|
254
|
+
# @since 0.8.0
|
255
|
+
def unobserve(observer)
|
256
|
+
thread_safe { watcher.unwatch(observer) }
|
257
|
+
end
|
258
|
+
alias_method :unsubscribe, :unobserve
|
259
|
+
|
260
|
+
# @param entity_path [String, Symbol, NilClass]
|
261
|
+
# @return [void]
|
262
|
+
#
|
263
|
+
# @api public
|
264
|
+
# @since 0.8.0
|
265
|
+
def clear_observers(entity_path = nil) # TODO: support for pattern-based pathes
|
266
|
+
thread_safe { watcher.clear_listeners(entity_path) }
|
267
|
+
end
|
268
|
+
alias_method :clear_listeners, :clear_observers
|
269
|
+
|
146
270
|
private
|
147
271
|
|
148
272
|
# @return [void]
|
149
273
|
#
|
150
274
|
# @api private
|
151
275
|
# @since 0.1.0
|
276
|
+
# @version 0.8.1
|
152
277
|
def build_registry!
|
153
278
|
@registry = RegistryBuilder.build(self)
|
154
279
|
end
|
@@ -17,7 +17,7 @@ class SmartCore::Container
|
|
17
17
|
def included(base_klass)
|
18
18
|
base_klass.instance_variable_set(:@__container_definition_commands__, CommandSet.new)
|
19
19
|
base_klass.instance_variable_set(:@__container_instantiation_commands__, CommandSet.new)
|
20
|
-
base_klass.instance_variable_set(:@__container_definition_lock__,
|
20
|
+
base_klass.instance_variable_set(:@__container_definition_lock__, ArbitraryLock.new)
|
21
21
|
base_klass.singleton_class.send(:attr_reader, :__container_definition_commands__)
|
22
22
|
base_klass.singleton_class.send(:attr_reader, :__container_instantiation_commands__)
|
23
23
|
base_klass.extend(ClassMethods)
|
@@ -36,7 +36,7 @@ class SmartCore::Container
|
|
36
36
|
def inherited(child_klass)
|
37
37
|
child_klass.instance_variable_set(:@__container_definition_commands__, CommandSet.new)
|
38
38
|
child_klass.instance_variable_set(:@__container_instantiation_commands__, CommandSet.new)
|
39
|
-
child_klass.instance_variable_set(:@__container_definition_lock__,
|
39
|
+
child_klass.instance_variable_set(:@__container_definition_lock__, ArbitraryLock.new)
|
40
40
|
SmartCore::Container::DefinitionDSL::Inheritance.inherit(base: self, child: child_klass)
|
41
41
|
child_klass.singleton_class.prepend(ClassInheritance)
|
42
42
|
super
|
@@ -18,7 +18,7 @@ class SmartCore::Container::DefinitionDSL::CommandSet
|
|
18
18
|
# @since 0.1.0
|
19
19
|
def initialize
|
20
20
|
@commands = []
|
21
|
-
@access_lock = SmartCore::Container::
|
21
|
+
@access_lock = SmartCore::Container::ArbitraryLock.new
|
22
22
|
end
|
23
23
|
|
24
24
|
# @param [SmartCore::Container::DefinitionDSL::Commands::Base]
|
@@ -36,7 +36,7 @@ module SmartCore::Container::DefinitionDSL::Commands::Definition
|
|
36
36
|
# @since 0.1.0
|
37
37
|
# @version 0.2.0
|
38
38
|
def call(registry)
|
39
|
-
registry.register_dependency(dependency_name, memoize, &dependency_definition)
|
39
|
+
registry.register_dependency(dependency_name, memoize: memoize, &dependency_definition)
|
40
40
|
end
|
41
41
|
|
42
42
|
# @return [SmartCore::Container::DefinitionDSL::Commands::Definition::Register]
|
@@ -22,8 +22,57 @@ module SmartCore::Container::DependencyResolver
|
|
22
22
|
#
|
23
23
|
# @api private
|
24
24
|
# @since 0.1.0
|
25
|
+
# @version 0.8.1
|
25
26
|
def fetch(container, dependency_path)
|
26
|
-
container.registry.resolve(dependency_path).reveal
|
27
|
+
container.registry.resolve(dependency_path).reveal(container)
|
28
|
+
end
|
29
|
+
|
30
|
+
# @param container [SmartCore::Container]
|
31
|
+
# @param key [String, Symbol]
|
32
|
+
# @return [Boolean]
|
33
|
+
#
|
34
|
+
# @api private
|
35
|
+
# @since 0.5.0
|
36
|
+
def key?(container, key)
|
37
|
+
extract(container, key)
|
38
|
+
true
|
39
|
+
rescue SmartCore::Container::ResolvingError
|
40
|
+
false
|
41
|
+
end
|
42
|
+
|
43
|
+
# @param container [SmartCore::Container]
|
44
|
+
# @param namespace_path [String, Symbol]
|
45
|
+
# @return [Boolean]
|
46
|
+
#
|
47
|
+
# @api private
|
48
|
+
# @since 0.5.0
|
49
|
+
def namespace?(container, namespace_path)
|
50
|
+
extract(container, namespace_path).is_a?(SmartCore::Container::Entities::Namespace)
|
51
|
+
rescue SmartCore::Container::ResolvingError
|
52
|
+
false
|
53
|
+
end
|
54
|
+
|
55
|
+
# @param container [SmartCore::Container]
|
56
|
+
# @param dependency_path [String, Symbol]
|
57
|
+
# @option memoized [NilClass, Boolean]
|
58
|
+
# @return [Boolean]
|
59
|
+
#
|
60
|
+
# @api private
|
61
|
+
# @since 0.5.0
|
62
|
+
def dependency?(container, dependency_path, memoized: nil)
|
63
|
+
entity = extract(container, dependency_path)
|
64
|
+
|
65
|
+
case
|
66
|
+
when memoized.nil?
|
67
|
+
entity.is_a?(SmartCore::Container::Entities::Dependency)
|
68
|
+
when !!memoized == true
|
69
|
+
entity.is_a?(SmartCore::Container::Entities::MemoizedDependency)
|
70
|
+
when !!memoized == false
|
71
|
+
entity.is_a?(SmartCore::Container::Entities::Dependency) &&
|
72
|
+
!entity.is_a?(SmartCore::Container::Entities::MemoizedDependency)
|
73
|
+
end
|
74
|
+
rescue SmartCore::Container::ResolvingError
|
75
|
+
false
|
27
76
|
end
|
28
77
|
|
29
78
|
# @param container [SmartCore::Container]
|
@@ -38,13 +87,16 @@ module SmartCore::Container::DependencyResolver
|
|
38
87
|
#
|
39
88
|
# @api private
|
40
89
|
# @since 0.1.0
|
41
|
-
# @version 0.1
|
90
|
+
# @version 0.8.1
|
42
91
|
def resolve(container, dependency_path)
|
43
92
|
entity = container
|
93
|
+
host_container = container
|
94
|
+
|
44
95
|
Route.build(dependency_path).each do |cursor|
|
45
96
|
entity = entity.registry.resolve(cursor.current_path)
|
46
|
-
|
47
|
-
entity = entity.reveal
|
97
|
+
prevent_ambiguous_resolving!(cursor, entity)
|
98
|
+
entity = entity.reveal(host_container)
|
99
|
+
host_container = entity.is_a?(SmartCore::Container) ? entity : nil
|
48
100
|
end
|
49
101
|
entity
|
50
102
|
rescue SmartCore::Container::ResolvingError => error
|
@@ -53,6 +105,28 @@ module SmartCore::Container::DependencyResolver
|
|
53
105
|
|
54
106
|
private
|
55
107
|
|
108
|
+
# @param container [SmartCore::Container]
|
109
|
+
# @param entity_path [String, Symbol]
|
110
|
+
# @return [SmartCore::Container::Entities::Base]
|
111
|
+
#
|
112
|
+
# @api private
|
113
|
+
# @since 0.5.0
|
114
|
+
# @version 0.8.1
|
115
|
+
def extract(container, entity_path)
|
116
|
+
resolved_entity = container
|
117
|
+
extracted_entity = container
|
118
|
+
host_container = container
|
119
|
+
|
120
|
+
Route.build(entity_path).each do |cursor|
|
121
|
+
resolved_entity = resolved_entity.registry.resolve(cursor.current_path)
|
122
|
+
extracted_entity = resolved_entity
|
123
|
+
resolved_entity = resolved_entity.reveal(host_container)
|
124
|
+
host_container = resolved_entity.is_a?(SmartCore::Container) ? resolved_entity : nil
|
125
|
+
end
|
126
|
+
|
127
|
+
extracted_entity
|
128
|
+
end
|
129
|
+
|
56
130
|
# @param cursor [SmartCore::Container::DependencyResolver::Route::Cursor]
|
57
131
|
# @param entity [SmartCore::Container::Entities::Base]
|
58
132
|
# @return [void]
|
@@ -60,8 +134,8 @@ module SmartCore::Container::DependencyResolver
|
|
60
134
|
# @raise [SmartCore::Container::ResolvingError]
|
61
135
|
#
|
62
136
|
# @api private
|
63
|
-
# @since 0.
|
64
|
-
def
|
137
|
+
# @since 0.5.0
|
138
|
+
def prevent_ambiguous_resolving!(cursor, entity)
|
65
139
|
if cursor.last? && entity.is_a?(SmartCore::Container::Entities::Namespace)
|
66
140
|
raise(
|
67
141
|
SmartCore::Container::ResolvingError.new(
|
@@ -0,0 +1,151 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.8.0
|
5
|
+
class SmartCore::Container::DependencyWatcher
|
6
|
+
require_relative 'dependency_watcher/observer'
|
7
|
+
|
8
|
+
# @param container [SmartCore::Container]
|
9
|
+
# @return [void]
|
10
|
+
#
|
11
|
+
# @api private
|
12
|
+
# @since 0.8.0
|
13
|
+
def initialize(container)
|
14
|
+
@container = container
|
15
|
+
@observers = Hash.new { |h, k| h[k] = [] }
|
16
|
+
@access_lock = SmartCore::Container::ArbitraryLock.new
|
17
|
+
end
|
18
|
+
|
19
|
+
# @param entity_path [String, Symbol]
|
20
|
+
# @return [void]
|
21
|
+
#
|
22
|
+
# @api private
|
23
|
+
# @since 0.8.0
|
24
|
+
def notify(entity_path)
|
25
|
+
thread_safe { notify_listeners(entity_path) }
|
26
|
+
end
|
27
|
+
|
28
|
+
# @param entity_path [String, Symbol]
|
29
|
+
# @param observer [Block]
|
30
|
+
# @return [SmartCore::Container::DependencyWatcher::Observer]
|
31
|
+
#
|
32
|
+
# @api private
|
33
|
+
# @since 0.8.0
|
34
|
+
def watch(entity_path, &observer) # TODO: support for pattern-based pathes
|
35
|
+
thread_safe { listen(entity_path, observer) }
|
36
|
+
end
|
37
|
+
|
38
|
+
# @param observer [SmartCore::Container::DependencyWatcher::Observer]
|
39
|
+
# @return [Boolean]
|
40
|
+
#
|
41
|
+
# @api private
|
42
|
+
# @since 0.8.0
|
43
|
+
def unwatch(observer)
|
44
|
+
thread_safe { remove_listener(observer) }
|
45
|
+
end
|
46
|
+
|
47
|
+
# @param entity_path [String, Symbol, NilClass]
|
48
|
+
# @return [void]
|
49
|
+
#
|
50
|
+
# @api private
|
51
|
+
# @since 0.8.0
|
52
|
+
def clear_listeners(entity_path = nil) # TODO: support for pattern-based pathes
|
53
|
+
thread_safe { remove_listeners(entity_path) }
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
# @return [SmartCore::Container]
|
59
|
+
#
|
60
|
+
# @api private
|
61
|
+
# @since 0.8.0
|
62
|
+
attr_reader :container
|
63
|
+
|
64
|
+
# @return [Hash<String,SmartCore::Container::DependencyWatcher::Observer>]
|
65
|
+
#
|
66
|
+
# @api private
|
67
|
+
# @since 0.8.0
|
68
|
+
attr_reader :observers
|
69
|
+
|
70
|
+
# @param entity_path [String, Symbol]
|
71
|
+
# @return [void]
|
72
|
+
#
|
73
|
+
# @api private
|
74
|
+
# @since 0.8.0
|
75
|
+
# @version 0.8.1
|
76
|
+
def notify_listeners(entity_path)
|
77
|
+
entity_path = indifferently_accessable_path(entity_path)
|
78
|
+
observers.fetch(entity_path).each(&:notify!) if observers.key?(entity_path)
|
79
|
+
container.host.notify_about_nested_changement(entity_path)
|
80
|
+
end
|
81
|
+
|
82
|
+
# @param entity_path [String, Symbol]
|
83
|
+
# @param observer [Proc]
|
84
|
+
# @return [SmartCore::Container::DependencyWatcher::Observer]
|
85
|
+
#
|
86
|
+
# @api private
|
87
|
+
# @since 0.8.0
|
88
|
+
def listen(entity_path, observer) # TODO: support for pattern-based pathes
|
89
|
+
raise(SmartCore::Container::ArgumentError, <<~ERROR_MESSAGE) unless observer.is_a?(Proc)
|
90
|
+
Observer is missing: you should provide an observer proc object (block).
|
91
|
+
ERROR_MESSAGE
|
92
|
+
|
93
|
+
entity_path = indifferently_accessable_path(entity_path)
|
94
|
+
Observer.new(container, entity_path, observer).tap { |obs| observers[entity_path] << obs }
|
95
|
+
end
|
96
|
+
|
97
|
+
# @param observer [SmartCore::Container::DependencyWatcher::Observer]
|
98
|
+
# @return [Boolean]
|
99
|
+
#
|
100
|
+
# @api private
|
101
|
+
# @since 0.8.0
|
102
|
+
def remove_listener(observer)
|
103
|
+
unless observer.is_a?(SmartCore::Container::DependencyWatcher::Observer)
|
104
|
+
raise(SmartCore::Container::ArgumentError, <<~ERROR_MESSAGE)
|
105
|
+
You should provide an observer object for unsubscribion
|
106
|
+
(an instance of SmartCore::Container::DependencyWatcher::Observer).
|
107
|
+
ERROR_MESSAGE
|
108
|
+
end
|
109
|
+
|
110
|
+
unsubscribed = false
|
111
|
+
observers.each_value do |observer_list|
|
112
|
+
if observer_list.delete(observer)
|
113
|
+
unsubscribed = true
|
114
|
+
break
|
115
|
+
end
|
116
|
+
end
|
117
|
+
unsubscribed
|
118
|
+
end
|
119
|
+
|
120
|
+
# @param entity_path [String, Symbol]
|
121
|
+
# @return [void]
|
122
|
+
#
|
123
|
+
# @api private
|
124
|
+
# @since 0.8.0
|
125
|
+
def remove_listeners(entity_path) # TODO: support for pattern-based pathes
|
126
|
+
if entity_path.nil?
|
127
|
+
observers.each_value(&:clear)
|
128
|
+
else
|
129
|
+
entity_path = indifferently_accessable_path(entity_path)
|
130
|
+
observers[entity_path].clear if observers.key?(entity_path)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# @param entity_path [String, Symbol]
|
135
|
+
# @return [String]
|
136
|
+
#
|
137
|
+
# @api private
|
138
|
+
# @since 0.8.0
|
139
|
+
def indifferently_accessable_path(entity_path)
|
140
|
+
SmartCore::Container::KeyGuard.indifferently_accessable_key(entity_path)
|
141
|
+
end
|
142
|
+
|
143
|
+
# @param block [Block]
|
144
|
+
# @return [Any]
|
145
|
+
#
|
146
|
+
# @api private
|
147
|
+
# @since 0.8.0
|
148
|
+
def thread_safe(&block)
|
149
|
+
@access_lock.thread_safe(&block)
|
150
|
+
end
|
151
|
+
end
|