smart_container 0.5.0 → 0.9.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: 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 )