smart_container 0.4.0 → 0.8.1
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 +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
|