data-provider 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +2 -2
- data/data-provider.gemspec +2 -5
- data/lib/data_provider/base.rb +149 -146
- data/lib/data_provider/container.rb +277 -0
- data/lib/data_provider.rb +1 -0
- data/spec/base_spec.rb +818 -0
- data/spec/container_spec.rb +792 -0
- data/spec/data_provider_spec.rb +85 -349
- metadata +4 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3463cfbe49623868590249a50db750da286c65f2
|
4
|
+
data.tar.gz: 9dad29a26d14bbb7fd2f5a38c9d6761dc38e3710
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 95affc545a8fd0e3d60b32b88a36f692ac1b97093991d3b33f6292559922586ed587650ed511db4a6f7af59a04d7c5a86153f7fc96dfe60f685c648d33c9b1b6
|
7
|
+
data.tar.gz: f907443bc27cf6917cf845da401c771377078998562cd897b010468404b8c6de1000bdefd97a4fd5eaa31942987ba25d3a4192fd11c6b892cc55152b7631708b
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -71,9 +71,9 @@ product_provider.take(:discount_price) # => TypeError (discount data not given,)
|
|
71
71
|
discounted_provider = product_provider.add_data(discount: 3.0) # returns a new instance of the same provider class
|
72
72
|
discounted_provider.take(:discount_price) # => 14.99
|
73
73
|
product_provider.take(:discount_price) # => TypeError (this instance didn't get the new data)
|
74
|
-
product_provider.
|
74
|
+
product_provider.add_data!(discount: 2) # => Updates this instance instead of creating a new one
|
75
75
|
product_provider.take(:discount_price) # => 15.99
|
76
|
-
product_provider.
|
76
|
+
product_provider.add_data!(discount: 4).take(:discount_price) #=> 13.99
|
77
77
|
```
|
78
78
|
|
79
79
|
Providers can be defined in a module and added to a provider class using the add class-method (not using include!)
|
data/data-provider.gemspec
CHANGED
@@ -1,9 +1,6 @@
|
|
1
|
-
GEM_NAME="data-provider"
|
2
|
-
PKG_VERSION='0.1.0'
|
3
|
-
|
4
1
|
Gem::Specification.new do |s|
|
5
|
-
s.name =
|
6
|
-
s.version =
|
2
|
+
s.name = "data-provider"
|
3
|
+
s.version = '0.2.0'
|
7
4
|
s.files = `git ls-files`.split($/)
|
8
5
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
9
6
|
|
data/lib/data_provider/base.rb
CHANGED
@@ -2,226 +2,229 @@ require 'logger'
|
|
2
2
|
|
3
3
|
module DataProvider
|
4
4
|
|
5
|
-
class ProviderMissingException < Exception
|
6
|
-
end
|
7
|
-
|
8
5
|
module Base
|
9
6
|
|
10
7
|
def self.included(base)
|
11
8
|
base.class_eval do
|
12
9
|
include InstanceMethods
|
10
|
+
include ProxyMethods
|
13
11
|
extend ClassMethods
|
12
|
+
extend ProxyMethods
|
14
13
|
end
|
15
14
|
end
|
16
15
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
@data_provider ||= {}
|
24
|
-
@data_provider[:provides] ||= {}
|
25
|
-
@data_provider[:provides].merge!(simple_provides)
|
26
|
-
return self
|
27
|
-
end
|
28
|
-
# no data given? just return existing hash
|
29
|
-
(@data_provider || {})[:provides] || {}
|
16
|
+
# both instance- class-level
|
17
|
+
module ProxyMethods
|
18
|
+
def provides *args
|
19
|
+
return dpc.provides if args.length == 0
|
20
|
+
dpc.provides *args
|
21
|
+
return self
|
30
22
|
end
|
31
23
|
|
32
|
-
|
33
|
-
|
34
|
-
args = data_provider_definitions.find{|args| args.first == id}
|
35
|
-
return args.nil? ? nil : Provider.new(*args)
|
24
|
+
def provider_identifiers *args
|
25
|
+
dpc.provider_identifiers *args
|
36
26
|
end
|
37
27
|
|
38
|
-
def
|
39
|
-
|
28
|
+
def provider *args, &block
|
29
|
+
dpc.provider *args, &block
|
40
30
|
end
|
41
31
|
|
42
|
-
|
43
|
-
|
44
|
-
add_provider(identifier, opts, block_given? ? block : nil)
|
32
|
+
def has_provider? *args
|
33
|
+
dpc.has_provider? *args
|
45
34
|
end
|
46
35
|
|
47
|
-
|
48
|
-
|
49
|
-
((@data_provider || {})[:provider_args] || [])
|
36
|
+
def has_providers_with_scope?(*args)
|
37
|
+
dpc.has_providers_with_scope?(*args)
|
50
38
|
end
|
51
39
|
|
52
|
-
|
53
|
-
|
54
|
-
(provides[identifier] || get_provider(identifier)) != nil
|
40
|
+
def fallback_provider?
|
41
|
+
dpc.fallback_provider?
|
55
42
|
end
|
56
43
|
|
57
|
-
def
|
58
|
-
|
59
|
-
provider_identifiers.find{|id| id.is_a?(Array) && id.length > scope.length && id[0..(scope.length-1)] == scope} != nil
|
44
|
+
def provider_missing *args, &block
|
45
|
+
dpc.provider_missing *args, &block
|
60
46
|
end
|
61
47
|
|
62
|
-
def
|
63
|
-
|
48
|
+
def take(id, opts = {})
|
49
|
+
dpc.take(id, opts.merge(:scope => self))
|
64
50
|
end
|
65
51
|
|
66
|
-
|
67
|
-
|
68
|
-
data = providers_module.instance_variable_get('@data_provider') || {}
|
69
|
-
|
70
|
-
(data[:provider_args] || []).each do |definition|
|
71
|
-
add_provider(*definition)
|
72
|
-
end
|
73
|
-
|
74
|
-
self.provides(data[:provides] || {})
|
52
|
+
def try_take(id, opts = {})
|
53
|
+
dpc.try_take(id, opts.merge(:scope => self))
|
75
54
|
end
|
76
55
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
data = providers_module.instance_variable_get('@data_provider') || {}
|
56
|
+
def got?(*args)
|
57
|
+
dpc.got?(*args)
|
58
|
+
end
|
81
59
|
|
82
|
-
|
83
|
-
definition[0] = [definition[0]].flatten
|
84
|
-
definition[0] = [_options[:scope]].flatten.compact + definition[0] if _options[:scope]
|
85
|
-
add_provider(*definition)
|
86
|
-
end
|
60
|
+
alias :has_data? :got?
|
87
61
|
|
88
|
-
|
89
|
-
|
90
|
-
end
|
62
|
+
def given *args
|
63
|
+
dpc.given *args
|
91
64
|
end
|
92
65
|
|
93
|
-
|
94
|
-
raise "DataProvider::Base#provider_missing expects a block as an argument" if !block_given?
|
95
|
-
@data_provider ||= {}
|
96
|
-
@data_provider[:provider_missing] = block
|
97
|
-
end
|
66
|
+
alias :get_data :given
|
98
67
|
|
99
|
-
def
|
100
|
-
|
101
|
-
|
68
|
+
def give! *args
|
69
|
+
dpc.give! *args
|
70
|
+
return self
|
102
71
|
end
|
103
72
|
|
73
|
+
alias :add_scope! :give!
|
74
|
+
alias :add_data! :give!
|
75
|
+
|
104
76
|
private
|
105
77
|
|
106
|
-
def
|
107
|
-
|
108
|
-
@data_provider[:provider_args] ||= []
|
109
|
-
@data_provider[:provider_args].unshift [identifier, opts, block]
|
78
|
+
def missing_provider *args
|
79
|
+
dpc.missing_provider *args
|
110
80
|
end
|
111
|
-
end # module ClassMethods
|
112
|
-
|
113
81
|
|
114
|
-
|
82
|
+
def scoped_take *args
|
83
|
+
dpc.scoped_take *args
|
84
|
+
end
|
115
85
|
|
116
|
-
|
117
|
-
|
86
|
+
def scope *args
|
87
|
+
dpc.scope *args
|
88
|
+
end
|
118
89
|
|
119
|
-
def
|
120
|
-
|
121
|
-
@data = options[:data].is_a?(Hash) ? options[:data] : {}
|
90
|
+
def scopes *args
|
91
|
+
dpc.scopes *args
|
122
92
|
end
|
123
93
|
|
124
|
-
def
|
125
|
-
|
94
|
+
def provider_stack *args
|
95
|
+
dpc.provider_stack *args
|
126
96
|
end
|
127
97
|
|
128
|
-
def
|
129
|
-
|
98
|
+
def provider_id *args
|
99
|
+
dpc.provider_id *args
|
130
100
|
end
|
101
|
+
end
|
131
102
|
|
132
|
-
|
133
|
-
|
103
|
+
module ClassMethods
|
104
|
+
def data_provider_container
|
105
|
+
@data_provider_container ||= DataProvider::Container.new
|
134
106
|
end
|
135
107
|
|
136
|
-
|
137
|
-
|
108
|
+
alias :dpc :data_provider_container
|
109
|
+
|
110
|
+
# can't copy self on a class-level
|
111
|
+
def give *args
|
112
|
+
dpc.give! *args
|
113
|
+
return self
|
138
114
|
end
|
139
115
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
provider = self.class.provides[id]
|
144
|
-
return provider.is_a?(Proc) ? provider.call : provider
|
145
|
-
end
|
146
|
-
# try to get a provider object
|
147
|
-
provider = self.class.get_provider(id)
|
148
|
-
if provider
|
149
|
-
@scope ||= []
|
150
|
-
@scope << (id.is_a?(Array) ? id[0..-2] : [])
|
151
|
-
result = instance_eval(&provider.block)
|
152
|
-
@scope.pop
|
153
|
-
# execute provider object's block within the scope of self
|
154
|
-
return result
|
155
|
-
end
|
116
|
+
# alias :give :give!
|
117
|
+
alias :add_scope :give
|
118
|
+
alias :add_data :give
|
156
119
|
|
157
|
-
|
158
|
-
if
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
@scope ||= []
|
163
|
-
@scope << (id.is_a?(Array) ? id[0..-2] : [])
|
164
|
-
result = instance_eval(&provider.block) # provider.block.call # with the block.call method the provider can't access private methods like missing_provider
|
165
|
-
@scope = nil
|
166
|
-
return result
|
120
|
+
def add! _module
|
121
|
+
if _module.is_a?(DataProvider::Container)
|
122
|
+
dpc.add!(_module)
|
123
|
+
else
|
124
|
+
dpc.add!(_module.dpc)
|
167
125
|
end
|
168
|
-
# no fallback either? Time for an error
|
169
|
-
raise ProviderMissingException.new(:message=>"Tried to take data from missing provider.", :provider_id => id)
|
170
|
-
end
|
171
126
|
|
172
|
-
|
173
|
-
return
|
174
|
-
|
127
|
+
include _module
|
128
|
+
return self
|
129
|
+
end
|
175
130
|
|
176
|
-
|
177
|
-
|
131
|
+
def add_scoped! _module, options = {}
|
132
|
+
if _module.is_a?(DataProvider::Container)
|
133
|
+
dpc.add_scoped!(_module, options)
|
134
|
+
else
|
135
|
+
dpc.add_scoped! _module.dpc, options
|
178
136
|
end
|
137
|
+
|
138
|
+
include _module
|
139
|
+
return self
|
179
140
|
end
|
180
141
|
|
181
|
-
|
142
|
+
# classes/modules can't be cloned, so add behave just like add!
|
143
|
+
alias :add :add!
|
144
|
+
alias :add_scoped :add_scoped!
|
145
|
+
end # module ClassMethods
|
146
|
+
|
147
|
+
|
148
|
+
module InstanceMethods
|
182
149
|
|
183
|
-
|
184
|
-
|
150
|
+
attr_reader :options
|
151
|
+
|
152
|
+
def initialize(opts = {})
|
153
|
+
@options = opts.is_a?(Hash) ? opts : {}
|
154
|
+
dpc.give!(options[:data]) if options[:data].is_a?(Hash)
|
185
155
|
end
|
186
156
|
|
187
|
-
|
157
|
+
def logger
|
158
|
+
@logger ||= options[:logger] || Logger.new(STDOUT).tap do |lger|
|
159
|
+
lger.level = Logger::WARN
|
160
|
+
end
|
161
|
+
end
|
188
162
|
|
189
|
-
def
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
163
|
+
def data_provider_container
|
164
|
+
@data_provider_container ||= options[:dpc] || DataProvider::Container.new.tap do |c|
|
165
|
+
# automatically adopt all class-level providers/provides/data
|
166
|
+
c.add! self.class.dpc
|
167
|
+
end
|
194
168
|
end
|
195
169
|
|
196
|
-
alias :
|
170
|
+
alias :dpc :data_provider_container
|
197
171
|
|
198
|
-
def
|
199
|
-
|
172
|
+
def add _module
|
173
|
+
if _module.is_a?(DataProvider::Container)
|
174
|
+
_dpc = _module
|
175
|
+
else
|
176
|
+
_dpc = _module.dpc
|
177
|
+
self.class.include _module # todo: make optional?
|
178
|
+
end
|
179
|
+
|
180
|
+
self.class.new(options.merge({
|
181
|
+
:data => nil,
|
182
|
+
:dpc => dpc.add(_dpc)
|
183
|
+
}))
|
200
184
|
end
|
201
185
|
|
202
|
-
|
203
|
-
|
186
|
+
def add_scoped _module, options = {}
|
187
|
+
if _module.is_a?(DataProvider::Container)
|
188
|
+
_dpc = _module
|
189
|
+
else
|
190
|
+
_dpc = _module.dpc
|
191
|
+
self.class.include _module # todo: make optional?
|
192
|
+
end
|
204
193
|
|
205
|
-
|
206
|
-
|
207
|
-
|
194
|
+
self.class.new(options.merge({
|
195
|
+
:data => nil,
|
196
|
+
:dpc => dpc.add_scoped(_dpc, :scope => options[:scope])
|
197
|
+
}))
|
208
198
|
end
|
209
199
|
|
210
|
-
|
211
|
-
|
200
|
+
def give *args
|
201
|
+
self.class.new(options.merge(:data => nil, :dpc => self.dpc.give(*args)))
|
202
|
+
end
|
212
203
|
|
213
|
-
|
204
|
+
alias :add_scope :give
|
205
|
+
alias :add_data :give
|
214
206
|
|
215
|
-
def
|
216
|
-
|
217
|
-
|
207
|
+
def add! _module
|
208
|
+
if _module.is_a?(DataProvider::Container)
|
209
|
+
dpc.add!(_module)
|
210
|
+
else
|
211
|
+
dpc.add!(_module.dpc)
|
212
|
+
self.class.include _module
|
213
|
+
end
|
214
|
+
|
215
|
+
return self
|
218
216
|
end
|
219
217
|
|
220
|
-
def
|
221
|
-
|
218
|
+
def add_scoped! _module, options = {}
|
219
|
+
if _module.is_a?(DataProvider::Container)
|
220
|
+
dpc.add_scoped!(_module, options)
|
221
|
+
else
|
222
|
+
dpc.add_scoped! _module.dpc, options
|
223
|
+
self.class.include _module
|
224
|
+
end
|
225
|
+
|
226
|
+
return self
|
222
227
|
end
|
223
228
|
end # module InstanceMethods
|
224
|
-
|
225
229
|
end # module Base
|
226
|
-
|
227
230
|
end # module DataProvider
|
@@ -0,0 +1,277 @@
|
|
1
|
+
module DataProvider
|
2
|
+
|
3
|
+
class ProviderMissingException < Exception
|
4
|
+
attr_reader :params
|
5
|
+
|
6
|
+
def initialize(_params = {})
|
7
|
+
@params = _params || {}
|
8
|
+
super(params[:message] || "Tried to take data from missing provider: #{provider_id.inspect}")
|
9
|
+
end
|
10
|
+
|
11
|
+
def provider_id
|
12
|
+
params[:provider_id]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
class Container
|
18
|
+
attr_reader :options
|
19
|
+
|
20
|
+
def initialize _opts = {}
|
21
|
+
@options = _opts.is_a?(Hash) ? _opts : {}
|
22
|
+
end
|
23
|
+
|
24
|
+
def logger
|
25
|
+
@logger ||= options[:logger] || Logger.new(STDOUT).tap do |lger|
|
26
|
+
lger.level = Logger::WARN
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def provider identifier, opts = {}, &block
|
31
|
+
add_provider(identifier, opts, block_given? ? block : nil)
|
32
|
+
end
|
33
|
+
|
34
|
+
def has_provider?(identifier)
|
35
|
+
(provides.keys.find{|k| k == identifier} || get_provider(identifier)) != nil
|
36
|
+
end
|
37
|
+
|
38
|
+
def has_providers_with_scope?(args)
|
39
|
+
scope = args.is_a?(Array) ? args : [args]
|
40
|
+
provider_identifiers.find{|id| id.is_a?(Array) && id.length > scope.length && id[0..(scope.length-1)] == scope} != nil
|
41
|
+
end
|
42
|
+
|
43
|
+
def provider_identifiers
|
44
|
+
(provides.keys + providers.map(&:first)).compact.uniq
|
45
|
+
end
|
46
|
+
|
47
|
+
# provides, when called with a hash param, will define 'simple providers' (providers
|
48
|
+
# with a simple, static value). When called without a param (or nil) it returns
|
49
|
+
# the current cumulative 'simple providers' hash
|
50
|
+
def provides _provides = nil
|
51
|
+
return @provides || {} if _provides.nil?
|
52
|
+
add_provides _provides
|
53
|
+
return self
|
54
|
+
end
|
55
|
+
|
56
|
+
def providers
|
57
|
+
@providers || []
|
58
|
+
end
|
59
|
+
|
60
|
+
def provider_missing &block
|
61
|
+
raise "DataProvider::Base#provider_missing expects a block as an argument" if !block_given?
|
62
|
+
@fallback_provider = block
|
63
|
+
end
|
64
|
+
|
65
|
+
def fallback_provider
|
66
|
+
block = @fallback_provider
|
67
|
+
block.nil? ? nil : Provider.new(nil, nil, block)
|
68
|
+
end
|
69
|
+
|
70
|
+
def fallback_provider?
|
71
|
+
!fallback_provider.nil?
|
72
|
+
end
|
73
|
+
|
74
|
+
def take(id, opts = {})
|
75
|
+
logger.debug "DataProvider::Container#take with id: #{id.inspect}"
|
76
|
+
|
77
|
+
# first try the simple providers
|
78
|
+
if provides.has_key?(id)
|
79
|
+
provider = provides[id]
|
80
|
+
return provider.is_a?(Proc) ? provider.call : provider
|
81
|
+
end
|
82
|
+
|
83
|
+
# try to get a provider object
|
84
|
+
provider = get_provider(id)
|
85
|
+
if provider
|
86
|
+
@stack = (@stack || []) + [id]
|
87
|
+
result = (opts[:scope] || self).instance_eval(&provider.block)
|
88
|
+
@stack.pop
|
89
|
+
# execute provider object's block within the scope of self
|
90
|
+
return result
|
91
|
+
end
|
92
|
+
|
93
|
+
# try to get a scoped provider object
|
94
|
+
if scope.length > 0
|
95
|
+
scoped_id = [scope, id].flatten
|
96
|
+
provider = get_provider(scoped_id)
|
97
|
+
if provider
|
98
|
+
@stack = (@stack || []) + [scoped_id]
|
99
|
+
result = (opts[:scope] || self).instance_eval(&provider.block)
|
100
|
+
@stack.pop
|
101
|
+
# execute provider object's block within the scope of self
|
102
|
+
return result
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# couldn't find requested provider, let's see if there's a fallback
|
107
|
+
if provider = fallback_provider
|
108
|
+
# temporarily set the @missing_provider instance variable, so the
|
109
|
+
# fallback provider can use it through the missing_provider private method
|
110
|
+
@missing_provider = id
|
111
|
+
@stack = (@stack || []) + [id]
|
112
|
+
result = (opts[:scope] || self).instance_eval(&provider.block) # provider.block.call # with the block.call method the provider can't access private methods like missing_provider
|
113
|
+
@stack.pop # = nil
|
114
|
+
@missing_provider = nil
|
115
|
+
return result
|
116
|
+
end
|
117
|
+
|
118
|
+
# no fallback either? Time for an error
|
119
|
+
raise ProviderMissingException.new(:provider_id => id)
|
120
|
+
end
|
121
|
+
|
122
|
+
def try_take(id, opts = {})
|
123
|
+
return take(id, opts) if self.has_provider?(id) || self.fallback_provider?
|
124
|
+
logger.debug "Try for missing provider: #{id.inspect}"
|
125
|
+
return nil
|
126
|
+
end
|
127
|
+
|
128
|
+
#
|
129
|
+
# "adding existing containers"-related methods
|
130
|
+
#
|
131
|
+
|
132
|
+
# adds all the providers defined in the given module to this class
|
133
|
+
def add!(container)
|
134
|
+
### add container's providers ###
|
135
|
+
# internally providers are added in reverse order (last one first)
|
136
|
+
# so at runtime you it's easy and fast to grab the latest provider
|
137
|
+
# so when adding now, we have to reverse the providers to get them in the original order
|
138
|
+
container.providers.reverse.each do |definition|
|
139
|
+
add_provider(*definition)
|
140
|
+
end
|
141
|
+
|
142
|
+
### add container's provides (simple providers) ###
|
143
|
+
self.provides(container.provides)
|
144
|
+
|
145
|
+
### fallback provider ###
|
146
|
+
@fallback_provider = container.fallback_provider.block if container.fallback_provider
|
147
|
+
|
148
|
+
### add container's data ###
|
149
|
+
give!(container.data)
|
150
|
+
end
|
151
|
+
|
152
|
+
def add(container)
|
153
|
+
# make a copy and add the container to that
|
154
|
+
give({}).add!(container)
|
155
|
+
end
|
156
|
+
|
157
|
+
# adds all the providers defined in the given module to this class,
|
158
|
+
# but turns their identifiers into array and prefixes the array with the :scope option
|
159
|
+
def add_scoped! container, _options = {}
|
160
|
+
### add container's providers ###
|
161
|
+
container.providers.reverse.each do |definition|
|
162
|
+
identifier = [definition[0]].flatten
|
163
|
+
identifier = [_options[:scope]].flatten.compact + identifier if _options[:scope]
|
164
|
+
add_provider(*([identifier]+definition[1..-1]))
|
165
|
+
end
|
166
|
+
|
167
|
+
### add container's provides (simple providers) ###
|
168
|
+
container.provides.each_pair do |key, value|
|
169
|
+
provides(([_options[:scope]].flatten.compact + [key].flatten.compact) => value)
|
170
|
+
end
|
171
|
+
|
172
|
+
### fallback provider ###
|
173
|
+
@fallback_provider = container.fallback_provider.block if container.fallback_provider
|
174
|
+
|
175
|
+
### add container's data ###
|
176
|
+
give!(container.data)
|
177
|
+
end
|
178
|
+
|
179
|
+
# adds all the providers defined in the given module to this class,
|
180
|
+
# but turns their identifiers into array and prefixes the array with the :scope option
|
181
|
+
def add_scoped container, _options = {}
|
182
|
+
copy.add_scoped!(container, _options)
|
183
|
+
end
|
184
|
+
|
185
|
+
#
|
186
|
+
# Data-related methods
|
187
|
+
#
|
188
|
+
|
189
|
+
def copy
|
190
|
+
c = self.class.new
|
191
|
+
c.add!(self)
|
192
|
+
end
|
193
|
+
|
194
|
+
def data
|
195
|
+
@data || {}
|
196
|
+
end
|
197
|
+
|
198
|
+
def give(_data = {})
|
199
|
+
copy.give!(_data)
|
200
|
+
end
|
201
|
+
|
202
|
+
alias :add_scope :give
|
203
|
+
alias :add_data :give
|
204
|
+
|
205
|
+
def give!(_data = {})
|
206
|
+
@data ||= {}
|
207
|
+
@data.merge!(_data)
|
208
|
+
return self
|
209
|
+
end
|
210
|
+
|
211
|
+
alias :add_scope! :give!
|
212
|
+
alias :add_data! :give!
|
213
|
+
|
214
|
+
def given(param_name)
|
215
|
+
return data[param_name] if got?(param_name)
|
216
|
+
logger.debug "Data provider expected missing data with identifier: #{param_name.inspect}"
|
217
|
+
# TODO: raise?
|
218
|
+
return nil
|
219
|
+
end
|
220
|
+
|
221
|
+
alias :get_data :given
|
222
|
+
|
223
|
+
|
224
|
+
def got?(param_name)
|
225
|
+
data.has_key?(param_name)
|
226
|
+
end
|
227
|
+
|
228
|
+
alias :has_data? :got?
|
229
|
+
|
230
|
+
def missing_provider
|
231
|
+
@missing_provider
|
232
|
+
end
|
233
|
+
|
234
|
+
def scoped_take(id)
|
235
|
+
take(scope + [id].flatten)
|
236
|
+
end
|
237
|
+
|
238
|
+
def provider_stack
|
239
|
+
(@stack || []).clone
|
240
|
+
end
|
241
|
+
|
242
|
+
def provider_id
|
243
|
+
provider_stack.last
|
244
|
+
end
|
245
|
+
|
246
|
+
def scopes
|
247
|
+
provider_stack.map{|provider_id| provider_id.is_a?(Array) ? provider_id[0..-2] : []}
|
248
|
+
end
|
249
|
+
|
250
|
+
def scope
|
251
|
+
scopes.last || []
|
252
|
+
end
|
253
|
+
|
254
|
+
private
|
255
|
+
|
256
|
+
def add_provider(identifier, opts = {}, block = nil)
|
257
|
+
@providers ||= []
|
258
|
+
@providers.unshift [identifier, opts, block]
|
259
|
+
end
|
260
|
+
|
261
|
+
def add_provides _provides = {}
|
262
|
+
if _provides.is_a?(Hash) != true
|
263
|
+
logger.error 'DataProvider::Container#add_provides received non-hash param'
|
264
|
+
return @provides
|
265
|
+
end
|
266
|
+
|
267
|
+
@provides ||= {}
|
268
|
+
@provides.merge! _provides
|
269
|
+
end
|
270
|
+
|
271
|
+
# returns the requested provider as a Provider object
|
272
|
+
def get_provider(id)
|
273
|
+
args = providers.find{|args| args.first == id}
|
274
|
+
return args.nil? ? nil : Provider.new(*args)
|
275
|
+
end
|
276
|
+
end # class Container
|
277
|
+
end # module DataProvider
|