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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 92746ed446b181dc165a597563edc69b62b41550974023342c4693f2c17dee6a
4
- data.tar.gz: 1cf3862c40c1044510a11e09f19df542a8d0b3a255bd0df5593ad9c531b9f10b
3
+ metadata.gz: 6a45cc16a5fa97c52b28570a75115e21765f771b58e43fc1a0bd90d39b3c8abe
4
+ data.tar.gz: e956a3ceaa496e4c7e023ac6310b93bc05525959f48619f0c31126d9097f7e83
5
5
  SHA512:
6
- metadata.gz: ec6db288f98f769d0bbe96dd4d35186d1a199f6e046edf1de83a50c4b76149366c94a7c172a005378be88c8e8503436b9dad7e2518bcbae1de939b2a37204600
7
- data.tar.gz: 9124de765215847cb7bd135a19524043652b9f9d7580027106a43cc6fa8f61a3bfd22c982cf07b1f46ea196b6fdae978d0973682a9c24511eb679d7c310b33a7
6
+ metadata.gz: d4d619d75a98601444c55ff7a278169e6b0937f0356ff19f8fcd41ba9c72d9f25c8ec0a077a90b87d77469605e542a5e5081aec5d9b0bf0c1718019902ad8166
7
+ data.tar.gz: cb220b711e67c661f7338ff6d49f82048df73861cadc0c1fdc981739d7c64ffec03953d397176c1d9e4e64321cdae078ca624fcb6ac51a8ccb92f4473b92fe83
@@ -5,11 +5,16 @@ inherit_gem:
5
5
  - lib/rubocop.rspec.yml
6
6
 
7
7
  AllCops:
8
- TargetRubyVersion: 2.4.9
8
+ TargetRubyVersion: 3.0.0
9
+ NewCops: enable
9
10
  Include:
10
11
  - lib/**/*.rb
11
12
  - spec/**/*.rb
12
13
  - Gemfile
13
14
  - Rakefile
14
- - siege.gemspec
15
+ - smart_container.gemspec
15
16
  - bin/console
17
+
18
+ Lint/EmptyBlock:
19
+ Exclude:
20
+ - spec/**/*.rb
@@ -1,6 +1,43 @@
1
1
  # Changelog
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
+ ## [0.9.0] - 2020-01-17
5
+ ### Added
6
+ - Support for *Ruby@3*;
7
+ - Updated development dependencies;
8
+
9
+ ### Changed
10
+ - No more TravisCI (todo: migrate to Github Actions);
11
+ - Minimal `smart_engine` version: *0.11.0* (in order to support *Ruby@3*);
12
+
13
+ ## [0.8.1] - 2020-07-09
14
+ ### Changed
15
+ - *Core*
16
+ - refactored `SmartCore::Container::Entities::NamespaceBuilder` and `SmartCore::Container::Entities::DependencyBuilder`
17
+ (from stateful-based logic on instances to stateless-based logic on modules);
18
+
19
+ ### Fixed
20
+ - Subscription to the nested dependency changement doesn't work
21
+ (incomplete nested dependency path in watcher notification);
22
+
23
+ ## [0.8.0] - 2020-07-08
24
+ ### Added
25
+ - An ability to observe dependency re-registrations:
26
+ - `#observe(path, &observer) # => observer object` - listen specific dependency path;
27
+ - `#unobserve(observer)` - unsubscribe concrete observer object;
28
+ - `#clear_observers(path = nil)` - unsubscribe specific listenr or all listeners (`nil` parameter);
29
+
30
+ ## [0.7.0] - 2020-06-20
31
+ ### Added
32
+ - `SmartCore::Container.define {}` - an ability to avoid explicit class definition that allows
33
+ to create container instances from an anonymous container class imidietly
34
+
35
+ ## [0.6.0] - 2020-01-12
36
+ ### Added
37
+ - Missing memoization flag `:memoize` for runtime-based dependency registration:
38
+ - `memoize: false` by default;
39
+ - signature: `SmartCore::Container#register(dependency_name, memoize: false, &dependency)`
40
+
4
41
  ## [0.5.0] - 2020-01-07
5
42
  ### Added
6
43
  - Key predicates (`#key?(key)`, `#dependency?(path, memoized: nil/true/false)`, `#namespace?(path)`);
@@ -1,83 +1,104 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- smart_container (0.4.0)
5
- smart_engine (~> 0.2)
4
+ smart_container (0.9.0)
5
+ smart_engine (~> 0.11)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- armitage-rubocop (0.78.0)
11
- rubocop (= 0.78.0)
12
- rubocop-performance (= 1.5.2)
13
- rubocop-rails (= 2.4.1)
14
- rubocop-rake (= 0.5.0)
15
- rubocop-rspec (= 1.37.1)
16
- ast (2.4.0)
17
- coderay (1.1.2)
18
- diff-lcs (1.3)
19
- docile (1.3.2)
20
- jaro_winkler (1.5.4)
21
- json (2.3.0)
22
- method_source (0.9.2)
23
- parallel (1.19.1)
24
- parser (2.7.0.1)
25
- ast (~> 2.4.0)
26
- pry (0.12.2)
27
- coderay (~> 1.1.0)
28
- method_source (~> 0.9.0)
29
- rack (2.0.8)
10
+ activesupport (6.1.1)
11
+ concurrent-ruby (~> 1.0, >= 1.0.2)
12
+ i18n (>= 1.6, < 2)
13
+ minitest (>= 5.1)
14
+ tzinfo (~> 2.0)
15
+ zeitwerk (~> 2.3)
16
+ armitage-rubocop (1.7.0.1)
17
+ rubocop (= 1.7.0)
18
+ rubocop-performance (= 1.9.1)
19
+ rubocop-rails (= 2.9.1)
20
+ rubocop-rake (= 0.5.1)
21
+ rubocop-rspec (= 2.1.0)
22
+ ast (2.4.1)
23
+ coderay (1.1.3)
24
+ concurrent-ruby (1.1.7)
25
+ diff-lcs (1.4.4)
26
+ docile (1.3.5)
27
+ i18n (1.8.7)
28
+ concurrent-ruby (~> 1.0)
29
+ method_source (1.0.0)
30
+ minitest (5.14.3)
31
+ parallel (1.20.1)
32
+ parser (3.0.0.0)
33
+ ast (~> 2.4.1)
34
+ pry (0.13.1)
35
+ coderay (~> 1.1)
36
+ method_source (~> 1.0)
37
+ rack (2.2.3)
30
38
  rainbow (3.0.0)
31
- rake (13.0.1)
32
- rspec (3.9.0)
33
- rspec-core (~> 3.9.0)
34
- rspec-expectations (~> 3.9.0)
35
- rspec-mocks (~> 3.9.0)
36
- rspec-core (3.9.1)
37
- rspec-support (~> 3.9.1)
38
- rspec-expectations (3.9.0)
39
+ rake (13.0.3)
40
+ regexp_parser (2.0.3)
41
+ rexml (3.2.4)
42
+ rspec (3.10.0)
43
+ rspec-core (~> 3.10.0)
44
+ rspec-expectations (~> 3.10.0)
45
+ rspec-mocks (~> 3.10.0)
46
+ rspec-core (3.10.1)
47
+ rspec-support (~> 3.10.0)
48
+ rspec-expectations (3.10.1)
39
49
  diff-lcs (>= 1.2.0, < 2.0)
40
- rspec-support (~> 3.9.0)
41
- rspec-mocks (3.9.1)
50
+ rspec-support (~> 3.10.0)
51
+ rspec-mocks (3.10.1)
42
52
  diff-lcs (>= 1.2.0, < 2.0)
43
- rspec-support (~> 3.9.0)
44
- rspec-support (3.9.2)
45
- rubocop (0.78.0)
46
- jaro_winkler (~> 1.5.1)
53
+ rspec-support (~> 3.10.0)
54
+ rspec-support (3.10.1)
55
+ rubocop (1.7.0)
47
56
  parallel (~> 1.10)
48
- parser (>= 2.6)
57
+ parser (>= 2.7.1.5)
49
58
  rainbow (>= 2.2.2, < 4.0)
59
+ regexp_parser (>= 1.8, < 3.0)
60
+ rexml
61
+ rubocop-ast (>= 1.2.0, < 2.0)
50
62
  ruby-progressbar (~> 1.7)
51
- unicode-display_width (>= 1.4.0, < 1.7)
52
- rubocop-performance (1.5.2)
53
- rubocop (>= 0.71.0)
54
- rubocop-rails (2.4.1)
63
+ unicode-display_width (>= 1.4.0, < 2.0)
64
+ rubocop-ast (1.4.0)
65
+ parser (>= 2.7.1.5)
66
+ rubocop-performance (1.9.1)
67
+ rubocop (>= 0.90.0, < 2.0)
68
+ rubocop-ast (>= 0.4.0)
69
+ rubocop-rails (2.9.1)
70
+ activesupport (>= 4.2.0)
55
71
  rack (>= 1.1)
56
- rubocop (>= 0.72.0)
57
- rubocop-rake (0.5.0)
72
+ rubocop (>= 0.90.0, < 2.0)
73
+ rubocop-rake (0.5.1)
58
74
  rubocop
59
- rubocop-rspec (1.37.1)
60
- rubocop (>= 0.68.1)
61
- ruby-progressbar (1.10.1)
62
- simplecov (0.17.1)
75
+ rubocop-rspec (2.1.0)
76
+ rubocop (~> 1.0)
77
+ rubocop-ast (>= 1.1.0)
78
+ ruby-progressbar (1.11.0)
79
+ simplecov (0.21.2)
63
80
  docile (~> 1.1)
64
- json (>= 1.8, < 3)
65
- simplecov-html (~> 0.10.0)
66
- simplecov-html (0.10.2)
67
- smart_engine (0.2.0)
68
- unicode-display_width (1.6.0)
81
+ simplecov-html (~> 0.11)
82
+ simplecov_json_formatter (~> 0.1)
83
+ simplecov-html (0.12.3)
84
+ simplecov_json_formatter (0.1.2)
85
+ smart_engine (0.11.0)
86
+ tzinfo (2.0.4)
87
+ concurrent-ruby (~> 1.0)
88
+ unicode-display_width (1.7.0)
89
+ zeitwerk (2.4.2)
69
90
 
70
91
  PLATFORMS
71
- ruby
92
+ x86_64-darwin-20
72
93
 
73
94
  DEPENDENCIES
74
- armitage-rubocop (~> 0.78)
75
- bundler (~> 2.1)
76
- pry (~> 0.12)
95
+ armitage-rubocop (~> 1.7)
96
+ bundler (~> 2.2)
97
+ pry (~> 0.13)
77
98
  rake (~> 13.0)
78
- rspec (~> 3.9)
79
- simplecov (~> 0.17)
99
+ rspec (~> 3.10)
100
+ simplecov (~> 0.21)
80
101
  smart_container!
81
102
 
82
103
  BUNDLED WITH
83
- 2.1.2
104
+ 2.2.3
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # SmartCore::Container &middot; [![Gem Version](https://badge.fury.io/rb/smart_container.svg)](https://badge.fury.io/rb/smart_container) [![Build Status](https://travis-ci.org/smart-rb/smart_container.svg?branch=master)](https://travis-ci.org/smart-rb/smart_container)
1
+ # SmartCore::Container &middot; [![Gem Version](https://badge.fury.io/rb/smart_container.svg)](https://badge.fury.io/rb/smart_container)
2
2
 
3
3
  Thread-safe semanticaly-defined IoC/DI Container.
4
4
 
@@ -22,9 +22,27 @@ require 'smart_core/container'
22
22
 
23
23
  ---
24
24
 
25
- ## Synopsis (demo)
25
+ ## Table of cotnents
26
+
27
+ - [Functionality](#functionality)
28
+ - [container class creation](#container-class-creation)
29
+ - [mixin](#mixin)
30
+ - [container instantiation and dependency resolving](#container-instantiation-and-dependency-resolving)
31
+ - [runtime-level dependency/namespace registration](#runtime-level-dependencynamespace-registration)
32
+ - [container keys (dependency names)](#container-keys-dependency-names)
33
+ - [key predicates](#key-predicates)
34
+ - [state freeze](#state-freeze)
35
+ - [reloading](#reloading)
36
+ - [hash tree](#hash-tree)
37
+ - [explicit class definition](#explicit-class-definition)
38
+ - [subscribe to dependency changements](#subscribe-to-dependency-changements)
39
+ - [Roadmap](#roadmap)
26
40
 
27
- - container class creation:
41
+ ---
42
+
43
+ ## Functionality
44
+
45
+ #### container class creation
28
46
 
29
47
  ```ruby
30
48
  class Container < SmartCore::Container
@@ -45,7 +63,31 @@ class Container < SmartCore::Container
45
63
  end
46
64
  ```
47
65
 
48
- - container instantiation and dependency resolving:
66
+ ---
67
+
68
+ #### mixin
69
+
70
+ ```ruby
71
+ # full documentaiton is coming;
72
+
73
+ class Application
74
+ include SmartCore::Container::Mixin
75
+
76
+ dependencies do
77
+ namespace(:database) do
78
+ register(:cache) { MemcachedClient.new }
79
+ end
80
+ end
81
+ end
82
+
83
+ # access:
84
+ Application.container
85
+ Application.new.container # NOTE: the same instance as Application.container
86
+ ```
87
+
88
+ ---
89
+
90
+ #### container instantiation and dependency resolving
49
91
 
50
92
  ```ruby
51
93
  container = Container.new # create container instance
@@ -70,20 +112,24 @@ container.fetch('database') # => SmartCore::Container (nested container)
70
112
  container.fetch('database.resolver') # => #<SomeDatabaseResolver:0x00007f0f0f1d6332>
71
113
  ```
72
114
 
73
- - runtime-level dependency/namespace registration:
115
+ ---
116
+
117
+ #### runtime-level dependency/namespace registration
74
118
 
75
119
  ```ruby
76
120
  container.namespace(:api) do
77
- register(:provider) { GoogleProvider }
121
+ register(:provider) { GoogleProvider } # without memoization
78
122
  end
79
123
 
80
- container.register('game_api') { 'overwatch' }
124
+ container.register('game_api', memoize: true) { 'overwatch' } # with memoization
81
125
 
82
126
  container['api.provider'] # => GoogleProvider
83
127
  container['game_api'] # => 'overwatch'
84
128
  ```
85
129
 
86
- - container keys (dependency names):
130
+ ---
131
+
132
+ #### container keys (dependency names):
87
133
 
88
134
  ```ruby
89
135
  # get dependnecy keys (only dependencies)
@@ -112,12 +158,15 @@ container.keys(all_variants: true)
112
158
  ]
113
159
  ```
114
160
 
115
- - key predicates:
116
- - `key?(key)` - has dependency or namespace?
117
- - `namespace?(path)` - has namespace?
118
- - `dependency?(path)` - has dependency?
119
- - `dependency?(path, memoized: true)` - has memoized dependency?
120
- - `dependency?(path, memoized: false)` - has non-memoized dependency?
161
+ ---
162
+
163
+ #### key predicates
164
+
165
+ - `key?(key)` - has dependency or namespace?
166
+ - `namespace?(path)` - has namespace?
167
+ - `dependency?(path)` - has dependency?
168
+ - `dependency?(path, memoized: true)` - has memoized dependency?
169
+ - `dependency?(path, memoized: false)` - has non-memoized dependency?
121
170
 
122
171
  ```ruby
123
172
  container.key?('database') # => true
@@ -136,13 +185,31 @@ container.dependency?('random', memoized: true) # => false
136
185
  container.dependency?('random', memoized: false) # => true
137
186
  ```
138
187
 
139
- - state freeze:
188
+ ---
189
+
190
+ #### state freeze
191
+
192
+ - state freeze (`#freeze!`, `.#frozen?`):
140
193
 
141
194
  ```ruby
142
195
  # documentation is coming;
143
196
  ```
144
197
 
145
- - reloading:
198
+ ---
199
+
200
+ #### reloading
201
+
202
+ - reloading (`#reload!`):
203
+
204
+ ```ruby
205
+ # documentation is coming;
206
+ ```
207
+
208
+ ---
209
+
210
+ #### hash tree
211
+
212
+ - hash tree (`#hash_tree`, `#hash_tree(resolve_dependencies: true)`):
146
213
 
147
214
  ```ruby
148
215
  # documentation is coming;
@@ -150,6 +217,147 @@ container.dependency?('random', memoized: false) # => true
150
217
 
151
218
  ---
152
219
 
220
+ #### explicit class definition
221
+
222
+ - `SmartCore::Container.define` - avoid explicit class definition (allows to create container instance from an anonymous container class immidietly):
223
+
224
+ ```ruby
225
+ # - create from empty container class -
226
+
227
+ AppContainer = SmartCore::Container.define do
228
+ namespace :database do
229
+ register(:logger) { Logger.new }
230
+ end
231
+ end # => an instance of Class<SmartCore::Container>
232
+
233
+ AppContainer.resolve('database.logger') # => #<Logger:0x00007f5f0f2f0158>
234
+ AppContainer['database.logger'] # => #<Logger:0x00007f5f0f2f0158>
235
+ ```
236
+
237
+ ```ruby
238
+ # - create from another container class with a custom sub-definitions -
239
+
240
+ class BasicContainer < SmartCore::Container
241
+ namespace(:api) do
242
+ register(:client) { Kickbox.new }
243
+ end
244
+ end
245
+
246
+ AppContainer = BasicContainer.define do
247
+ register(:db_driver) { Sequel }
248
+ end
249
+ # --- or ---
250
+ AppContainer = SmartCore::Container.define(BasicContainer) do
251
+ register(:db_driver) { Sequel }
252
+ end
253
+
254
+ AppContainer['api.client'] # => #<Kickbox:0x00007f5f0f2f0158> (BasicContainer dependency)
255
+ AppContainer['db_driver'] # => Sequel (AppContainer dependency)
256
+ ```
257
+
258
+ ---
259
+
260
+ #### subscribe to dependency changements
261
+
262
+ - features and limitations:
263
+ - you can subscribe only on container instances (on container instance changements);
264
+ - at this moment only the full entity path patterns are supported (pattern-based pathes are not supported yet);
265
+ - you can subscribe on namespace changements (when the full namespace is re-registered) and dependency changement (when some dependency has been changed);
266
+ - `#observe(path, &observer) => observer` - subscribe a custom block to dependency changement events (your proc will be invoked with `|path, container|` attributes);
267
+ - `#unobserve(observer)` - unsubscribe concrete observer from dependency observing (returns `true` (unsubscribed) or `false` (nothing to unsubscribe));
268
+ - `#clear_observers(entity_path = nil)` - unsubscribe all observers from concrete path or from all pathes (`nil` parameters);
269
+ - aliases:
270
+ - `#observe` => `#subscribe`;
271
+ - `#unobserve` => `#unsubscribe`;
272
+ - `#clear_observers` => `#clear_listeners`;
273
+
274
+ ```ruby
275
+ container = SmartCore::Container.define do
276
+ namespace(:database) do
277
+ register(:stats) { 'stat_db' }
278
+ end
279
+ end
280
+ ```
281
+
282
+ ```ruby
283
+ # observe entity change
284
+ entity_observer = container.observe('database.stats') do |dependency_path, container|
285
+ puts "changed => '#{container[dependency_path]}'"
286
+ end
287
+
288
+ # observe namespace change
289
+ namespace_observer = container.observe('database') do |namespace_path, container|
290
+ puts "changed => '#{namespace_path}'"
291
+ end
292
+ ```
293
+
294
+ ```ruby
295
+ container.fetch('database').register('stats') = 'kek' # => invokes entity_observer and outputs "changed! => 'kek'"
296
+ container.namespace('database') {} # => invoks namespace_observer and outputs "changed => 'database'"
297
+
298
+ container.unobserve(observer) # unsubscribe entity_observer from dependency changement observing;
299
+ container.clear_observers # unsubscribe all observers
300
+
301
+ container.fetch('database').register('stats') = 'pek' # no one to listen this changement... :)
302
+ container.namespace('database') {} # no one to listen this changement... :)
303
+ ```
304
+
305
+ ---
306
+
307
+ ## Roadmap
308
+
309
+ - migrate to Github Actions;
310
+
311
+ - convinient way to rebind registered dependnecies:
312
+
313
+ ```ruby
314
+ # PoC
315
+
316
+ container['dependency.path'] = 'pek' # simplest instant dependency registration without memoization
317
+ # --- or/and ---
318
+ container.rebind('dependency.path', memoize: true/false) { 'pek' } # bind with dynamic dependency registration
319
+ container.rebind('dependency.path', memoize: true/false, 'pek') # bind with instant dependency registration
320
+ ```
321
+
322
+ - pattern-based pathes in dependency changement observing;
323
+
324
+ ```ruby
325
+ container.observe('path.*') { puts 'kek!' } # subscribe to all changements in `path` namespace;
326
+ ```
327
+
328
+ - support for instant dependency registration:
329
+
330
+ ```ruby
331
+ # common (dynamic) way:
332
+ register('dependency_name') { dependency_value }
333
+
334
+ # instant way:
335
+ register('dependency_name', dependency_value)
336
+ ```
337
+
338
+ - support for memoization ignorance during dependency resolving:
339
+
340
+ ```ruby
341
+ resolve('logger', :allocate) # Draft
342
+ ```
343
+
344
+ - container composition;
345
+
346
+ - support for fallback block in `.resolve` operation (similar to `Hash#fetch` works);
347
+
348
+ - inline temporary dependency switch:
349
+
350
+ ```ruby
351
+ with(logger: Logger.new, db: DB.new) do
352
+ # logger is a new logger
353
+ # db is a new db
354
+ end
355
+
356
+ # out of block: logger is an old logger, db is an old db
357
+ ```
358
+
359
+ ---
360
+
153
361
  ## Contributing
154
362
 
155
363
  - Fork it ( https://github.com/smart-rb/smart_container/fork )