smart_container 0.4.0 → 0.8.1

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: bb1bc1e5f80263730638b0b0387105364777f87e957b5f673c27c219f206273d
4
- data.tar.gz: 0d1a505edb3b4456ab44ecfe52071b1cb5555f51680d3a48de68fb12bd11dcad
3
+ metadata.gz: fbae5c2d40dc40e3114d685c1f13d6cbfb7003a1c8fda862ef5dbcfa432cf5cd
4
+ data.tar.gz: dd288fa47167c0da4e2aae656478170d0dd78b142eef52a351c461ddbc92bf29
5
5
  SHA512:
6
- metadata.gz: 3959674748c1dcc2564bd6edc9ee0acdc3770b0bd260d50c7a1bba5906fee6725ff577e90a2b36b0a81910c423020431810b2a052f42c65826bfc8dcabe7dc22
7
- data.tar.gz: f01f97eda299d91b22f730de1eba90e546f9f4de0362218bc0b8f86d8800acd6abf3d2214e223c0246f5c1d4b4742b71c7223ada409a3665765c088c88ab207e
6
+ metadata.gz: 27129a91c84f8aad432c5462c2d3a921284b2b8e3b1fb4b0a215295f6f88d94063946cc24f2d065f6da9ba6e64baf421f2a192b68fa63ebda879a81715e2c88f
7
+ data.tar.gz: 5e6839adcfe1e3c31513b622fc3e46aab37ab3ec35a992c8a3b9c7ff029c976dbf331619d3df20da7ffe3d712a8839f04ac83f3055f9e2426869e9b9ecf556f6
@@ -5,11 +5,11 @@ inherit_gem:
5
5
  - lib/rubocop.rspec.yml
6
6
 
7
7
  AllCops:
8
- TargetRubyVersion: 2.4.9
8
+ TargetRubyVersion: 2.7.1
9
9
  Include:
10
10
  - lib/**/*.rb
11
11
  - spec/**/*.rb
12
12
  - Gemfile
13
13
  - Rakefile
14
- - siege.gemspec
14
+ - smart_container.gemspec
15
15
  - bin/console
@@ -2,18 +2,19 @@
2
2
  language: ruby
3
3
  cache: bundler
4
4
  os: linux
5
+ dist: xenial
5
6
  before_install:
6
- - gem install bundler -v 2.1.2
7
+ - gem install bundler
7
8
  script:
8
9
  - bundle exec rake rubocop
9
10
  - bundle exec rake rspec
10
11
  jobs:
11
12
  fast_finish: true
12
13
  include:
13
- - rvm: 2.4.9
14
- - rvm: 2.5.7
15
- - rvm: 2.6.5
16
- - rvm: 2.7.0
14
+ - rvm: 2.4.10
15
+ - rvm: 2.5.8
16
+ - rvm: 2.6.6
17
+ - rvm: 2.7.1
17
18
  - rvm: ruby-head
18
19
  - rvm: jruby-head
19
20
  allow_failures:
@@ -1,6 +1,38 @@
1
1
  # Changelog
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
+ ## [0.8.1] - 2020-07-09
5
+ ### Changed
6
+ - *Core*
7
+ - refactored `SmartCore::Container::Entities::NamespaceBuilder` and `SmartCore::Container::Entities::DependencyBuilder`
8
+ (from stateful-based logic on instances to stateless-based logic on modules);
9
+
10
+ ### Fixed
11
+ - Subscription to the nested dependency changement doesn't work
12
+ (incomplete nested dependency path in watcher notification);
13
+
14
+ ## [0.8.0] - 2020-07-08
15
+ ### Added
16
+ - An ability to observe dependency re-registrations:
17
+ - `#observe(path, &observer) # => observer object` - listen specific dependency path;
18
+ - `#unobserve(observer)` - unsubscribe concrete observer object;
19
+ - `#clear_observers(path = nil)` - unsubscribe specific listenr or all listeners (`nil` parameter);
20
+
21
+ ## [0.7.0] - 2020-06-20
22
+ ### Added
23
+ - `SmartCore::Container.define {}` - an ability to avoid explicit class definition that allows
24
+ to create container instances from an anonymous container class imidietly
25
+
26
+ ## [0.6.0] - 2020-01-12
27
+ ### Added
28
+ - Missing memoization flag `:memoize` for runtime-based dependency registration:
29
+ - `memoize: false` by default;
30
+ - signature: `SmartCore::Container#register(dependency_name, memoize: false, &dependency)`
31
+
32
+ ## [0.5.0] - 2020-01-07
33
+ ### Added
34
+ - Key predicates (`#key?(key)`, `#dependency?(path, memoized: nil/true/false)`, `#namespace?(path)`);
35
+
4
36
  ## [0.4.0] - 2020-01-06
5
37
  ### Added
6
38
  - `#keys(all_variants: false)` - return a list of dependency keys
@@ -1,83 +1,98 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- smart_container (0.4.0)
5
- smart_engine (~> 0.2)
4
+ smart_container (0.8.1)
5
+ smart_engine (~> 0.5)
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)
10
+ activesupport (6.0.2.2)
11
+ concurrent-ruby (~> 1.0, >= 1.0.2)
12
+ i18n (>= 0.7, < 2)
13
+ minitest (~> 5.1)
14
+ tzinfo (~> 1.1)
15
+ zeitwerk (~> 2.2)
16
+ armitage-rubocop (0.81.0)
17
+ rubocop (= 0.81.0)
12
18
  rubocop-performance (= 1.5.2)
13
- rubocop-rails (= 2.4.1)
14
- rubocop-rake (= 0.5.0)
15
- rubocop-rspec (= 1.37.1)
19
+ rubocop-rails (= 2.5.2)
20
+ rubocop-rake (= 0.5.1)
21
+ rubocop-rspec (= 1.38.1)
16
22
  ast (2.4.0)
17
23
  coderay (1.1.2)
24
+ concurrent-ruby (1.1.6)
18
25
  diff-lcs (1.3)
19
26
  docile (1.3.2)
27
+ i18n (1.8.2)
28
+ concurrent-ruby (~> 1.0)
20
29
  jaro_winkler (1.5.4)
21
- json (2.3.0)
22
- method_source (0.9.2)
30
+ method_source (1.0.0)
31
+ minitest (5.14.0)
23
32
  parallel (1.19.1)
24
- parser (2.7.0.1)
33
+ parser (2.7.1.0)
25
34
  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)
35
+ pry (0.13.1)
36
+ coderay (~> 1.1)
37
+ method_source (~> 1.0)
38
+ rack (2.2.2)
30
39
  rainbow (3.0.0)
31
40
  rake (13.0.1)
41
+ rexml (3.2.4)
32
42
  rspec (3.9.0)
33
43
  rspec-core (~> 3.9.0)
34
44
  rspec-expectations (~> 3.9.0)
35
45
  rspec-mocks (~> 3.9.0)
36
46
  rspec-core (3.9.1)
37
47
  rspec-support (~> 3.9.1)
38
- rspec-expectations (3.9.0)
48
+ rspec-expectations (3.9.1)
39
49
  diff-lcs (>= 1.2.0, < 2.0)
40
50
  rspec-support (~> 3.9.0)
41
51
  rspec-mocks (3.9.1)
42
52
  diff-lcs (>= 1.2.0, < 2.0)
43
53
  rspec-support (~> 3.9.0)
44
54
  rspec-support (3.9.2)
45
- rubocop (0.78.0)
55
+ rubocop (0.81.0)
46
56
  jaro_winkler (~> 1.5.1)
47
57
  parallel (~> 1.10)
48
- parser (>= 2.6)
58
+ parser (>= 2.7.0.1)
49
59
  rainbow (>= 2.2.2, < 4.0)
60
+ rexml
50
61
  ruby-progressbar (~> 1.7)
51
- unicode-display_width (>= 1.4.0, < 1.7)
62
+ unicode-display_width (>= 1.4.0, < 2.0)
52
63
  rubocop-performance (1.5.2)
53
64
  rubocop (>= 0.71.0)
54
- rubocop-rails (2.4.1)
65
+ rubocop-rails (2.5.2)
66
+ activesupport
55
67
  rack (>= 1.1)
56
68
  rubocop (>= 0.72.0)
57
- rubocop-rake (0.5.0)
69
+ rubocop-rake (0.5.1)
58
70
  rubocop
59
- rubocop-rspec (1.37.1)
71
+ rubocop-rspec (1.38.1)
60
72
  rubocop (>= 0.68.1)
61
73
  ruby-progressbar (1.10.1)
62
- simplecov (0.17.1)
74
+ simplecov (0.18.5)
63
75
  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)
76
+ simplecov-html (~> 0.11)
77
+ simplecov-html (0.12.2)
78
+ smart_engine (0.7.0)
79
+ thread_safe (0.3.6)
80
+ tzinfo (1.2.7)
81
+ thread_safe (~> 0.1)
82
+ unicode-display_width (1.7.0)
83
+ zeitwerk (2.3.0)
69
84
 
70
85
  PLATFORMS
71
86
  ruby
72
87
 
73
88
  DEPENDENCIES
74
- armitage-rubocop (~> 0.78)
89
+ armitage-rubocop (~> 0.81)
75
90
  bundler (~> 2.1)
76
- pry (~> 0.12)
91
+ pry (~> 0.13)
77
92
  rake (~> 13.0)
78
93
  rspec (~> 3.9)
79
- simplecov (~> 0.17)
94
+ simplecov (~> 0.18)
80
95
  smart_container!
81
96
 
82
97
  BUNDLED WITH
83
- 2.1.2
98
+ 2.1.4
data/README.md CHANGED
@@ -22,9 +22,27 @@ require 'smart_core/container'
22
22
 
23
23
  ---
24
24
 
25
- ## Synopsis (demo)
25
+ ## Table of cotnents
26
26
 
27
- - container class creation:
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)
40
+
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,7 +112,24 @@ container.fetch('database') # => SmartCore::Container (nested container)
70
112
  container.fetch('database.resolver') # => #<SomeDatabaseResolver:0x00007f0f0f1d6332>
71
113
  ```
72
114
 
73
- - container keys (dependency names):
115
+ ---
116
+
117
+ #### runtime-level dependency/namespace registration
118
+
119
+ ```ruby
120
+ container.namespace(:api) do
121
+ register(:provider) { GoogleProvider } # without memoization
122
+ end
123
+
124
+ container.register('game_api', memoize: true) { 'overwatch' } # with memoization
125
+
126
+ container['api.provider'] # => GoogleProvider
127
+ container['game_api'] # => 'overwatch'
128
+ ```
129
+
130
+ ---
131
+
132
+ #### container keys (dependency names):
74
133
 
75
134
  ```ruby
76
135
  # get dependnecy keys (only dependencies)
@@ -101,6 +160,191 @@ container.keys(all_variants: true)
101
160
 
102
161
  ---
103
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?
170
+
171
+ ```ruby
172
+ container.key?('database') # => true
173
+ container.key?('database.cache.memcached') # => true
174
+
175
+ container.dependency?('database') # => false
176
+ container.dependency?('database.resolver') # => true
177
+
178
+ container.namespace?('database') # => true
179
+ container.namespace?('database.resolver') # => false
180
+
181
+ container.dependency?('database.resolver', memoized: true) # => true
182
+ container.dependency?('database.resolver', memoized: false) # => false
183
+
184
+ container.dependency?('random', memoized: true) # => false
185
+ container.dependency?('random', memoized: false) # => true
186
+ ```
187
+
188
+ ---
189
+
190
+ #### state freeze
191
+
192
+ - state freeze (`#freeze!`, `.#frozen?`):
193
+
194
+ ```ruby
195
+ # documentation is coming;
196
+ ```
197
+
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)`):
213
+
214
+ ```ruby
215
+ # documentation is coming;
216
+ ```
217
+
218
+ ---
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
+ - convinient way to rebind registered dependnecies:
310
+
311
+ ```ruby
312
+ # PoC
313
+
314
+ container['dependency.path'] = 'pek' # simplest instant dependency registration without memoization
315
+ # --- or/and ---
316
+ container.rebind('dependency.path', memoize: true/false) { 'pek' } # bind with dynamic dependency registration
317
+ container.rebind('dependency.path', memoize: true/false, 'pek') # bind with instant dependency registration
318
+ ```
319
+
320
+ - pattern-based pathes in dependency changement observing;
321
+
322
+ ```ruby
323
+ container.observe('path.*') { puts 'kek!' } # subscribe to all changements in `path` namespace;
324
+ ```
325
+
326
+ - support for instant dependency registration:
327
+
328
+ ```ruby
329
+ # common (dynamic) way:
330
+ register('dependency_name') { dependency_value }
331
+
332
+ # instant way:
333
+ register('dependency_name', dependency_value)
334
+ ```
335
+
336
+ - support for memoization ignorance during dependency resolving:
337
+
338
+ ```ruby
339
+ resolve('logger', :allocate) # Draft
340
+ ```
341
+
342
+ - container composition;
343
+
344
+ - support for fallback block in `.resolve` operation (similar to `Hash#fetch` works);
345
+
346
+ ---
347
+
104
348
  ## Contributing
105
349
 
106
350
  - Fork it ( https://github.com/smart-rb/smart_container/fork )