smart_core 0.7.0 → 0.8.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 19dd6183688e0576100f7178ad66764ca76d1461c459eaeb239815c1b75a2d30
4
- data.tar.gz: 34419b8bac8cc0e409c823282320fadf14f562225a5c4dd62545c4270b298919
3
+ metadata.gz: 3ca3b0d1486eb3331a2d09f642d63c5557fa56aba7927eba276f5cdf1ea27ccb
4
+ data.tar.gz: ea3f79d0fa9471d4bf3ebe4558c3bbd7bb508b925d1265a6ac749a1a2a15bcf5
5
5
  SHA512:
6
- metadata.gz: '06718cef684bec320e3fa67d83e9486df6c991571fcabe6fad48a2a7063f554499e46a7c231bc37edb8dcb2325daf9004ae293f3e736e85f73a6eb6c791d7a74'
7
- data.tar.gz: d13ec368c4bed72a132f1de1963c322383e8ad7d5168c3da188a13b649f7ec1cc27da080cc917b0c5c30c344436847229dd7bf92b429d6cd499dc77557274070
6
+ metadata.gz: ff087931c4a69cfeedabbaf8ab7b96645a47c3ceec7ad78ec0475f2d6229faf45a20aae9d17febf12e23b4090edcae34056f6c9f386be22a1fd2515ebe5f3aaf
7
+ data.tar.gz: 6cea80b530a0e742c67b58de15c23d06b0de7cc92337920ec19d6849b765a1fe61f7d0b7a9d2b4653ed36c199143c5d9401cf07710b1fef0c966bbb0c64497e5
@@ -1,6 +1,17 @@
1
1
  # Changelog
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
+ ## [0.8.0] - 2019-11-14
5
+ ### Added
6
+ - [**SmartCore::Container**]
7
+ - support for `dot-notation`;
8
+
9
+ ### Changed
10
+ - [**SmartCore::Container**]
11
+ - new `#resolve`: now supports only the dot-notated invokation style;
12
+ - old `#resolve` renamed to `#fetch`;
13
+ - added `#[](dependency_path)` - an alias for `#resolve`;
14
+
4
15
  ## [0.7.0] - 2019-11-10
5
16
  ### Changed
6
17
  - `SmartCore::Operation::Custom` result type is renamed to `SmartCore::Operation::Callback`;
data/README.md CHANGED
@@ -38,7 +38,7 @@ require 'smart_core'
38
38
  - Schema Structure Validator (`SmartCore::Schema`);
39
39
  - Saga (`SmartCore::Saga`);
40
40
  - External Type System (`SmartCore::Types`);
41
- - Step-like execution behavior for `SmartCore::Operation` (`.step`);
41
+ - Step-like execution behavior for `SmartCore::Operation` (`.step`, `SmartCore::Railway`);
42
42
  - Automatic result instantiation and handling for `SmartCore::Operation`;
43
43
 
44
44
  ---
data/Rakefile CHANGED
@@ -6,6 +6,7 @@ require 'rubocop'
6
6
  require 'rubocop-rspec'
7
7
  require 'rubocop-performance'
8
8
  require 'rubocop/rake_task'
9
+ require 'rubocop-rake'
9
10
 
10
11
  RuboCop::RakeTask.new(:rubocop) do |t|
11
12
  config_path = File.expand_path(File.join('.rubocop.yml'), __dir__)
@@ -13,6 +14,7 @@ RuboCop::RakeTask.new(:rubocop) do |t|
13
14
  t.options = ['--config', config_path]
14
15
  t.requires << 'rubocop-rspec'
15
16
  t.requires << 'rubocop-performance'
17
+ t.requires << 'rubocop-rake'
16
18
  end
17
19
 
18
20
  RSpec::Core::RakeTask.new(:rspec)
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # @api public
4
- # @since 0.1.0
4
+ # @since 0.7.0
5
5
  class SmartCore::Container
6
6
  require_relative 'container/errors'
7
7
  require_relative 'container/arbitary_lock'
@@ -14,13 +14,19 @@ class SmartCore::Container
14
14
  require_relative 'container/dependency_resolver'
15
15
  require_relative 'container/mixin'
16
16
 
17
- # @since 0.1.0
17
+ # @since 0.7.0
18
18
  include DefinitionDSL
19
19
 
20
+ # @return [SmartCore::Container::Registry]
21
+ #
22
+ # @api private
23
+ # @since 0.7.0
24
+ attr_reader :registry
25
+
20
26
  # @return [void]
21
27
  #
22
28
  # @api public
23
- # @since 0.1.0
29
+ # @since 0.7.0
24
30
  def initialize
25
31
  build_registry!
26
32
  @access_lock = ArbitaryLock.new
@@ -31,7 +37,7 @@ class SmartCore::Container
31
37
  # @return [void]
32
38
  #
33
39
  # @api public
34
- # @sicne 0.1.0
40
+ # @sicne 0.7.0
35
41
  def register(dependency_name, &dependency_definition)
36
42
  thread_safe { registry.register_dependency(dependency_name, &dependency_definition) }
37
43
  end
@@ -41,7 +47,7 @@ class SmartCore::Container
41
47
  # @return [void]
42
48
  #
43
49
  # @api public
44
- # @since 0.1.0
50
+ # @since 0.7.0
45
51
  def namespace(namespace_name, &dependencies_definition)
46
52
  thread_safe { registry.register_namespace(namespace_name, &dependencies_definition) }
47
53
  end
@@ -50,15 +56,26 @@ class SmartCore::Container
50
56
  # @return [Any]
51
57
  #
52
58
  # @api public
53
- # @since 0.1.0
59
+ # @since 0.7.0
60
+ # @version 0.8.0
54
61
  def resolve(dependency_path)
55
- thread_safe { DependencyResolver.resolve(registry, dependency_path) }
62
+ thread_safe { DependencyResolver.resolve(self, dependency_path) }
63
+ end
64
+ alias_method :[], :resolve
65
+
66
+ # @param dependency_path [String, Symbol]
67
+ # @return [Any]
68
+ #
69
+ # @api public
70
+ # @since 0.8.0
71
+ def fetch(dependency_path)
72
+ thread_safe { DependencyResolver.fetch(self, dependency_path) }
56
73
  end
57
74
 
58
75
  # @return [void]
59
76
  #
60
77
  # @api public
61
- # @since 0.1.0
78
+ # @since 0.7.0
62
79
  def freeze!
63
80
  thread_safe { registry.freeze! }
64
81
  end
@@ -66,7 +83,7 @@ class SmartCore::Container
66
83
  # @return [Boolean]
67
84
  #
68
85
  # @api public
69
- # @since 0.1.0
86
+ # @since 0.7.0
70
87
  def frozen?
71
88
  thread_safe { registry.frozen? }
72
89
  end
@@ -74,15 +91,16 @@ class SmartCore::Container
74
91
  # @return [void]
75
92
  #
76
93
  # @api public
77
- # @since 0.1.0
94
+ # @since 0.7.0
78
95
  def reload!
79
96
  thread_safe { build_registry! }
80
97
  end
81
98
 
99
+ # @option resolve_dependencies [Boolean]
82
100
  # @return [Hash<String|Symbol,SmartCore::Container::Entities::Base|Any>]
83
101
  #
84
102
  # @api public
85
- # @since 0.1.0
103
+ # @since 0.7.0
86
104
  def hash_tree(resolve_dependencies: false)
87
105
  thread_safe { registry.hash_tree(resolve_dependencies: resolve_dependencies) }
88
106
  end
@@ -91,16 +109,10 @@ class SmartCore::Container
91
109
 
92
110
  private
93
111
 
94
- # @return [SmartCore::Container::Registry]
95
- #
96
- # @api private
97
- # @since 0.1.0
98
- attr_reader :registry
99
-
100
112
  # @return [void]
101
113
  #
102
114
  # @api private
103
- # @since 0.1.0
115
+ # @since 0.7.0
104
116
  def build_registry!
105
117
  @registry = RegistryBuilder.build(self)
106
118
  end
@@ -109,7 +121,7 @@ class SmartCore::Container
109
121
  # @return [Any]
110
122
  #
111
123
  # @api private
112
- # @since 0.1.0
124
+ # @since 0.7.0
113
125
  def thread_safe(&block)
114
126
  @access_lock.thread_safe(&block)
115
127
  end
@@ -3,19 +3,64 @@
3
3
  # @api private
4
4
  # @since 0.7.0
5
5
  module SmartCore::Container::DependencyResolver
6
+ require_relative 'dependency_resolver/route'
7
+
6
8
  class << self
7
- # @param registry [SmartCore::Container::Registry]
9
+ # @param container [SmartCore::Container]
10
+ # @param dependency_path [String, Symbol]
11
+ # @return [SmartCore::Container, Any]
12
+ #
13
+ # @see SmartCore::Container::Registry#resolve
14
+ # @see SmartCore::Container::Entities::Namespace#reveal
15
+ # @see SmartCore::Container::Entities::Dependency#reveal
16
+ #
17
+ # @api private
18
+ # @since 0.8.0
19
+ def fetch(container, dependency_path)
20
+ container.registry.resolve(dependency_path).reveal
21
+ end
22
+
23
+ # @param container [SmartCore::Container]
8
24
  # @param dependency_path [String, Symbol]
9
25
  # @return [SmartCore::Container, Any]
10
26
  #
11
27
  # @see SmartCore::Container::Registry#resolve
12
- # @see SmartCore::Container::Entities::Namespace#resolve
13
- # @see SmartCore::Container::Entities::Dependency#resolve
28
+ # @see SmartCore::Container::Entities::Namespace#reveal
29
+ # @see SmartCore::Container::Entities::Dependency#reveal
30
+ #
31
+ # @raise [SmartCore::Container::ResolvingError]
14
32
  #
15
33
  # @api private
16
34
  # @since 0.7.0
17
- def resolve(registry, dependency_path)
18
- registry.resolve(dependency_path).resolve
35
+ # @version 0.8.0
36
+ def resolve(container, dependency_path)
37
+ entity = container
38
+
39
+ Route.build(dependency_path).each do |cursor|
40
+ entity = entity.registry.resolve(cursor.current_path)
41
+ if cursor.last? && entity.is_a?(SmartCore::Container::Entities::Namespace)
42
+ # rubocop:enable Metrics/LineLength
43
+ raise(SmartCore::Container::ResolvingError.new(<<~MESSAGE, path_part: cursor.current_path))
44
+ Trying to resolve a namespace as a dependency
45
+ MESSAGE
46
+ # rubocop:disable Metrics/LineLength
47
+ end
48
+ if !cursor.last? && entity.is_a?(SmartCore::Container::Entities::Dependency)
49
+ # rubocop:enable Metrics/LineLength
50
+ raise(SmartCore::Container::ResolvingError.new(<<~MESSAGE, path_part: cursor.current_path))
51
+ Trying to resolve nonexistent dependency
52
+ MESSAGE
53
+ # rubocop:disable Metrics/LineLength
54
+ end
55
+ entity = entity.reveal
56
+ end
57
+
58
+ entity
59
+ rescue SmartCore::Container::ResolvingError => error
60
+ full_dependency_path = Route.build_path(dependency_path, error.path_part)
61
+ raise(SmartCore::Container::ResolvingError.new(<<~MESSAGE, path_part: full_dependency_path))
62
+ #{error.message} (incorrect path: "#{full_dependency_path}")
63
+ MESSAGE
19
64
  end
20
65
  end
21
66
  end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.8.0
5
+ class SmartCore::Container::DependencyResolver::Route
6
+ require_relative 'route/cursor'
7
+
8
+ # @since 0.8.0
9
+ include Enumerable
10
+
11
+ # @return [String]
12
+ #
13
+ # @api private
14
+ # @since 0.8.0
15
+ PATH_PART_SEPARATOR = '.'
16
+
17
+ class << self
18
+ # @param path [String, Symbol]
19
+ # @return [SmartCore::Container::DependencyResolver::Route]
20
+ #
21
+ # @api private
22
+ # @since 0.8.0
23
+ def build(path)
24
+ new(SmartCore::Container::KeyGuard.indifferently_accessable_key(path))
25
+ end
26
+
27
+ # @return [Array<String>]
28
+ #
29
+ # @api private
30
+ # @since 0.8.0
31
+ def build_path(*path_parts)
32
+ path_parts.join(PATH_PART_SEPARATOR)
33
+ end
34
+ end
35
+
36
+ # @return [Integer]
37
+ #
38
+ # @api private
39
+ # @since 0.8.0
40
+ attr_reader :size
41
+
42
+ # @return [String]
43
+ #
44
+ # @api private
45
+ # @since 0.8.0
46
+ attr_reader :path
47
+
48
+ # @param path [String]
49
+ # @return [void]
50
+ #
51
+ # @api private
52
+ # @since 0.8.0
53
+ def initialize(path)
54
+ @path = path
55
+ @path_parts = path.split(PATH_PART_SEPARATOR).freeze
56
+ @size = @path_parts.size
57
+ end
58
+
59
+ # @param block [Block]
60
+ # @yield cursor [SmartCore::Container::DependencyResolver::Route::Cursor]
61
+ # @return [Enumerable]
62
+ #
63
+ # @api private
64
+ # @since 0.8.0
65
+ def each(&block)
66
+ enumerator = Enumerator.new do |yielder|
67
+ path_parts.each_with_index do |path_part, path_part_index|
68
+ cursor = Cursor.new(path_part, path_part_index, self)
69
+ yielder.yield(cursor)
70
+ end
71
+ end
72
+
73
+ block_given? ? enumerator.each(&block) : enumerator
74
+ end
75
+
76
+ private
77
+
78
+ # @return [Array<String>]
79
+ #
80
+ # @api private
81
+ # @since 0.8.0
82
+ attr_reader :path_parts
83
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.8.0
5
+ class SmartCore::Container::DependencyResolver::Route::Cursor
6
+ # @return [String]
7
+ #
8
+ # @api private
9
+ # @since 0.8.0
10
+ attr_reader :path_part
11
+ alias_method :current_path, :path_part
12
+
13
+ # @param path_part [String]
14
+ # @param path_part_index [Integer]
15
+ # @param route [SmartCore::Container::DependencyResolver::Route]
16
+ # @return [void]
17
+ #
18
+ # @api private
19
+ # @since 0.8.0
20
+ def initialize(path_part, path_part_index, route)
21
+ @path_part = path_part
22
+ @path_part_index = path_part_index
23
+ @route = route
24
+ end
25
+
26
+ # @return [Boolean]
27
+ #
28
+ # @api private
29
+ # @since 0.8.0
30
+ def last?
31
+ route.size <= (path_part_index + 1)
32
+ end
33
+
34
+ private
35
+
36
+ # @return [Integer]
37
+ #
38
+ # @api private
39
+ # @since 0.8.0
40
+ attr_reader :path_part_index
41
+
42
+ # @return [SmartCore::Container::DependencyResolver::Route]
43
+ #
44
+ # @api private
45
+ # @since 0.8.0
46
+ attr_reader :route
47
+ end
@@ -21,6 +21,6 @@ class SmartCore::Container::Entities::Base
21
21
  # @return [Any]
22
22
  #
23
23
  # @api private
24
- # @since 0.7.0
25
- def resolve; end
24
+ # @since 0.8.0
25
+ def reveal; end
26
26
  end
@@ -6,7 +6,7 @@ class SmartCore::Container::Entities::Dependency < SmartCore::Container::Entitie
6
6
  # @return [String]
7
7
  #
8
8
  # @api private
9
- # @sicne 0.7.0
9
+ # @since 0.7.0
10
10
  alias_method :dependency_name, :external_name
11
11
 
12
12
  # @param dependency_name [String]
@@ -23,8 +23,8 @@ class SmartCore::Container::Entities::Dependency < SmartCore::Container::Entitie
23
23
  # @return [Any]
24
24
  #
25
25
  # @api private
26
- # @since 0.7.0
27
- def resolve
26
+ # @since 0.8.0
27
+ def reveal
28
28
  dependency_definition.call
29
29
  end
30
30
 
@@ -24,8 +24,8 @@ class SmartCore::Container::Entities::Namespace < SmartCore::Container::Entities
24
24
  # @return [SmartCore::Container]
25
25
  #
26
26
  # @api private
27
- # @since 0.7.0
28
- def resolve
27
+ # @since 0.8.0
28
+ def reveal
29
29
  thread_safe { container_instance }
30
30
  end
31
31
 
@@ -19,11 +19,9 @@ class SmartCore::Container
19
19
  # @since 0.7.0
20
20
  FrozenRegistryError = Class.new(SmartCore::FrozenError)
21
21
 
22
- # @see SmartCore::Container::Registry
23
- #
24
22
  # @api public
25
- # @since 0.7.0
26
- NonexistentEntityError = Class.new(Error)
23
+ # @since 0.8.0
24
+ FetchError = Class.new(Error)
27
25
 
28
26
  # @see SmartCore::Container::DependencyCompatability::General
29
27
  # @see SmartCore::Container::DependencyCompatability::Definition
@@ -40,4 +38,28 @@ class SmartCore::Container
40
38
  # @api public
41
39
  # @since 0.7.0
42
40
  NamespaceOverDependencyOverlapError = Class.new(Error)
41
+
42
+ # @see SmartCore::Container::DependencyResolver
43
+ # @see SmartCore::Container::Registry
44
+ #
45
+ # @api public
46
+ # @since 0.8.0
47
+ class ResolvingError < FetchError
48
+ # @return [String]
49
+ #
50
+ # @api private
51
+ # @since 0.8.0
52
+ attr_reader :path_part
53
+
54
+ # @param message [String]
55
+ # @param path_part [String]
56
+ # @return [void]
57
+ #
58
+ # @api private
59
+ # @since 0.8.0
60
+ def initialize(messegae = nil, path_part:)
61
+ @path_part = path_part
62
+ super(message)
63
+ end
64
+ end
43
65
  end
@@ -55,9 +55,7 @@ module SmartCore::Container::Mixin
55
55
  def dependencies(freeze_state: false, &block)
56
56
  @__smart_core_container_access_lock__.thread_safe do
57
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
58
+ @__smart_core_container_klass__.instance_eval { freeze_state! } if freeze_state
61
59
  end
62
60
  end
63
61
 
@@ -111,9 +111,9 @@ class SmartCore::Container::Registry
111
111
  enumerate do |(entity_name, entity)|
112
112
  case entity
113
113
  when SmartCore::Container::Entities::Namespace
114
- tree[entity_name] = entity.resolve.hash_tree(resolve_dependencies: resolve_dependencies)
114
+ tree[entity_name] = entity.reveal.hash_tree(resolve_dependencies: resolve_dependencies)
115
115
  when SmartCore::Container::Entities::Dependency
116
- tree[entity_name] = resolve_dependencies ? entity.resolve : entity
116
+ tree[entity_name] = resolve_dependencies ? entity.reveal : entity
117
117
  end
118
118
  end
119
119
  end
@@ -145,14 +145,14 @@ class SmartCore::Container::Registry
145
145
  #
146
146
  # @api private
147
147
  # @since 0.7.0
148
+ # @version 0.8.0
148
149
  def fetch_entity(entity_path)
149
150
  dependency_name = indifferently_accessable_name(entity_path)
150
151
  registry.fetch(dependency_name)
151
152
  rescue KeyError
152
- raise(
153
- SmartCore::Container::NonexistentEntityError,
154
- "Entity with '#{dependency_name}' name does not exist!"
155
- )
153
+ raise(SmartCore::Container::ResolvingError.new(<<~MESSAGE, path_part: dependency_name))
154
+ Entity with \"#{dependency_name}\" name does not exist
155
+ MESSAGE
156
156
  end
157
157
 
158
158
  # @param dependency_name [String, Symbol]
@@ -195,7 +195,7 @@ class SmartCore::Container::Registry
195
195
  # rubocop:disable Layout/RescueEnsureAlignment
196
196
  namespace_entity = begin
197
197
  fetch_entity(namespace_name)
198
- rescue SmartCore::Container::NonexistentEntityError
198
+ rescue SmartCore::Container::FetchError
199
199
  registry[namespace_name] = SmartCore::Container::Entities::NamespaceBuilder.build(
200
200
  namespace_name
201
201
  )
@@ -5,5 +5,5 @@ module SmartCore
5
5
  #
6
6
  # @api public
7
7
  # @since 0.1.0
8
- VERSION = '0.7.0'
8
+ VERSION = '0.8.0'
9
9
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smart_core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rustam Ibragimov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-11-10 00:00:00.000000000 Z
11
+ date: 2019-11-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: simplecov
@@ -131,6 +131,8 @@ files:
131
131
  - lib/smart_core/container/dependency_compatability/general.rb
132
132
  - lib/smart_core/container/dependency_compatability/registry.rb
133
133
  - lib/smart_core/container/dependency_resolver.rb
134
+ - lib/smart_core/container/dependency_resolver/route.rb
135
+ - lib/smart_core/container/dependency_resolver/route/cursor.rb
134
136
  - lib/smart_core/container/entities.rb
135
137
  - lib/smart_core/container/entities/base.rb
136
138
  - lib/smart_core/container/entities/dependency.rb
@@ -210,7 +212,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
210
212
  - !ruby/object:Gem::Version
211
213
  version: '0'
212
214
  requirements: []
213
- rubygems_version: 3.0.3
215
+ rubyforge_project:
216
+ rubygems_version: 2.7.6
214
217
  signing_key:
215
218
  specification_version: 4
216
219
  summary: "(in active development) A set of common abstractions"