Skip to content
This repository
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 100 lines (87 sloc) 2.923 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 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
require 'sprockets/base'

module Sprockets
  # `Index` is a special cached version of `Environment`.
  #
  # The expection is that all of its file system methods are cached
  # for the instances lifetime. This makes `Index` much faster. This
  # behavior is ideal in production environments where the file system
  # is immutable.
  #
  # `Index` should not be initialized directly. Instead use
  # `Environment#index`.
  class Index < Base
    def initialize(environment)
      @environment = environment

      if environment.respond_to?(:default_external_encoding)
        @default_external_encoding = environment.default_external_encoding
      end

      # Copy environment attributes
      @logger = environment.logger
      @context_class = environment.context_class
      @cache = environment.cache
      @trail = environment.trail.index
      @digest = environment.digest
      @digest_class = environment.digest_class
      @version = environment.version
      @mime_types = environment.mime_types
      @engines = environment.engines
      @preprocessors = environment.preprocessors
      @postprocessors = environment.postprocessors
      @bundle_processors = environment.bundle_processors

      # Initialize caches
      @assets = {}
      @digests = {}
    end

    # No-op return self as index
    def index
      self
    end

    # Cache calls to `file_digest`
    def file_digest(pathname)
      key = pathname.to_s
      if @digests.key?(key)
        @digests[key]
      else
        @digests[key] = super
      end
    end

    # Cache `find_asset` calls
    def find_asset(path, options = {})
      options[:bundle] = true unless options.key?(:bundle)
      if asset = @assets[cache_key_for(path, options)]
        asset
      elsif asset = super
        logical_path_cache_key = cache_key_for(path, options)
        full_path_cache_key = cache_key_for(asset.pathname, options)

        # Cache on Index
        @assets[logical_path_cache_key] = @assets[full_path_cache_key] = asset

        # Push cache upstream to Environment
        @environment.instance_eval do
          @assets[logical_path_cache_key] = @assets[full_path_cache_key] = asset
        end

        asset
      end
    end

    protected
      # Index is immutable, any methods that try to clear the cache
      # should bomb.
      def expire_index!
        raise TypeError, "can't modify immutable index"
      end

      # Cache asset building in memory and in persisted cache.
      def build_asset(path, pathname, options)
        # Memory cache
        key = cache_key_for(pathname, options)
        if @assets.key?(key)
          @assets[key]
        else
          @assets[key] = begin
            # Persisted cache
            cache_asset(key) do
              super
            end
          end
        end
      end
  end
end
Something went wrong with that request. Please try again.