dry-container 0.4.0 → 0.5.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
  SHA1:
3
- metadata.gz: 674ad0ad74a6d746feaad68d60327231693da1af
4
- data.tar.gz: 7f61c7b298cbccb1f0c0b34d7df4a116d0a500ef
3
+ metadata.gz: 2f11ec3380a6ff086362780a67b687935cff8ddf
4
+ data.tar.gz: 15db84953170fdc3f249d852d01d106f7a904f23
5
5
  SHA512:
6
- metadata.gz: d794c0b798bb18519f10b7625f351193a3e768c7870d57a95adc76cb1d2e4a2c45a679622349c2c3404922346a3108b6c42cafe9a51b7a51dc34790c98ad9f89
7
- data.tar.gz: 5581b7fff68c5eb4e50a8bdd949043b54464f6f103eb6719bc9a6b7ad27a57e077d4b8118d76df8d929bd6d67af2f39fe396505f106263948a74bde96b1bf826
6
+ metadata.gz: f36ffd98d0c80ffd158e1554a09dd89919aeb7c780010a276118ad217db89d9ace865746c18b97321b6022d75dc5a4e46523d27927cd01ee182d0bb3b6b105b8
7
+ data.tar.gz: 7b52ee74e85b40edad15d082ad5fc64a20a00947a8d97d472be013f4f98fe363be5c25f007cd6d089582d0302034b35ed0041ce843e276c896100a9775a2a14a
@@ -0,0 +1,11 @@
1
+ ## v0.5.0
2
+
3
+ ## Added
4
+
5
+ * `memoize` option to `#register` - memoizes items on first resolve ([ivoanjo](https://github.com/ivoanjo))
6
+
7
+ ## Fixed
8
+
9
+ * `required_ruby_version` set to `>= 2.0.0` ([artofhuman](https://github.com/artofhuman))
10
+
11
+ [Compare v0.4.0...HEAD](https://github.com/dry-rb/dry-container/compare/v0.4.0...HEAD)
data/README.md CHANGED
@@ -91,6 +91,29 @@ end
91
91
  container.import(ns)
92
92
  container.resolve('repositories.authentication.users')
93
93
  # => []
94
+
95
+ # You can also register a block that is used to initialize a dependency and
96
+ # then memoize it, allowing several dependencies to be added without
97
+ # enforcing an instantiation order
98
+ class MessagePrinter
99
+ def initialize(container)
100
+ @message = container.resolve(:message)
101
+ @time = Time.now
102
+ end
103
+
104
+ def print
105
+ puts "#{@message} at #{@time}"
106
+ end
107
+ end
108
+
109
+ container.register(:message_printer, -> { MessagePrinter.new(container) }, memoize: true)
110
+ container.register(:message, 'Hello, world!')
111
+ container.resolve(:message_printer).print
112
+ # => Hello, world! at 2016-08-30 05:32:12 -0700
113
+
114
+ # Same instance is reused next time
115
+ container.resolve(:message_printer).print
116
+ # => Hello, world! at 2016-08-30 05:32:12 -0700
94
117
  ```
95
118
 
96
119
  You can also get container behaviour at both the class and instance level via the mixin:
@@ -15,6 +15,8 @@ Gem::Specification.new do |spec|
15
15
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
16
16
  spec.require_paths = ['lib']
17
17
 
18
+ spec.required_ruby_version = ">= 2.0.0"
19
+
18
20
  spec.add_runtime_dependency 'concurrent-ruby', '~> 1.0'
19
21
  spec.add_runtime_dependency 'dry-configurable', '~> 0.1', '>= 0.1.3'
20
22
 
@@ -4,22 +4,41 @@ module Dry
4
4
  #
5
5
  # @private
6
6
  class Item
7
- attr_reader :item, :options
7
+ attr_reader :item, :options, :memoize, :memoize_mutex
8
8
 
9
9
  def initialize(item, options = {})
10
10
  @item = item
11
11
  @options = {
12
12
  call: item.is_a?(::Proc) && item.parameters.empty?
13
13
  }.merge(options)
14
+
15
+ if options[:memoize] == true
16
+ raise(
17
+ ::Dry::Container::Error,
18
+ 'Memoize only supported for a block or a proc'
19
+ ) unless item.is_a?(::Proc)
20
+ @memoize = true
21
+ @memoize_mutex = ::Mutex.new
22
+ end
14
23
  end
15
24
 
16
25
  def call
26
+ return memoized_item if memoize
27
+
17
28
  if options[:call] == true
18
29
  item.call
19
30
  else
20
31
  item
21
32
  end
22
33
  end
34
+
35
+ private
36
+
37
+ def memoized_item
38
+ memoize_mutex.synchronize do
39
+ @memoized_item ||= item.call
40
+ end
41
+ end
23
42
  end
24
43
  end
25
44
  end
@@ -1,7 +1,7 @@
1
1
  module Dry
2
2
  class Container
3
3
  PREFIX_NAMESPACE = ->(namespace, key, config) do
4
- [namespace, key].compact.join(config.namespace_separator)
4
+ [namespace, key].join(config.namespace_separator)
5
5
  end
6
6
  # Mixin to expose Inversion of Control (IoC) container behaviour
7
7
  #
@@ -125,16 +125,24 @@ module Dry
125
125
  #
126
126
  # @param [Dry::Container] other
127
127
  # The other container to merge in
128
+ # @param [Hash] options
129
+ # @option options [Symbol] :namespace
130
+ # Namespace to prefix other container items with, defaults to nil
128
131
  #
129
132
  # @return [Dry::Container::Mixin] self
130
133
  #
131
134
  # @api public
132
135
  def merge(other, namespace: nil)
133
- _container.merge!(
134
- other._container.each_with_object(::Concurrent::Hash.new) do |a, h|
135
- h[PREFIX_NAMESPACE.call(namespace, a.first, config)] = a.last
136
- end
137
- )
136
+ if namespace
137
+ _container.merge!(
138
+ other._container.each_with_object(::Concurrent::Hash.new) do |a, h|
139
+ h[PREFIX_NAMESPACE.call(namespace, a.first, config)] = a.last
140
+ end
141
+ )
142
+ else
143
+ _container.merge!(other._container)
144
+ end
145
+
138
146
  self
139
147
  end
140
148
 
@@ -21,7 +21,7 @@ module Dry
21
21
  # @option options [Symbol] :call
22
22
  # Whether the item should be called when resolved
23
23
  #
24
- # @raise [Dry::Conainer::Error]
24
+ # @raise [Dry::Container::Error]
25
25
  # If an item is already registered with the given key
26
26
  #
27
27
  # @return [Mixed]
@@ -1,6 +1,6 @@
1
1
  module Dry
2
2
  class Container
3
3
  # @api public
4
- VERSION = '0.4.0'.freeze
4
+ VERSION = '0.5.0'.freeze
5
5
  end
6
6
  end
@@ -185,6 +185,33 @@ shared_examples 'a container' do
185
185
  expect(container[:item].call).to eq('item')
186
186
  end
187
187
  end
188
+
189
+ context 'with option memoize: true' do
190
+ it 'registers and resolves a proc' do
191
+ container.register(:item, proc { 'item' }, memoize: true)
192
+
193
+ expect(container[:item]).to be container[:item]
194
+ expect(container.keys).to eq(['item'])
195
+ expect(container.key?(:item)).to be true
196
+ expect(container.resolve(:item)).to eq('item')
197
+ expect(container[:item]).to eq('item')
198
+ end
199
+
200
+ it 'only resolves the proc once' do
201
+ resolved_times = 0
202
+
203
+ container.register(:item, proc { resolved_times += 1 }, memoize: true)
204
+
205
+ expect(container.resolve(:item)).to be 1
206
+ expect(container.resolve(:item)).to be 1
207
+ end
208
+
209
+ context 'when receiving something other than a proc' do
210
+ it do
211
+ expect { container.register(:item, 'Hello!', memoize: true) }.to raise_error(Dry::Container::Error)
212
+ end
213
+ end
214
+ end
188
215
  end
189
216
 
190
217
  describe 'registering an object' do
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.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Holland
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-14 00:00:00.000000000 Z
11
+ date: 2016-08-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -99,6 +99,7 @@ files:
99
99
  - ".rubocop.yml"
100
100
  - ".rubocop_todo.yml"
101
101
  - ".travis.yml"
102
+ - CHANGELOG.md
102
103
  - Gemfile
103
104
  - LICENSE
104
105
  - README.md
@@ -132,7 +133,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
132
133
  requirements:
133
134
  - - ">="
134
135
  - !ruby/object:Gem::Version
135
- version: '0'
136
+ version: 2.0.0
136
137
  required_rubygems_version: !ruby/object:Gem::Requirement
137
138
  requirements:
138
139
  - - ">="
@@ -149,4 +150,3 @@ test_files:
149
150
  - spec/integration/mixin_spec.rb
150
151
  - spec/spec_helper.rb
151
152
  - spec/support/shared_examples/container.rb
152
- has_rdoc: