dry-container 0.2.1 → 0.2.2

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
  SHA1:
3
- metadata.gz: 80070803509a4e967b6874018aa178ab1fff0c12
4
- data.tar.gz: 3a46e86e6ada0346d0da825d93c04bb225f6d31d
3
+ metadata.gz: 00fac333cd99a672b9cb5d60dac62f5ebcb197c1
4
+ data.tar.gz: 3e040234421d7e23618d0a8fc6e5273ccdb73fb0
5
5
  SHA512:
6
- metadata.gz: e32f26c42d3d6c268866b72eba0b4a6bac760c278da01c8d3b46d0ac12b9c5ebcfa31a6150bd38ae88998d7561d77fe0f95d8ea33dc8d0ce0be7be657f1d676f
7
- data.tar.gz: 8dc9547baf6a1b3ba22767c9008d4cd467e444269a0341e4cf0a1da01ebc90b6cc91cf673ea695cb237b5775389213dbec52eef05e6b0c6ab0364acfb482f3eb
6
+ metadata.gz: f161b567597ebd6f7a102ca2815687dbd1d50b4bf6d95187e4252f4793e28ef9318cf38ffd71ffdd136721ad7b65aeadde21f392e8016c538b016236c2485618
7
+ data.tar.gz: 1d6644026909c74463aa84963876d6af086ed7c6c2e8246769159298e76a8bcec1381955d2031b99fdc129e9edcc1cc05eb2784d8f5f2b0d5d4161bbc028d510
data/.rubocop.yml CHANGED
@@ -18,3 +18,7 @@ Lint/NestedMethodDefinition:
18
18
  Metrics/MethodLength:
19
19
  Exclude:
20
20
  - lib/dry/container/mixin.rb
21
+
22
+ Style/FileName:
23
+ Exclude:
24
+ - lib/dry-container.rb
data/README.md CHANGED
@@ -49,6 +49,25 @@ container.register(:block, call: false) do
49
49
  end
50
50
  container.resolve(:block)
51
51
  # => #<Proc:0x007fa75e6830f0@(irb):36>
52
+
53
+ # You can also register items under namespaces using the #namespace method
54
+ container.namespace('repositories') do
55
+ namespace('checkout') do
56
+ register('orders') { ThreadSafe::Array.new }
57
+ end
58
+ end
59
+ container.resolve('repositories.checkout.orders')
60
+ # => []
61
+
62
+ # Or import a namespace
63
+ ns = Dry::Container::Namespace.new('repositories') do
64
+ namespace('authentication') do
65
+ register('users') { ThreadSafe::Array.new }
66
+ end
67
+ end
68
+ container.import(ns)
69
+ container.resolve('repositories.authentication.users')
70
+ # => []
52
71
  ```
53
72
 
54
73
  You can also get container behaviour at both the class and instance level via the mixin:
@@ -76,7 +95,7 @@ You can configure how items are registered and resolved from the container:
76
95
  ```ruby
77
96
  Dry::Container.configure do |config|
78
97
  config.registry = ->(container, key, item, options) { container[key] = item }
79
- config.resolver = ->(key) { container[key] }
98
+ config.resolver = ->(container, key) { container[key] }
80
99
  end
81
100
 
82
101
  class Container
@@ -84,7 +103,7 @@ class Container
84
103
 
85
104
  configure do |config|
86
105
  config.registry = ->(container, key, item, options) { container[key] = item }
87
- config.resolver = ->(key) { container[key] }
106
+ config.resolver = ->(container, key) { container[key] }
88
107
  end
89
108
  end
90
109
 
@@ -93,7 +112,7 @@ class ContainerObject
93
112
 
94
113
  configure do |config|
95
114
  config.registry = ->(container, key, item, options) { container[key] = item }
96
- config.resolver = ->(key) { container[key] }
115
+ config.resolver = ->(container, key) { container[key] }
97
116
  end
98
117
  end
99
118
  ```
data/lib/dry/container.rb CHANGED
@@ -2,11 +2,15 @@ require 'thread_safe'
2
2
  require 'dry-configurable'
3
3
  require 'dry/container/error'
4
4
  require 'dry/container/item'
5
+ require 'dry/container/namespace'
5
6
  require 'dry/container/registry'
6
7
  require 'dry/container/resolver'
8
+ require 'dry/container/namespace_dsl'
7
9
  require 'dry/container/mixin'
8
10
  require 'dry/container/version'
9
11
 
12
+ # A collection of micro-libraries, each intended to encapsulate
13
+ # a common task in Ruby
10
14
  module Dry
11
15
  # Inversion of Control (IoC) container
12
16
  #
@@ -31,10 +31,11 @@ module Dry
31
31
  base.class_eval do
32
32
  extend ::Dry::Configurable
33
33
 
34
- setting :registry, Registry.new
35
- setting :resolver, Resolver.new
34
+ setting :registry, ::Dry::Container::Registry.new
35
+ setting :resolver, ::Dry::Container::Resolver.new
36
+ setting :namespace_separator, '.'
36
37
 
37
- @_container = ThreadSafe::Cache.new
38
+ @_container = ::ThreadSafe::Cache.new
38
39
  end
39
40
  end
40
41
  # @private
@@ -42,13 +43,14 @@ module Dry
42
43
  base.class_eval do
43
44
  extend ::Dry::Configurable
44
45
 
45
- setting :registry, Registry.new
46
- setting :resolver, Resolver.new
46
+ setting :registry, ::Dry::Container::Registry.new
47
+ setting :resolver, ::Dry::Container::Resolver.new
48
+ setting :namespace_separator, '.'
47
49
 
48
50
  attr_reader :_container
49
51
 
50
52
  def initialize(*args, &block)
51
- @_container = ThreadSafe::Cache.new
53
+ @_container = ::ThreadSafe::Cache.new
52
54
  super(*args, &block)
53
55
  end
54
56
 
@@ -69,7 +71,7 @@ module Dry
69
71
  # If a block is given, contents will be ignored and the block
70
72
  # will be registered instead
71
73
  #
72
- # @return [Dry::Container] self
74
+ # @return [Dry::Container::Mixin] self
73
75
  #
74
76
  # @api public
75
77
  def register(key, contents = nil, options = {}, &block)
@@ -96,6 +98,37 @@ module Dry
96
98
  config.resolver.call(_container, key)
97
99
  end
98
100
  alias_method :[], :resolve
101
+ # Evaluate block and register items in namespace
102
+ #
103
+ # @param [Mixed] namespace
104
+ # The namespace to register items in
105
+ #
106
+ # @return [Dry::Container::Mixin] self
107
+ #
108
+ # @api public
109
+ def namespace(namespace, &block)
110
+ ::Dry::Container::NamespaceDSL.new(
111
+ self,
112
+ namespace,
113
+ config.namespace_separator,
114
+ &block
115
+ )
116
+
117
+ self
118
+ end
119
+ # Import a namespace
120
+ #
121
+ # @param [Dry::Container::Namespace] namespace
122
+ # The namespace to import
123
+ #
124
+ # @return [Dry::Container::Mixin] self
125
+ #
126
+ # @api public
127
+ def import(namespace)
128
+ namespace(namespace.name, &namespace.block)
129
+
130
+ self
131
+ end
99
132
  end
100
133
  end
101
134
  end
@@ -0,0 +1,38 @@
1
+ module Dry
2
+ class Container
3
+ # Create a namespace to be imported
4
+ #
5
+ # @example
6
+ #
7
+ # ns = Dry::Container::Namespace.new('name') do
8
+ # register('item', 'item')
9
+ # end
10
+ #
11
+ # container = Dry::Container.new
12
+ #
13
+ # container.import(ns)
14
+ #
15
+ # container.resolve('name.item')
16
+ # => 'item'
17
+ #
18
+ #
19
+ # @api public
20
+ class Namespace
21
+ attr_reader :name, :block
22
+ # Create a new namespace
23
+ #
24
+ # @param [Mixed] name
25
+ # The name of the namespace
26
+ # @yield
27
+ # The block to evaluate when the namespace is imported
28
+ #
29
+ # @return [Dry::Container::Namespace]
30
+ #
31
+ # @api public
32
+ def initialize(name, &block)
33
+ @name = name
34
+ @block = block
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,39 @@
1
+ module Dry
2
+ class Container
3
+ # @api private
4
+ class NamespaceDSL < ::SimpleDelegator
5
+ def initialize(container, namespace, namespace_separator, &block)
6
+ @namespace = namespace
7
+ @namespace_separator = namespace_separator
8
+
9
+ super(container)
10
+
11
+ if block.arity.zero?
12
+ instance_eval(&block)
13
+ else
14
+ block.call(self)
15
+ end
16
+ end
17
+
18
+ def register(key, *args, &block)
19
+ super(namespaced(key), *args, &block)
20
+ end
21
+
22
+ def namespace(namespace, &block)
23
+ super(namespaced(namespace), &block)
24
+ end
25
+
26
+ def import(namespace)
27
+ namespace(namespace.name, &namespace.block)
28
+
29
+ self
30
+ end
31
+
32
+ private
33
+
34
+ def namespaced(key)
35
+ [@namespace, key].join(@namespace_separator)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -6,7 +6,7 @@ module Dry
6
6
  class Registry
7
7
  # @private
8
8
  def initialize
9
- @_mutex = Mutex.new
9
+ @_mutex = ::Mutex.new
10
10
  end
11
11
  # Register an item with the container to be resolved later
12
12
  #
@@ -31,7 +31,7 @@ module Dry
31
31
  if container.key?(key)
32
32
  fail Error, "There is already an item registered with the key #{key.inspect}"
33
33
  else
34
- container[key] = Item.new(item, options)
34
+ container[key] = ::Dry::Container::Item.new(item, options)
35
35
  end
36
36
  end
37
37
  end
@@ -1,6 +1,6 @@
1
1
  module Dry
2
2
  class Container
3
3
  # @api public
4
- VERSION = '0.2.1'.freeze
4
+ VERSION = '0.2.2'.freeze
5
5
  end
6
6
  end
@@ -72,6 +72,41 @@ shared_examples 'a container' do
72
72
  it { is_expected.to eq(item) }
73
73
  end
74
74
  end
75
+
76
+ describe 'namespace_separator' do
77
+ describe 'default' do
78
+ it { expect(klass.config.namespace_separator).to eq('.') }
79
+ end
80
+
81
+ describe 'custom' do
82
+ let(:custom_registry) { double('Registry') }
83
+ let(:key) { 'key' }
84
+ let(:namespace_separator) { '-' }
85
+ let(:namespace) { 'one' }
86
+
87
+ before do
88
+ klass.configure do |config|
89
+ config.namespace_separator = namespace_separator
90
+ end
91
+
92
+ container.namespace(namespace) do
93
+ register('key', 'item')
94
+ end
95
+ end
96
+
97
+ after do
98
+ # HACK: Have to reset the configuration so that it doesn't
99
+ # interfere with other specs
100
+ klass.configure do |config|
101
+ config.namespace_separator = '.'
102
+ end
103
+ end
104
+
105
+ subject! { container.resolve([namespace, key].join(namespace_separator)) }
106
+
107
+ it { is_expected.to eq('item') }
108
+ end
109
+ end
75
110
  end
76
111
 
77
112
  context 'with default configuration' do
@@ -149,5 +184,75 @@ shared_examples 'a container' do
149
184
  expect { container.resolve(:item) }.to raise_error(Dry::Container::Error)
150
185
  end
151
186
  end
187
+
188
+ describe 'namespace' do
189
+ context 'when block does not take arguments' do
190
+ before do
191
+ container.namespace('one') do
192
+ register('two', 2)
193
+ end
194
+ end
195
+
196
+ subject! { container.resolve('one.two') }
197
+
198
+ it 'registers items under the given namespace' do
199
+ is_expected.to eq(2)
200
+ end
201
+ end
202
+
203
+ context 'when block takes arguments' do
204
+ before do
205
+ container.namespace('one') do |c|
206
+ c.register('two', 2)
207
+ end
208
+ end
209
+
210
+ subject! { container.resolve('one.two') }
211
+
212
+ it 'registers items under the given namespace' do
213
+ is_expected.to eq(2)
214
+ end
215
+ end
216
+
217
+ context 'with nesting' do
218
+ before do
219
+ container.namespace('one') do
220
+ namespace('two') do
221
+ register('three', 3)
222
+ end
223
+ end
224
+ end
225
+
226
+ subject! { container.resolve('one.two.three') }
227
+
228
+ it 'registers items under the given namespaces' do
229
+ is_expected.to eq(3)
230
+ end
231
+ end
232
+ end
233
+
234
+ describe 'import' do
235
+ it 'allows importing of namespaces' do
236
+ ns = Dry::Container::Namespace.new('one') do
237
+ register('two', 2)
238
+ end
239
+
240
+ container.import(ns)
241
+
242
+ expect(container.resolve('one.two')).to eq(2)
243
+ end
244
+
245
+ it 'allows importing of nested namespaces' do
246
+ ns = Dry::Container::Namespace.new('two') do
247
+ register('three', 3)
248
+ end
249
+
250
+ container.namespace('one') do
251
+ import(ns)
252
+ end
253
+
254
+ expect(container.resolve('one.two.three')).to eq(3)
255
+ end
256
+ end
152
257
  end
153
258
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dry-container
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Holland
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-07-20 00:00:00.000000000 Z
11
+ date: 2015-08-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thread_safe
@@ -102,6 +102,8 @@ files:
102
102
  - lib/dry/container/error.rb
103
103
  - lib/dry/container/item.rb
104
104
  - lib/dry/container/mixin.rb
105
+ - lib/dry/container/namespace.rb
106
+ - lib/dry/container/namespace_dsl.rb
105
107
  - lib/dry/container/registry.rb
106
108
  - lib/dry/container/resolver.rb
107
109
  - lib/dry/container/version.rb