lib/data_provider/container.rb in data-provider-0.2.1 vs lib/data_provider/container.rb in data-provider-0.2.2

- old
+ new

@@ -73,32 +73,36 @@ def take(id, opts = {}) logger.debug "DataProvider::Container#take with id: #{id.inspect}" # first try the simple providers - if provides.has_key?(id) + if provides.has_key?(id) && opts[:skip].nil? provider = provides[id] return provider.is_a?(Proc) ? provider.call : provider end # try to get a provider object - provider = get_provider(id) + provider = get_provider(id, :skip => opts[:skip]) if provider - @stack = (@stack || []) + [id] + @stack = (@stack || []) + [provider] + @skip_stack = (@skip_stack || []) + [opts[:skip].to_i] result = (opts[:scope] || self).instance_eval(&provider.block) + @skip_stack.pop @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) + provider = get_provider(scoped_id, :skip => opts[:skip]) if provider - @stack = (@stack || []) + [scoped_id] + @stack = (@stack || []) + [provider] + @skip_stack = (@skip_stack || []) + [opts[:skip].to_i] result = (opts[:scope] || self).instance_eval(&provider.block) + @skip_stack.pop @stack.pop # execute provider object's block within the scope of self return result end end @@ -106,12 +110,14 @@ # 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] + @stack = (@stack || []) + [provider] + @skip_stack = (@skip_stack || []) + [opts[:skip].to_i] 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 + @skip_stack.pop @stack.pop # = nil @missing_provider = nil return result end @@ -123,10 +129,16 @@ return take(id, opts) if self.has_provider?(id) || self.fallback_provider? logger.debug "Try for missing provider: #{id.inspect}" return nil end + # take_super is only meant to be called form inside a provider + # returns the result of next provider with the same ID + def take_super(opts = {}) + take(provider_id, opts.merge(:skip => current_skip + 1)) + end + # # "adding existing containers"-related methods # # adds all the providers defined in the given module to this class @@ -237,22 +249,30 @@ def provider_stack (@stack || []).clone end - def provider_id + def current_provider provider_stack.last end + def provider_id + current_provider ? current_provider.id : nil + end + def scopes - provider_stack.map{|provider_id| provider_id.is_a?(Array) ? provider_id[0..-2] : []} + provider_stack.map{|provider| provider.id.is_a?(Array) ? provider.id[0..-2] : []} end def scope scopes.last || [] end + def current_skip + (@skip_stack || []).last.to_i + end + private def add_provider(identifier, opts = {}, block = nil) @providers ||= [] @providers.unshift [identifier, opts, block] @@ -267,11 +287,17 @@ @provides ||= {} @provides.merge! _provides end # returns the requested provider as a Provider object - def get_provider(id) - args = providers.find{|args| args.first == id} + def get_provider(id, opts = {}) + if opts[:skip] + matches = providers.find_all{|args| args.first == id} + args = matches[opts[:skip].to_i] + else + args = providers.find{|args| args.first == id} + end + return args.nil? ? nil : Provider.new(*args) end end # class Container end # module DataProvider \ No newline at end of file