Class: DataProvider::Container

Inherits:
Object
  • Object
show all
Defined in:
lib/data_provider/container.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(_opts = {}) ⇒ Container

Returns a new instance of Container.



20
21
22
# File 'lib/data_provider/container.rb', line 20

def initialize _opts = {}
  @options = _opts.is_a?(Hash) ? _opts : {}
end

Instance Attribute Details

#optionsObject (readonly)

Returns the value of attribute options.



18
19
20
# File 'lib/data_provider/container.rb', line 18

def options
  @options
end

Instance Method Details

#add(container) ⇒ Object



152
153
154
155
# File 'lib/data_provider/container.rb', line 152

def add(container)
  # make a copy and add the container to that 
  give({}).add!(container)
end

#add!(container) ⇒ Object

adds all the providers defined in the given module to this class



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/data_provider/container.rb', line 133

def add!(container)
  ### add container's providers ###
  # internally providers are added in reverse order (last one first)
  # so at runtime you it's easy and fast to grab the latest provider
  # so when adding now, we have to reverse the providers to get them in the original order
  container.providers.reverse.each do |definition|
    add_provider(*definition)
  end

  ### add container's provides (simple providers) ###
  self.provides(container.provides)

  ### fallback provider ###
  @fallback_provider = container.fallback_provider.block if container.fallback_provider

  ### add container's data ###
  give!(container.data)
end

#add_scoped(container, _options = {}) ⇒ Object

adds all the providers defined in the given module to this class, but turns their identifiers into array and prefixes the array with the :scope option



181
182
183
# File 'lib/data_provider/container.rb', line 181

def add_scoped container, _options = {}
  copy.add_scoped!(container, _options)
end

#add_scoped!(container, _options = {}) ⇒ Object

adds all the providers defined in the given module to this class, but turns their identifiers into array and prefixes the array with the :scope option



159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/data_provider/container.rb', line 159

def add_scoped! container, _options = {}
  ### add container's providers ###
  container.providers.reverse.each do |definition|
    identifier = [definition[0]].flatten
    identifier = [_options[:scope]].flatten.compact + identifier if _options[:scope]
    add_provider(*([identifier]+definition[1..-1]))
  end

  ### add container's provides (simple providers) ###
  container.provides.each_pair do |key, value|
    provides(([_options[:scope]].flatten.compact + [key].flatten.compact) => value)
  end

  ### fallback provider ###
  @fallback_provider = container.fallback_provider.block if container.fallback_provider

  ### add container's data ###
  give!(container.data)
end

#copyObject

Data-related methods



189
190
191
192
# File 'lib/data_provider/container.rb', line 189

def copy
  c = self.class.new
  c.add!(self)
end

#dataObject



194
195
196
# File 'lib/data_provider/container.rb', line 194

def data
  @data || {}
end

#fallback_providerObject



65
66
67
68
# File 'lib/data_provider/container.rb', line 65

def fallback_provider
  block = @fallback_provider
  block.nil? ? nil : Provider.new(nil, nil, block)
end

#fallback_provider?Boolean

Returns:

  • (Boolean)


70
71
72
# File 'lib/data_provider/container.rb', line 70

def fallback_provider?
  !fallback_provider.nil?
end

#give(_data = {}) ⇒ Object Also known as: add_scope, add_data



198
199
200
# File 'lib/data_provider/container.rb', line 198

def give(_data = {})
  copy.give!(_data)
end

#give!(_data = {}) ⇒ Object Also known as: add_scope!, add_data!



205
206
207
208
209
# File 'lib/data_provider/container.rb', line 205

def give!(_data = {})
  @data ||= {}
  @data.merge!(_data)
  return self
end

#given(param_name) ⇒ Object Also known as: get_data



214
215
216
217
218
219
# File 'lib/data_provider/container.rb', line 214

def given(param_name)
  return data[param_name] if got?(param_name)
  logger.debug "Data provider expected missing data with identifier: #{param_name.inspect}"
  # TODO: raise?
  return nil
end

#got?(param_name) ⇒ Boolean Also known as: has_data?

Returns:

  • (Boolean)


224
225
226
# File 'lib/data_provider/container.rb', line 224

def got?(param_name)
  data.has_key?(param_name)
end

#has_provider?(identifier) ⇒ Boolean

Returns:

  • (Boolean)


34
35
36
# File 'lib/data_provider/container.rb', line 34

def has_provider?(identifier)
  (provides.keys.find{|k| k == identifier} || get_provider(identifier)) != nil
end

#has_providers_with_scope?(args) ⇒ Boolean

Returns:

  • (Boolean)


38
39
40
41
# File 'lib/data_provider/container.rb', line 38

def has_providers_with_scope?(args)
  scope = args.is_a?(Array) ? args : [args]
  provider_identifiers.find{|id| id.is_a?(Array) && id.length > scope.length && id[0..(scope.length-1)] == scope} != nil
end

#loggerObject



24
25
26
27
28
# File 'lib/data_provider/container.rb', line 24

def logger
  @logger ||= options[:logger] || Logger.new(STDOUT).tap do |lger|
    lger.level = Logger::WARN
  end
end

#missing_providerObject



230
231
232
# File 'lib/data_provider/container.rb', line 230

def missing_provider
  @missing_provider
end

#provider(identifier, opts = {}, &block) ⇒ Object



30
31
32
# File 'lib/data_provider/container.rb', line 30

def provider identifier, opts = {}, &block
  add_provider(identifier, opts, block_given? ? block : nil)
end

#provider_idObject



242
243
244
# File 'lib/data_provider/container.rb', line 242

def provider_id
  provider_stack.last
end

#provider_identifiersObject



43
44
45
# File 'lib/data_provider/container.rb', line 43

def provider_identifiers
  (provides.keys + providers.map(&:first)).compact.uniq
end

#provider_missing(&block) ⇒ Object



60
61
62
63
# File 'lib/data_provider/container.rb', line 60

def provider_missing &block
  raise "DataProvider::Base#provider_missing expects a block as an argument" if !block_given?
  @fallback_provider = block
end

#provider_stackObject



238
239
240
# File 'lib/data_provider/container.rb', line 238

def provider_stack
  (@stack || []).clone
end

#providersObject



56
57
58
# File 'lib/data_provider/container.rb', line 56

def providers
  @providers || []
end

#provides(_provides = nil) ⇒ Object

provides, when called with a hash param, will define ‘simple providers’ (providers with a simple, static value). When called without a param (or nil) it returns the current cumulative ‘simple providers’ hash



50
51
52
53
54
# File 'lib/data_provider/container.rb', line 50

def provides _provides = nil
  return @provides || {} if _provides.nil?
  add_provides _provides
  return self
end

#scopeObject



250
251
252
# File 'lib/data_provider/container.rb', line 250

def scope
  scopes.last || []
end

#scoped_take(id) ⇒ Object



234
235
236
# File 'lib/data_provider/container.rb', line 234

def scoped_take(id)
  take(scope + [id].flatten)
end

#scopesObject



246
247
248
# File 'lib/data_provider/container.rb', line 246

def scopes
  provider_stack.map{|provider_id| provider_id.is_a?(Array) ? provider_id[0..-2] : []}
end

#take(id, opts = {}) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/data_provider/container.rb', line 74

def take(id, opts = {})
  logger.debug "DataProvider::Container#take with id: #{id.inspect}"

  # first try the simple providers
  if provides.has_key?(id)
    provider = provides[id]
    return provider.is_a?(Proc) ? provider.call : provider
  end

  # try to get a provider object
  provider = get_provider(id)
  if provider
    @stack = (@stack || []) + [id]
    result = (opts[:scope] || self).instance_eval(&provider.block) 
    @stack.pop
    # execute provider object's block within the scope of self
    return result
  end

  # try to get a scoped provider object
  if scope.length > 0
    scoped_id = [scope, id].flatten
    provider = get_provider(scoped_id)
    if provider
      @stack = (@stack || []) + [scoped_id]
      result = (opts[:scope] || self).instance_eval(&provider.block) 
      @stack.pop
      # execute provider object's block within the scope of self
      return result
    end
  end

  # couldn't find requested provider, let's see if there's a fallback
  if provider = fallback_provider
    # temporarily set the @missing_provider instance variable, so the
    # fallback provider can use it through the missing_provider private method
    @missing_provider = id
    @stack = (@stack || []) + [id]
    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
    @stack.pop # = nil
    @missing_provider = nil
    return result
  end

  # no fallback either? Time for an error
  raise ProviderMissingException.new(:provider_id => id) 
end

#try_take(id, opts = {}) ⇒ Object



122
123
124
125
126
# File 'lib/data_provider/container.rb', line 122

def try_take(id, opts = {})
  return take(id, opts) if self.has_provider?(id) || self.fallback_provider?
  logger.debug "Try for missing provider: #{id.inspect}"
  return nil
end