require 'forwardable' module Roadie # An asset provider that just composes a list of other asset providers. # # Give it a list of providers and they will all be tried in order. # # {ProviderList} behaves like an Array, *and* an asset provider, and can be coerced into an array. class ProviderList extend Forwardable include Enumerable # Wrap a single provider, or a list of providers into a {ProviderList}. # # @overload wrap(provider_list) # @param [ProviderList] provider_list An actual instance of {ProviderList}. # @return The passed in provider_list # # @overload wrap(provider) # @param [asset provider] provider # @return a new {ProviderList} with just the passed provider in it # # @overload wrap(provider1, provider2, ...) # @return a new {ProviderList} with all the passed providers in it. def self.wrap(*providers) if providers.size == 1 && providers.first.class == self providers.first else new(providers.flatten) end end # Returns a new empty list. def self.empty() new([]) end def initialize(providers) @providers = providers end # @return [Stylesheet, nil] def find_stylesheet(name) @providers.each do |provider| css = provider.find_stylesheet(name) return css if css end nil end # Tries to find the given stylesheet and raises an {ProvidersFailed} error # if no provider could find the asset. # # @return [Stylesheet] def find_stylesheet!(name) errors = [] @providers.each do |provider| begin return provider.find_stylesheet!(name) rescue CssNotFound => error errors << error end end raise ProvidersFailed.new(name, self, errors) end def to_s list = @providers.map { |provider| # Indent every line one level provider.to_s.split("\n").join("\n\t") } "ProviderList: [\n\t#{list.join(",\n\t")}\n]" end # ProviderList can be coerced to an array. This makes Array#flatten work # with it, among other things. def to_ary() to_a end # @!method each # @see Array#each # @!method size # @see Array#size # @!method empty? # @see Array#empty? # @!method push # @see Array#push # @!method << # @see Array#<< # @!method pop # @see Array#pop # @!method unshift # @see Array#unshift # @!method shift # @see Array#shift # @!method last # @see Array#last def_delegators :@providers, :each, :size, :empty?, :push, :<<, :pop, :unshift, :shift, :last end end