smart_core 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +1 -1
  3. data/.rubocop.yml +1 -1
  4. data/.travis.yml +5 -8
  5. data/CHANGELOG.md +5 -0
  6. data/README.md +14 -4
  7. data/lib/smart_core.rb +2 -2
  8. data/lib/smart_core/container.rb +49 -56
  9. data/lib/smart_core/container/arbitary_lock.rb +22 -0
  10. data/lib/smart_core/container/definition_dsl.rb +105 -55
  11. data/lib/smart_core/container/{command_set.rb → definition_dsl/command_set.rb} +20 -26
  12. data/lib/smart_core/container/definition_dsl/commands.rb +12 -0
  13. data/lib/smart_core/container/{commands → definition_dsl/commands}/base.rb +3 -3
  14. data/lib/smart_core/container/definition_dsl/commands/definition/compose.rb +46 -0
  15. data/lib/smart_core/container/definition_dsl/commands/definition/namespace.rb +51 -0
  16. data/lib/smart_core/container/{commands → definition_dsl/commands/definition}/register.rb +13 -25
  17. data/lib/smart_core/container/definition_dsl/commands/instantiation/compose.rb +50 -0
  18. data/lib/smart_core/container/definition_dsl/commands/instantiation/freeze_state.rb +24 -0
  19. data/lib/smart_core/container/dependency_compatability.rb +3 -3
  20. data/lib/smart_core/container/dependency_compatability/definition.rb +42 -0
  21. data/lib/smart_core/container/dependency_compatability/general.rb +61 -0
  22. data/lib/smart_core/container/dependency_compatability/registry.rb +28 -29
  23. data/lib/smart_core/container/dependency_resolver.rb +9 -4
  24. data/lib/smart_core/container/entities.rb +11 -0
  25. data/lib/smart_core/container/{entity.rb → entities/base.rb} +7 -7
  26. data/lib/smart_core/container/entities/dependency.rb +38 -0
  27. data/lib/smart_core/container/entities/dependency_builder.rb +50 -0
  28. data/lib/smart_core/container/entities/namespace.rb +73 -0
  29. data/lib/smart_core/container/entities/namespace_builder.rb +41 -0
  30. data/lib/smart_core/container/errors.rb +43 -0
  31. data/lib/smart_core/container/key_guard.rb +5 -5
  32. data/lib/smart_core/container/mixin.rb +20 -16
  33. data/lib/smart_core/container/registry.rb +224 -201
  34. data/lib/smart_core/container/registry_builder.rb +38 -5
  35. data/lib/smart_core/{exceptions.rb → errors.rb} +0 -0
  36. data/lib/smart_core/operation.rb +3 -1
  37. data/lib/smart_core/operation/{custom.rb → callback.rb} +7 -7
  38. data/lib/smart_core/operation/result.rb +1 -1
  39. data/lib/smart_core/operation/result_interface.rb +3 -3
  40. data/lib/smart_core/version.rb +1 -1
  41. data/smart_core.gemspec +6 -5
  42. metadata +28 -38
  43. data/lib/smart_core/container/command_definer.rb +0 -117
  44. data/lib/smart_core/container/commands.rb +0 -9
  45. data/lib/smart_core/container/commands/namespace.rb +0 -53
  46. data/lib/smart_core/container/dependency.rb +0 -44
  47. data/lib/smart_core/container/dependency_builder.rb +0 -48
  48. data/lib/smart_core/container/dependency_compatability/abstract.rb +0 -59
  49. data/lib/smart_core/container/dependency_compatability/command_set.rb +0 -35
  50. data/lib/smart_core/container/exceptions.rb +0 -31
  51. data/lib/smart_core/container/memoized_dependency.rb +0 -28
  52. data/lib/smart_core/container/namespace.rb +0 -51
@@ -1,36 +1,35 @@
1
1
  # frozen_string_literal: true
2
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
3
+ # @api private
4
+ # @since 0.7.0
5
+ module SmartCore::Container::DependencyCompatability::Registry
6
+ class << self
7
+ # @since 0.7.0
8
+ include SmartCore::Container::DependencyCompatability::General
9
+
10
+ # @param registry [SmartCore::Container::Registry]
11
+ # @param dependency_name [String, Symbol]
12
+ # @return [Boolean]
13
+ #
14
+ # @api private
15
+ # @since 0.7.0
16
+ def potential_namespace_overlap?(registry, dependency_name)
17
+ registry.any? do |(entity_name, entity)|
18
+ next unless entity.is_a?(SmartCore::Container::Entities::Namespace)
19
+ entity.namespace_name == dependency_name
20
20
  end
21
+ end
21
22
 
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
23
+ # @param registry [SmartCore::Container::Registry]
24
+ # @param namespace_name [String, Symbol]
25
+ # @return [Boolean]
26
+ #
27
+ # @api private
28
+ # @since 0.7.0
29
+ def potential_dependency_overlap?(registry, namespace_name)
30
+ registry.any? do |(entity_name, entity)|
31
+ next unless entity.is_a?(SmartCore::Container::Entities::Dependency)
32
+ entity.dependency_name == namespace_name
34
33
  end
35
34
  end
36
35
  end
@@ -1,16 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # @api private
4
- # @since 0.5.0
4
+ # @since 0.7.0
5
5
  module SmartCore::Container::DependencyResolver
6
6
  class << self
7
7
  # @param registry [SmartCore::Container::Registry]
8
- # @return [Any]
8
+ # @param dependency_path [String, Symbol]
9
+ # @return [SmartCore::Container, Any]
10
+ #
11
+ # @see SmartCore::Container::Registry#resolve
12
+ # @see SmartCore::Container::Entities::Namespace#resolve
13
+ # @see SmartCore::Container::Entities::Dependency#resolve
9
14
  #
10
15
  # @api private
11
- # @since 0.5.0
16
+ # @since 0.7.0
12
17
  def resolve(registry, dependency_path)
13
- registry.resolve(dependency_path).call
18
+ registry.resolve(dependency_path).resolve
14
19
  end
15
20
  end
16
21
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.7.0
5
+ module SmartCore::Container::Entities
6
+ require_relative 'entities/base'
7
+ require_relative 'entities/dependency'
8
+ require_relative 'entities/dependency_builder'
9
+ require_relative 'entities/namespace'
10
+ require_relative 'entities/namespace_builder'
11
+ end
@@ -1,26 +1,26 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # @api private
4
- # @since 0.5.0
5
- class SmartCore::Container::Entity
4
+ # @since 0.7.0
5
+ class SmartCore::Container::Entities::Base
6
6
  # @return [String]
7
7
  #
8
8
  # @api private
9
- # @since 0.5.0
9
+ # @since 0.7.0
10
10
  attr_reader :external_name
11
11
 
12
12
  # @param external_name [String]
13
13
  # @return [void]
14
14
  #
15
15
  # @api private
16
- # @since 0.5.0
16
+ # @since 0.7.0
17
17
  def initialize(external_name)
18
18
  @external_name = external_name
19
19
  end
20
20
 
21
- # @return [void]
21
+ # @return [Any]
22
22
  #
23
23
  # @api private
24
- # @since 0.5.0
25
- def call; end
24
+ # @since 0.7.0
25
+ def resolve; end
26
26
  end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.7.0
5
+ class SmartCore::Container::Entities::Dependency < SmartCore::Container::Entities::Base
6
+ # @return [String]
7
+ #
8
+ # @api private
9
+ # @sicne 0.7.0
10
+ alias_method :dependency_name, :external_name
11
+
12
+ # @param dependency_name [String]
13
+ # @param dependency_definition [Proc]
14
+ # @return [void]
15
+ #
16
+ # @api private
17
+ # @since 0.7.0
18
+ def initialize(dependency_name, dependency_definition)
19
+ super(dependency_name)
20
+ @dependency_definition = dependency_definition
21
+ end
22
+
23
+ # @return [Any]
24
+ #
25
+ # @api private
26
+ # @since 0.7.0
27
+ def resolve
28
+ dependency_definition.call
29
+ end
30
+
31
+ private
32
+
33
+ # @return [Proc]
34
+ #
35
+ # @api private
36
+ # @since 0.7.0
37
+ attr_reader :dependency_definition
38
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.7.0
5
+ class SmartCore::Container::Entities::DependencyBuilder
6
+ class << self
7
+ # @param dependency_name [String]
8
+ # @param dependency_definition [Proc]
9
+ # @return [SmartCore::Container::Entities::Dependency]
10
+ #
11
+ # @api private
12
+ # @since 0.7.0
13
+ def build(dependency_name, dependency_definition)
14
+ new(dependency_name, dependency_definition).build
15
+ end
16
+ end
17
+
18
+ # @param dependency_name [String]
19
+ # @param dependency_definition [Proc]
20
+ # @return [void]
21
+ #
22
+ # @api private
23
+ # @since 0.7.0
24
+ def initialize(dependency_name, dependency_definition)
25
+ @dependency_name = dependency_name
26
+ @dependency_definition = dependency_definition
27
+ end
28
+
29
+ # @return [SmartCore::Container::Entities::Dependency]
30
+ #
31
+ # @api private
32
+ # @since 0.7.0
33
+ def build
34
+ SmartCore::Container::Entities::Dependency.new(dependency_name, dependency_definition)
35
+ end
36
+
37
+ private
38
+
39
+ # @return [String]
40
+ #
41
+ # @api private
42
+ # @since 0.7.0
43
+ attr_reader :dependency_name
44
+
45
+ # @return [Proc]
46
+ #
47
+ # @api private
48
+ # @since 0.7.0
49
+ attr_reader :dependency_definition
50
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.7.0
5
+ class SmartCore::Container::Entities::Namespace < SmartCore::Container::Entities::Base
6
+ # @return [String]
7
+ #
8
+ # @api private
9
+ # @since 0.7.0
10
+ alias_method :namespace_name, :external_name
11
+
12
+ # @param namespace_name [String]
13
+ # @return [void]
14
+ #
15
+ # @api private
16
+ # @since 0.7.0
17
+ def initialize(namespace_name)
18
+ super(namespace_name)
19
+ @container_klass = Class.new(SmartCore::Container)
20
+ @container_instance = nil
21
+ @lock = SmartCore::Container::ArbitaryLock.new
22
+ end
23
+
24
+ # @return [SmartCore::Container]
25
+ #
26
+ # @api private
27
+ # @since 0.7.0
28
+ def resolve
29
+ thread_safe { container_instance }
30
+ end
31
+
32
+ # @param dependencies_definition [Proc]
33
+ # @return [void]
34
+ #
35
+ # @api private
36
+ # @since 0.7.0
37
+ def append_definitions(dependencies_definition)
38
+ thread_safe { container_klass.instance_eval(&dependencies_definition) }
39
+ end
40
+
41
+ # @return [void]
42
+ #
43
+ # @api private
44
+ # @since 0.7.0
45
+ def freeze!
46
+ thread_safe { container_instance.freeze! }
47
+ end
48
+
49
+ private
50
+
51
+ # @return [Class<SmartCore::Container>]
52
+ #
53
+ # @api private
54
+ # @since 0.7.0
55
+ attr_reader :container_klass
56
+
57
+ # @return [SmartCore::Container]
58
+ #
59
+ # @api private
60
+ # @since 0.7.0
61
+ def container_instance
62
+ @container_instance ||= container_klass.new
63
+ end
64
+
65
+ # @param block [Block]
66
+ # @return [Any]
67
+ #
68
+ # @api private
69
+ # @since 0.7.0
70
+ def thread_safe(&block)
71
+ @lock.thread_safe(&block)
72
+ end
73
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.7.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.7.0
12
+ def build(namespace_name)
13
+ new(namespace_name).build
14
+ end
15
+ end
16
+
17
+ # @param namespace_name [String]
18
+ # @return [void]
19
+ #
20
+ # @api private
21
+ # @since 0.7.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.7.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.7.0
40
+ attr_reader :namespace_name
41
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ class SmartCore::Container
4
+ # @api public
5
+ # @since 0.7.0
6
+ Error = Class.new(SmartCore::Error)
7
+
8
+ # @api public
9
+ # @since 0.7.0
10
+ ArgumentError = Class.new(SmartCore::ArgumentError)
11
+
12
+ # @api public
13
+ # @since 0.7.0
14
+ IncompatibleEntityNameError = Class.new(ArgumentError)
15
+
16
+ # @see SmartCore::Container::Registry
17
+ #
18
+ # @api public
19
+ # @since 0.7.0
20
+ FrozenRegistryError = Class.new(SmartCore::FrozenError)
21
+
22
+ # @see SmartCore::Container::Registry
23
+ #
24
+ # @api public
25
+ # @since 0.7.0
26
+ NonexistentEntityError = Class.new(Error)
27
+
28
+ # @see SmartCore::Container::DependencyCompatability::General
29
+ # @see SmartCore::Container::DependencyCompatability::Definition
30
+ # @see SmartCore::Container::DependencyCompatability::Registry
31
+ #
32
+ # @api public
33
+ # @since 0.7.0
34
+ DependencyOverNamespaceOverlapError = Class.new(Error)
35
+
36
+ # @see SmartCore::Container::DependencyCompatability::General
37
+ # @see SmartCore::Container::DependencyCompatability::Definition
38
+ # @see SmartCore::Container::DependencyCompatability::Registry
39
+ #
40
+ # @api public
41
+ # @since 0.7.0
42
+ NamespaceOverDependencyOverlapError = Class.new(Error)
43
+ end
@@ -1,19 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # @api priavate
4
- # @since 0.5.0
4
+ # @since 0.7.0
5
5
  module SmartCore::Container::KeyGuard
6
6
  class << self
7
7
  # @param key [Symbol, String]
8
8
  # @return [void]
9
9
  #
10
- # @raise [SmartCore::Container::ArgumentError]
10
+ # @raise [SmartCore::Container::IncompatibleEntityNameError]
11
11
  #
12
12
  # @api private
13
- # @since 0.5.0
13
+ # @since 0.7.0
14
14
  def prevent_incomparabilities!(key)
15
15
  raise(
16
- SmartCore::Container::ArgumentError,
16
+ SmartCore::Container::IncompatibleEntityNameError,
17
17
  'Namespace/Dependency name should be a symbol or a string'
18
18
  ) unless key.is_a?(String) || key.is_a?(Symbol)
19
19
  end
@@ -22,7 +22,7 @@ module SmartCore::Container::KeyGuard
22
22
  # @return [String]
23
23
  #
24
24
  # @api private
25
- # @since 0.5.0
25
+ # @since 0.7.0
26
26
  def indifferently_accessable_key(key)
27
27
  prevent_incomparabilities!(key)
28
28
  key.to_s
@@ -1,18 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # @api public
4
- # @since 0.5.0
4
+ # @since 0.7.0
5
5
  module SmartCore::Container::Mixin
6
6
  class << self
7
7
  # @param base_klass [Class]
8
8
  # @return [void]
9
9
  #
10
10
  # @api private
11
- # @since 0.5.0
11
+ # @since 0.7.0
12
12
  def included(base_klass)
13
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)
14
+ base_klass.instance_variable_set(:@__smart_core_container_access_lock__, SmartCore::Container::ArbitaryLock.new)
16
15
  base_klass.instance_variable_set(:@__smart_core_container_klass__, Class.new(SmartCore::Container))
17
16
  base_klass.instance_variable_set(:@__smart_core_container__, nil)
18
17
  # rubocop:enable Metrics/LineLength
@@ -24,57 +23,62 @@ module SmartCore::Container::Mixin
24
23
  end
25
24
 
26
25
  # @api private
27
- # @since 0.5.0
26
+ # @since 0.7.0
28
27
  module ClassInheritance
29
28
  # @param child_klass [CLass]
30
29
  # @return [void]
31
30
  #
32
31
  # @api private
33
- # @since 0.5.0
32
+ # @since 0.7.0
34
33
  def inherited(child_klass)
35
34
  inherited_container_klass = Class.new(@__smart_core_container_klass__)
36
35
 
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)
36
+ # rubocop:disable Metrics/LineLength
37
+ child_klass.instance_variable_set(:@__smart_core_container_access_lock__, SmartCore::Container::ArbitaryLock.new)
39
38
  child_klass.instance_variable_set(:@__smart_core_container_klass__, inherited_container_klass)
40
39
  child_klass.instance_variable_set(:@__smart_core_container__, nil)
40
+ # rubocop:disable Metrics/LineLength
41
41
 
42
42
  super
43
43
  end
44
44
  end
45
45
 
46
46
  # @api private
47
- # @since 0.5.0
47
+ # @since 0.7.0
48
48
  module ClassMethods
49
+ # @param freeze_state [Boolean]
49
50
  # @param block [Proc]
50
51
  # @return [void]
51
52
  #
52
53
  # @api public
53
- # @since 0.5.0
54
- def dependencies(&block)
55
- @__smart_core_container_definition_lock__.synchronize do
54
+ # @since 0.7.0
55
+ def dependencies(freeze_state: false, &block)
56
+ @__smart_core_container_access_lock__.thread_safe do
56
57
  @__smart_core_container_klass__.instance_eval(&block) if block_given?
58
+ @__smart_core_container_klass__.instance_eval do
59
+ freeze_state!
60
+ end if freeze_state
57
61
  end
58
62
  end
59
63
 
60
64
  # @return [SmartCore::Container]
61
65
  #
62
66
  # @api public
63
- # @since 0.5.0
67
+ # @since 0.7.0
64
68
  def container
65
- @__smart_core_container_definition_lock__.synchronize do
69
+ @__smart_core_container_access_lock__.thread_safe do
66
70
  @__smart_core_container__ ||= @__smart_core_container_klass__.new
67
71
  end
68
72
  end
69
73
  end
70
74
 
71
75
  # @api private
72
- # @since 0.5.0
76
+ # @since 0.7.0
73
77
  module InstanceMethods
74
78
  # @return [SmartCore::Container]
75
79
  #
76
80
  # @api public
77
- # @since 0.5.0
81
+ # @since 0.7.0
78
82
  def container
79
83
  self.class.container
80
84
  end