smart_container 0.5.0 → 0.9.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.
@@ -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]