class Sprockets::Base - sprockets-2.11.3 Documentation

# class Sprockets::Base

`Base` class for `Environment` and `Index`.

### Attributes

cache[R]

Get persistent cache store

context_class[R]

Get `Context` class.

This class maybe mutated and mixed in with custom helpers.

    environment.context_class.instance_eval do
      include MyHelpers
      def asset_url; end
    end

digest_class[R]

Returns a `Digest` implementation class.

Defaults to `Digest::MD5`.

logger[RW]

Get and set `Logger` instance.

version[R]

The `Environment#version` is a custom value used for manually expiring all asset caches.

Sprockets is able to track most file and directory changes and will take care of expiring the cache for you. However, its impossible to know when any custom helpers change that you mix into the `Context`.

It would be wise to increment this value anytime you make a configuration change to the `Environment` object.

### Public Instance Methods

[](*args) click to toggle source

Preferred `find_asset` shorthand.

    environment['application.js']

    # File lib/sprockets/base.rb, line 294
    def [](*args)
      find_asset(*args)
    end

append_path(path) click to toggle source
Calls superclass method Sprockets::Paths#append_path

    # File lib/sprockets/base.rb, line 107
    def append_path(path)
      # Overrides the global behavior to expire the index
      expire_index!
      super
    end

attributes_for(path) click to toggle source

Internal. Return a `AssetAttributes` for `path`.

    # File lib/sprockets/base.rb, line 252
    def attributes_for(path)
      AssetAttributes.new(self, path)
    end

cache=(cache) click to toggle source

Set persistent cache store

The cache store must implement a pair of getters and setters. Either `get(key)`/`set(key, value)`, `[key]`/`=value`, `read(key)`/`write(key, value)`.

    # File lib/sprockets/base.rb, line 96
    def cache=(cache)
      expire_index!
      @cache = cache
    end

clear_paths() click to toggle source
Calls superclass method Sprockets::Paths#clear_paths

    # File lib/sprockets/base.rb, line 113
    def clear_paths
      # Overrides the global behavior to expire the index
      expire_index!
      super
    end

content_type_of(path) click to toggle source

Internal. Return content type of `path`.

    # File lib/sprockets/base.rb, line 257
    def content_type_of(path)
      attributes_for(path).content_type
    end

digest() click to toggle source

Returns a `Digest` instance for the `Environment`.

This value serves two purposes. If two `Environment`s have the same digest value they can be treated as equal. This is more useful for comparing environment states between processes rather than in the same. Two equal `Environment`s can share the same cached assets.

The value also provides a seed digest for all `Asset` digests. Any change in the environment digest will affect all of its assets.

    # File lib/sprockets/base.rb, line 64
    def digest
      # Compute the initial digest using the implementation class. The
      # Sprockets release version and custom environment version are
      # mixed in. So any new releases will affect all your assets.
      @digest ||= digest_class.new.update(VERSION).update(version.to_s)

      # Returned a dupped copy so the caller can safely mutate it with `.update`
      @digest.dup
    end

digest_class=(klass) click to toggle source

Assign a `Digest` implementation class. This maybe any Ruby `Digest::` implementation such as `Digest::MD5` or `Digest::SHA1`.

    environment.digest_class = Digest::SHA1

    # File lib/sprockets/base.rb, line 27
    def digest_class=(klass)
      expire_index!
      @digest_class = klass
    end

each_entry(root, &block) click to toggle source

    # File lib/sprockets/base.rb, line 298
    def each_entry(root, &block)
      return to_enum(__method__, root) unless block_given?
      root = Pathname.new(root) unless root.is_a?(Pathname)

      paths = []
      entries(root).sort.each do |filename|
        path = root.join(filename)
        paths << path

        if stat(path).directory?
          each_entry(path) do |subpath|
            paths << subpath
          end
        end
      end

      paths.sort_by(&:to_s).each(&block)

      nil
    end

each_file() { |path| ... } click to toggle source

    # File lib/sprockets/base.rb, line 319
    def each_file
      return to_enum(__method__) unless block_given?
      paths.each do |root|
        each_entry(root) do |path|
          if !stat(path).directory?
            yield path
          end
        end
      end
      nil
    end

each_logical_path(*args) { |logical_path, filename| ... } click to toggle source

    # File lib/sprockets/base.rb, line 331
    def each_logical_path(*args, &block)
      return to_enum(__method__, *args) unless block_given?
      filters = args.flatten
      files = {}
      each_file do |filename|
        if logical_path = logical_path_for_filename(filename, filters)
          unless files[logical_path]
            if block.arity == 2
              yield logical_path, filename.to_s
            else
              yield logical_path
            end
          end

          files[logical_path] = true
        end
      end
      nil
    end

entries(pathname) click to toggle source

Works like `Dir.entries`.

Subclasses may cache this method.

    # File lib/sprockets/base.rb, line 223
    def entries(pathname)
      @trail.entries(pathname)
    end

file_digest(path) click to toggle source

Read and compute digest of filename.

Subclasses may cache this method.

    # File lib/sprockets/base.rb, line 237
    def file_digest(path)
      if stat = self.stat(path)
        # If its a file, digest the contents
        if stat.file?
          digest.file(path.to_s)

        # If its a directive, digest the list of filenames
        elsif stat.directory?
          contents = self.entries(path).join(',')
          digest.update(contents)
        end
      end
    end

find_asset(path, options = {}) click to toggle source

Find asset by logical path or expanded path.

    # File lib/sprockets/base.rb, line 262
    def find_asset(path, options = {})
      logical_path = path
      pathname     = Pathname.new(path)

      if pathname.absolute?
        return unless stat(pathname)
        logical_path = attributes_for(pathname).logical_path
      else
        begin
          pathname = resolve(logical_path)

          # If logical path is missing a mime type extension, append
          # the absolute path extname so it has one.
          #
          # Ensures some consistency between finding "foo/bar" vs
          # "foo/bar.js".
          if File.extname(logical_path) == ""
            expanded_logical_path = attributes_for(pathname).logical_path
            logical_path += File.extname(expanded_logical_path)
          end
        rescue FileNotFound
          return nil
        end
      end

      build_asset(logical_path, pathname, options)
    end

index() click to toggle source

Return an `Index`. Must be implemented by the subclass.

    # File lib/sprockets/base.rb, line 210
    def index
      raise NotImplementedError
    end

inspect() click to toggle source

Pretty inspect

    # File lib/sprockets/base.rb, line 352
    def inspect
      "#<#{self.class}:0x#{object_id.to_s(16)} " +
        "root=#{root.to_s.inspect}, " +
        "paths=#{paths.inspect}, " +
        "digest=#{digest.to_s.inspect}" +
        ">"
    end

prepend_path(path) click to toggle source
Calls superclass method Sprockets::Paths#prepend_path

    # File lib/sprockets/base.rb, line 101
    def prepend_path(path)
      # Overrides the global behavior to expire the index
      expire_index!
      super
    end

register_bundle_processor(mime_type, klass, &block) click to toggle source
Calls superclass method Sprockets::Processing#register_bundle_processor

    # File lib/sprockets/base.rb, line 197
    def register_bundle_processor(mime_type, klass, &block)
      # Overrides the global behavior to expire the index
      expire_index!
      super
    end

register_engine(ext, klass) click to toggle source

Registers a new Engine `klass` for `ext`.

Calls superclass method Sprockets::Engines#register_engine

    # File lib/sprockets/base.rb, line 166
    def register_engine(ext, klass)
      # Overrides the global behavior to expire the index
      expire_index!
      add_engine_to_trail(ext, klass)
      super
    end

register_mime_type(mime_type, ext) click to toggle source

Register a new mime type.

Calls superclass method Sprockets::Mime#register_mime_type

    # File lib/sprockets/base.rb, line 158
    def register_mime_type(mime_type, ext)
      # Overrides the global behavior to expire the index
      expire_index!
      @trail.append_extension(ext)
      super
    end

register_postprocessor(mime_type, klass, &block) click to toggle source
Calls superclass method Sprockets::Processing#register_postprocessor

    # File lib/sprockets/base.rb, line 185
    def register_postprocessor(mime_type, klass, &block)
      # Overrides the global behavior to expire the index
      expire_index!
      super
    end

register_preprocessor(mime_type, klass, &block) click to toggle source
Calls superclass method Sprockets::Processing#register_preprocessor

    # File lib/sprockets/base.rb, line 173
    def register_preprocessor(mime_type, klass, &block)
      # Overrides the global behavior to expire the index
      expire_index!
      super
    end

resolve(logical_path, options = {}) { |dirname.join(bower)| ... } click to toggle source

Finds the expanded real path for a given logical path by searching the environment's paths.

    resolve("application.js")
    # => "/path/to/app/javascripts/application.js.coffee"

A `FileNotFound` exception is raised if the file does not exist.

    # File lib/sprockets/base.rb, line 126
    def resolve(logical_path, options = {})
      # If a block is given, preform an iterable search
      if block_given?
        args = attributes_for(logical_path).search_paths + [options]
        @trail.find(*args) do |path|
          pathname = Pathname.new(path)
          if %w( .bower.json bower.json component.json ).include?(pathname.basename.to_s)
            bower = json_decode(pathname.read)
            case bower['main']
            when String
              yield pathname.dirname.join(bower['main'])
            when Array
              extname = File.extname(logical_path)
              bower['main'].each do |fn|
                if extname == "" || extname == File.extname(fn)
                  yield pathname.dirname.join(fn)
                end
              end
            end
          else
            yield pathname
          end
        end
      else
        resolve(logical_path, options) do |pathname|
          return pathname
        end
        raise FileNotFound, "couldn't find file '#{logical_path}'"
      end
    end

stat(path) click to toggle source

Works like `File.stat`.

Subclasses may cache this method.

    # File lib/sprockets/base.rb, line 230
    def stat(path)
      @trail.stat(path)
    end

unregister_bundle_processor(mime_type, klass) click to toggle source
Calls superclass method Sprockets::Processing#unregister_bundle_processor

    # File lib/sprockets/base.rb, line 203
    def unregister_bundle_processor(mime_type, klass)
      # Overrides the global behavior to expire the index
      expire_index!
      super
    end

unregister_postprocessor(mime_type, klass) click to toggle source
Calls superclass method Sprockets::Processing#unregister_postprocessor

    # File lib/sprockets/base.rb, line 191
    def unregister_postprocessor(mime_type, klass)
      # Overrides the global behavior to expire the index
      expire_index!
      super
    end

unregister_preprocessor(mime_type, klass) click to toggle source
Calls superclass method Sprockets::Processing#unregister_preprocessor

    # File lib/sprockets/base.rb, line 179
    def unregister_preprocessor(mime_type, klass)
      # Overrides the global behavior to expire the index
      expire_index!
      super
    end

version=(version) click to toggle source

Assign an environment version.

    environment.version = '2.0'

    # File lib/sprockets/base.rb, line 48
    def version=(version)
      expire_index!
      @version = version
    end

### Protected Instance Methods

build_asset(logical_path, pathname, options) click to toggle source

    # File lib/sprockets/base.rb, line 366
    def build_asset(logical_path, pathname, options)
      pathname = Pathname.new(pathname)

      # If there are any processors to run on the pathname, use
      # `BundledAsset`. Otherwise use `StaticAsset` and treat is as binary.
      if attributes_for(pathname).processors.any?
        if options[:bundle] == false
          circular_call_protection(pathname.to_s) do
            ProcessedAsset.new(index, logical_path, pathname)
          end
        else
          BundledAsset.new(index, logical_path, pathname)
        end
      else
        StaticAsset.new(index, logical_path, pathname)
      end
    end

cache_key_for(path, options) click to toggle source

    # File lib/sprockets/base.rb, line 384
    def cache_key_for(path, options)
      "#{path}:#{options[:bundle] ? '1' : '0'}"
    end

circular_call_protection(path) { || ... } click to toggle source

    # File lib/sprockets/base.rb, line 388
    def circular_call_protection(path)
      reset = Thread.current[:sprockets_circular_calls].nil?
      calls = Thread.current[:sprockets_circular_calls] ||= Set.new
      if calls.include?(path)
        raise CircularDependencyError, "#{path} has already been required"
      end
      calls << path
      yield
    ensure
      Thread.current[:sprockets_circular_calls] = nil if reset
    end

expire_index!() click to toggle source

Clear index after mutating state. Must be implemented by the subclass.

    # File lib/sprockets/base.rb, line 362
    def expire_index!
      raise NotImplementedError
    end

json_decode(obj) click to toggle source

    # File lib/sprockets/base.rb, line 438
    def json_decode(obj)
      MultiJson.load(obj)
    end

logical_path_for_filename(filename, filters) click to toggle source

    # File lib/sprockets/base.rb, line 400
    def logical_path_for_filename(filename, filters)
      logical_path = attributes_for(filename).logical_path.to_s

      if matches_filter(filters, logical_path, filename)
        return logical_path
      end

      # If filename is an index file, retest with alias
      if File.basename(logical_path)[/[^\.]+/, 0] == 'index'
        path = logical_path.sub(/\/index\./, '.')
        if matches_filter(filters, path, filename)
          return path
        end
      end

      nil
    end

matches_filter(filters, logical_path, filename) click to toggle source

    # File lib/sprockets/base.rb, line 418
    def matches_filter(filters, logical_path, filename)
      return true if filters.empty?

      filters.any? do |filter|
        if filter.is_a?(Regexp)
          filter.match(logical_path)
        elsif filter.respond_to?(:call)
          if filter.arity == 1
            filter.call(logical_path)
          else
            filter.call(logical_path, filename.to_s)
          end
        else
          File.fnmatch(filter.to_s, logical_path)
        end
      end
    end