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 176
def [](*args)
  find_asset(*args)
end
attributes_for(path) click to toggle source

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

# File lib/sprockets/base.rb, line 144
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
content_type_of(path) click to toggle source

Internal. Return content type of `path`.

# File lib/sprockets/base.rb, line 149
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 180
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 201
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| ... } click to toggle source
# File lib/sprockets/base.rb, line 213
def each_logical_path(*args)
  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)
      yield logical_path unless files[logical_path]
      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 115
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 129
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 154
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)
    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 102
def index
  raise NotImplementedError
end
inspect() click to toggle source

Pretty inspect

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

Works like `File.stat`.

Subclasses may cache this method.

# File lib/sprockets/base.rb, line 122
def stat(path)
  trail.stat(path)
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 241
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 259
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 263
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 237
def expire_index!
  raise NotImplementedError
end
logical_path_for_filename(filename, filters) click to toggle source
# File lib/sprockets/base.rb, line 275
def logical_path_for_filename(filename, filters)
  logical_path = attributes_for(filename).logical_path.to_s

  if matches_filter(filters, logical_path)
    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)
      return path
    end
  end

  nil
end
matches_filter(filters, filename) click to toggle source
# File lib/sprockets/base.rb, line 293
def matches_filter(filters, filename)
  return true if filters.empty?

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