data-provider 0.1.0 → 0.2.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 +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
|