smart_core 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
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"