smart_container 0.5.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.8.0
5
+ class SmartCore::Container::DependencyWatcher::Observer
6
+ # @param container [SmartCore::Container]
7
+ # @param dependency_path [String]
8
+ # @param callback [Proc]
9
+ # @return [void]
10
+ #
11
+ # @api private
12
+ # @since 0.8.0
13
+ def initialize(container, dependency_path, callback)
14
+ @container = container
15
+ @dependency_path = dependency_path
16
+ @callback = callback
17
+ end
18
+
19
+ # @return [void]
20
+ #
21
+ # @api private
22
+ # @since 0.8.0
23
+ def notify!
24
+ callback.call(dependency_path, container)
25
+ end
26
+
27
+ private
28
+
29
+ # @return [SmartCore::Container]
30
+ #
31
+ # @api private
32
+ # @since 0.8.0
33
+ attr_reader :container
34
+
35
+ # @return [String]
36
+ #
37
+ # @api private
38
+ # @since 0.8.0
39
+ attr_reader :dependency_path
40
+
41
+ # @return [Proc]
42
+ #
43
+ # @api private
44
+ # @since 0.8.0
45
+ attr_reader :callback
46
+ end
@@ -20,11 +20,13 @@ class SmartCore::Container::Entities::Dependency < SmartCore::Container::Entitie
20
20
  @dependency_definition = dependency_definition
21
21
  end
22
22
 
23
+ # @param host_container [SmartCore::Container, NilClass]
23
24
  # @return [Any]
24
25
  #
25
26
  # @api private
26
27
  # @since 0.1.0
27
- def reveal
28
+ # @version 0.8.1
29
+ def reveal(host_container = SmartCore::Container::NO_HOST_CONTAINER)
28
30
  dependency_definition.call
29
31
  end
30
32
 
@@ -2,7 +2,8 @@
2
2
 
3
3
  # @api private
4
4
  # @since 0.1.0
5
- class SmartCore::Container::Entities::DependencyBuilder
5
+ # @version 0.8.1
6
+ module SmartCore::Container::Entities::DependencyBuilder
6
7
  class << self
7
8
  # @param dependency_name [String]
8
9
  # @param dependency_definition [Proc]
@@ -11,68 +12,35 @@ class SmartCore::Container::Entities::DependencyBuilder
11
12
  #
12
13
  # @api private
13
14
  # @since 0.1.0
14
- # @version 0.2.0
15
+ # @version 0.8.1
15
16
  def build(dependency_name, dependency_definition, memoize)
16
- new(dependency_name, dependency_definition, memoize).build
17
+ if memoize
18
+ build_memoized_dependency(dependency_name, dependency_definition)
19
+ else
20
+ build_original_dependency(dependency_name, dependency_definition)
21
+ end
17
22
  end
18
- end
19
-
20
- # @param dependency_name [String]
21
- # @param dependency_definition [Proc]
22
- # @param memoize [Boolean]
23
- # @return [void]
24
- #
25
- # @api private
26
- # @since 0.1.0
27
- # @version 0.2.0
28
- def initialize(dependency_name, dependency_definition, memoize)
29
- @dependency_name = dependency_name
30
- @dependency_definition = dependency_definition
31
- @memoize = memoize
32
- end
33
-
34
- # @return [SmartCore::Container::Entities::Dependency]
35
- #
36
- # @api private
37
- # @since 0.1.0
38
- # @version 0.2.0
39
- def build
40
- memoize ? build_memoized_dependency : build_original_dependency
41
- end
42
-
43
- private
44
23
 
45
- # @return [String]
46
- #
47
- # @api private
48
- # @since 0.1.0
49
- attr_reader :dependency_name
24
+ private
50
25
 
51
- # @return [Proc]
52
- #
53
- # @api private
54
- # @since 0.1.0
55
- attr_reader :dependency_definition
56
-
57
- # @return [Boolean]
58
- #
59
- # @api private
60
- # @since 0.2.0
61
- attr_reader :memoize
62
-
63
- # @return [SmartCore::Container::Entities::Dependency]
64
- #
65
- # @api private
66
- # @since 0.2.0
67
- def build_memoized_dependency
68
- SmartCore::Container::Entities::MemoizedDependency.new(dependency_name, dependency_definition)
69
- end
26
+ # @param dependency_name [String]
27
+ # @param dependency_definition [Proc]
28
+ # @return [SmartCore::Container::Entities::Dependency]
29
+ #
30
+ # @api private
31
+ # @since 0.8.1
32
+ def build_memoized_dependency(dependency_name, dependency_definition)
33
+ SmartCore::Container::Entities::MemoizedDependency.new(dependency_name, dependency_definition)
34
+ end
70
35
 
71
- # @return [SmartCore::Container::Entities::Dependency]
72
- #
73
- # @api private
74
- # @since 0.2.0
75
- def build_original_dependency
76
- SmartCore::Container::Entities::Dependency.new(dependency_name, dependency_definition)
36
+ # @param dependency_name [String]
37
+ # @param dependency_definition [Proc]
38
+ # @return [SmartCore::Container::Entities::Dependency]
39
+ #
40
+ # @api private
41
+ # @since 0.8.1
42
+ def build_original_dependency(dependency_name, dependency_definition)
43
+ SmartCore::Container::Entities::Dependency.new(dependency_name, dependency_definition)
44
+ end
77
45
  end
78
46
  end
@@ -12,14 +12,16 @@ module SmartCore::Container::Entities
12
12
  # @since 0.2.0
13
13
  def initialize(dependency_name, dependency_definition)
14
14
  super(dependency_name, dependency_definition)
15
- @lock = SmartCore::Container::ArbitaryLock.new
15
+ @lock = SmartCore::Container::ArbitraryLock.new
16
16
  end
17
17
 
18
+ # @param host_container [SmartCore::Container, NilClass]
18
19
  # @return [Any]
19
20
  #
20
21
  # @api private
21
22
  # @since 0.2.0
22
- def reveal
23
+ # @version 0.8.1
24
+ def reveal(host_container = SmartCore::Container::NO_HOST_CONTAINER)
23
25
  @lock.thread_safe do
24
26
  unless instance_variable_defined?(:@revealed_dependency)
25
27
  @revealed_dependency = dependency_definition.call
@@ -9,24 +9,35 @@ class SmartCore::Container::Entities::Namespace < SmartCore::Container::Entities
9
9
  # @since 0.1.0
10
10
  alias_method :namespace_name, :external_name
11
11
 
12
+ # @return [NilClass, SmartCore::Container]
13
+ #
14
+ # @api private
15
+ # @since 0.8.01
16
+ attr_reader :host_container
17
+
12
18
  # @param namespace_name [String]
19
+ # @param host_container [NilClass, SmartCore::Container]
13
20
  # @return [void]
14
21
  #
15
22
  # @api private
16
23
  # @since 0.1.0
17
- def initialize(namespace_name)
24
+ # @version 0.8.1
25
+ def initialize(namespace_name, host_container = SmartCore::Container::NO_HOST_CONTAINER)
18
26
  super(namespace_name)
19
27
  @container_klass = Class.new(SmartCore::Container)
20
28
  @container_instance = nil
21
- @lock = SmartCore::Container::ArbitaryLock.new
29
+ @host_container = host_container
30
+ @lock = SmartCore::Container::ArbitraryLock.new
22
31
  end
23
32
 
33
+ # @param runtime_host_container [SmartCore::Container, NilClass]
24
34
  # @return [SmartCore::Container]
25
35
  #
26
36
  # @api private
27
37
  # @since 0.1.0
28
- def reveal
29
- thread_safe { container_instance }
38
+ # @version 0.8.1
39
+ def reveal(runtime_host_container = SmartCore::Container::NO_HOST_CONTAINER)
40
+ thread_safe { container_instance(runtime_host_container) }
30
41
  end
31
42
 
32
43
  # @param dependencies_definition [Proc]
@@ -54,12 +65,18 @@ class SmartCore::Container::Entities::Namespace < SmartCore::Container::Entities
54
65
  # @since 0.1.0
55
66
  attr_reader :container_klass
56
67
 
68
+ # @param runtime_host_container [SmartCore::Container, NilClass]
57
69
  # @return [SmartCore::Container]
58
70
  #
59
71
  # @api private
60
72
  # @since 0.1.0
61
- def container_instance
62
- @container_instance ||= container_klass.new
73
+ # @version 0.8.1
74
+ def container_instance(runtime_host_container = SmartCore::Container::NO_HOST_CONTAINER)
75
+ @host_container ||= runtime_host_container
76
+ @container_instance ||= container_klass.new(
77
+ host_container: @host_container,
78
+ host_path: @host_container && namespace_name
79
+ )
63
80
  end
64
81
 
65
82
  # @param block [Block]
@@ -2,40 +2,20 @@
2
2
 
3
3
  # @api private
4
4
  # @since 0.1.0
5
- class SmartCore::Container::Entities::NamespaceBuilder
6
- class << self
7
- # @param namespace_name [String]
8
- # @return [SmartCore::Container::Entities::Namespace]
9
- #
10
- # @api private
11
- # @since 0.1.0
12
- def build(namespace_name)
13
- new(namespace_name).build
5
+ # @version 0.8.1
6
+ module SmartCore::Container::Entities
7
+ module NamespaceBuilder
8
+ class << self
9
+ # @param namespace_name [String]
10
+ # @param host_container [SmartContainer, NilClass]
11
+ # @return [SmartCore::Container::Entities::Namespace]
12
+ #
13
+ # @api private
14
+ # @since 0.1.0
15
+ # @version 0.8.1
16
+ def build(namespace_name, host_container = SmartCore::Container::NO_HOST_CONTAINER)
17
+ SmartCore::Container::Entities::Namespace.new(namespace_name, host_container)
18
+ end
14
19
  end
15
20
  end
16
-
17
- # @param namespace_name [String]
18
- # @return [void]
19
- #
20
- # @api private
21
- # @since 0.1.0
22
- def initialize(namespace_name)
23
- @namespace_name = namespace_name
24
- end
25
-
26
- # @return [SmartCore::Container::Entities::Namespace]
27
- #
28
- # @api private
29
- # @since 0.1.0
30
- def build
31
- SmartCore::Container::Entities::Namespace.new(namespace_name)
32
- end
33
-
34
- private
35
-
36
- # @return [String]
37
- #
38
- # @api private
39
- # @since 0.1.0
40
- attr_reader :namespace_name
41
21
  end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ using SmartCore::Ext::BasicObjectAsObject
4
+
5
+ # @api private
6
+ # @since 0.8.1
7
+ class SmartCore::Container::Host
8
+ class << self
9
+ # @param container [SmartCore::Container]
10
+ # @param path [String]
11
+ # @return [SmartCore::Container::Host]
12
+ #
13
+ # @api private
14
+ # @since 0.8.1
15
+ # rubocop:disable Metrics/AbcSize, Style/NilComparison
16
+ def build(container, path)
17
+ if (container.nil? && !path.nil?) || (!container.nil? && path.nil?)
18
+ raise(SmartCore::Container::ArgumentError, <<~ERROR_MESSAGE)
19
+ Host container requires both host container instance and host container path
20
+ (container: #{container.inspect} / path: #{path.inspect})
21
+ ERROR_MESSAGE
22
+ end
23
+
24
+ if (!container.nil? && !path.nil?) &&
25
+ (!container.is_a?(SmartCore::Container) || !path.is_a?(String))
26
+ raise(SmartCore::Container::ArgumentError, <<~ERROR_MESSAGE)
27
+ Host container should be a type of SmartCore::Container
28
+ and host path should be a type of String.
29
+ ERROR_MESSAGE
30
+ end
31
+
32
+ new(container, path)
33
+ end
34
+ # rubocop:enable Metrics/AbcSize, Style/NilComparison
35
+ end
36
+
37
+ # @return [SmartCore::Container]
38
+ #
39
+ # @api private
40
+ # @since 0.8.1
41
+ attr_reader :container
42
+
43
+ # @return [String]
44
+ #
45
+ # @api private
46
+ # @since 0.8.1
47
+ attr_reader :path
48
+
49
+ # @return [Boolean]
50
+ #
51
+ # @api private
52
+ # @since 0.8.1
53
+ attr_reader :exists
54
+ alias_method :exists?, :exists
55
+ alias_method :present?, :exists
56
+
57
+ # @param container [SmartCore::Container]
58
+ # @param path [String]
59
+ # @return [void]
60
+ #
61
+ # @api private
62
+ # @since 0.8.1
63
+ def initialize(container, path)
64
+ @container = container
65
+ @path = path
66
+ @exists = !!container
67
+ end
68
+
69
+ # @param nested_entity_path [String]
70
+ # @return [void]
71
+ #
72
+ # @api private
73
+ # @since 0.8.1
74
+ def notify_about_nested_changement(nested_entity_path)
75
+ return unless exists?
76
+ host_path = "#{path}" \
77
+ "#{SmartCore::Container::DependencyResolver::PATH_PART_SEPARATOR}" \
78
+ "#{nested_entity_path}"
79
+ container.watcher.notify(host_path)
80
+ end
81
+ end
@@ -11,7 +11,7 @@ module SmartCore::Container::Mixin
11
11
  # @since 0.1.0
12
12
  def included(base_klass)
13
13
  # rubocop:disable Layout/LineLength
14
- base_klass.instance_variable_set(:@__smart_core_container_access_lock__, SmartCore::Container::ArbitaryLock.new)
14
+ base_klass.instance_variable_set(:@__smart_core_container_access_lock__, SmartCore::Container::ArbitraryLock.new)
15
15
  base_klass.instance_variable_set(:@__smart_core_container_klass__, Class.new(SmartCore::Container))
16
16
  base_klass.instance_variable_set(:@__smart_core_container__, nil)
17
17
  # rubocop:enable Layout/LineLength
@@ -34,7 +34,7 @@ module SmartCore::Container::Mixin
34
34
  inherited_container_klass = Class.new(@__smart_core_container_klass__)
35
35
 
36
36
  # rubocop:disable Layout/LineLength
37
- child_klass.instance_variable_set(:@__smart_core_container_access_lock__, SmartCore::Container::ArbitaryLock.new)
37
+ child_klass.instance_variable_set(:@__smart_core_container_access_lock__, SmartCore::Container::ArbitraryLock.new)
38
38
  child_klass.instance_variable_set(:@__smart_core_container_klass__, inherited_container_klass)
39
39
  child_klass.instance_variable_set(:@__smart_core_container__, nil)
40
40
  # rubocop:enable Layout/LineLength
@@ -37,7 +37,7 @@ class SmartCore::Container::Registry
37
37
  # @since 0.1.0
38
38
  def initialize
39
39
  @registry = {}
40
- @access_lock = SmartCore::Container::ArbitaryLock.new
40
+ @access_lock = SmartCore::Container::ArbitraryLock.new
41
41
  end
42
42
 
43
43
  # @param entity_path [String, Symbol]
@@ -57,18 +57,24 @@ class SmartCore::Container::Registry
57
57
  # @api private
58
58
  # @since 0.1.0
59
59
  # @version 0.3.0
60
- def register_dependency(name, memoize = DEFAULT_MEMOIZATION_BEHAVIOR, &dependency_definition)
60
+ def register_dependency(name, memoize: DEFAULT_MEMOIZATION_BEHAVIOR, &dependency_definition)
61
61
  thread_safe { add_dependency(name, dependency_definition, memoize) }
62
62
  end
63
63
 
64
64
  # @param name [String, Symbol]
65
+ # @param host_container [NilClasss, SmartCore::Container]
65
66
  # @param dependencies_definition [Block]
66
67
  # @return [void]
67
68
  #
68
69
  # @api private
69
70
  # @since 0.1.0
70
- def register_namespace(name, &dependencies_definition)
71
- thread_safe { add_namespace(name, dependencies_definition) }
71
+ # @version 0.8.1
72
+ def register_namespace(
73
+ name,
74
+ host_container = SmartCore::Container::NO_HOST_CONTAINER,
75
+ &dependencies_definition
76
+ )
77
+ thread_safe { add_namespace(name, host_container, dependencies_definition) }
72
78
  end
73
79
 
74
80
  # @return [void]
@@ -223,6 +229,7 @@ class SmartCore::Container::Registry
223
229
  end
224
230
 
225
231
  # @param namespace_name [String, Symbol]
232
+ # @param host_container [NilClass, SmartCore::Container]
226
233
  # @param dependencies_definition [Proc]
227
234
  # @return [SmartCore::Container::Entities::Namespace]
228
235
  #
@@ -230,25 +237,26 @@ class SmartCore::Container::Registry
230
237
  #
231
238
  # @api private
232
239
  # @since 0.1.0
233
- def add_namespace(namespace_name, dependencies_definition)
240
+ # @version 0.8.1
241
+ # rubocop:disable Lint/EmptyBlock
242
+ def add_namespace(namespace_name, host_container, dependencies_definition)
234
243
  if state_frozen?
235
244
  raise(SmartCore::Container::FrozenRegistryError, 'Can not modify frozen registry!')
236
245
  end
237
246
  namespace_name = indifferently_accessable_name(namespace_name)
247
+ dependencies_definition ||= proc {}
238
248
  prevent_dependency_overlap!(namespace_name)
239
249
 
240
- # rubocop:disable Layout/RescueEnsureAlignment
241
250
  namespace_entity = begin
242
251
  fetch_entity(namespace_name)
243
252
  rescue SmartCore::Container::FetchError
244
253
  registry[namespace_name] = SmartCore::Container::Entities::NamespaceBuilder.build(
245
- namespace_name
254
+ namespace_name, host_container
246
255
  )
247
256
  end
248
- # rubocop:enable Layout/RescueEnsureAlignment
249
-
250
257
  namespace_entity.tap { namespace_entity.append_definitions(dependencies_definition) }
251
258
  end
259
+ # rubocop:enable Lint/EmptyBlock
252
260
 
253
261
  # @param root_dependency_name [String, NilClass]
254
262
  # @param block [Block]