class Sprockets::BundledAsset

concatenated with other assets. Use for ‘.js` and `.css` files.
`BundledAsset`s are used for files that need to be processed and

def self.serialized_attributes

Define extra attributes to be serialized.
def self.serialized_attributes
  super + %w( content_type mtime )
end

def blank_context

Return new blank `Context` to evaluate processors in.
def blank_context
  environment.context_class.new(environment, logical_path.to_s, pathname)
end

def body

original file.
dependencies but does run any processors or engines on the
Get asset's own processed contents. Excludes any of its required
def body
  @body ||= build_dependency_context_and_body[1]
end

def build_dependencies_paths_and_assets

def build_dependencies_paths_and_assets
  check_circular_dependency!
  paths, assets = {}, []
  # Define an `add_dependency` helper
  add_dependency = lambda do |asset|
    unless assets.any? { |a| a.pathname == asset.pathname }
      assets << asset
    end
  end
  # Iterate over all the declared require paths from the `Context`
  dependency_context._required_paths.each do |required_path|
    # Catch `require_self`
    if required_path == pathname.to_s
      add_dependency.call(self)
    else
      # Recursively lookup required asset
      environment[required_path, @options].to_a.each do |asset|
        add_dependency.call(asset)
      end
    end
  end
  # Ensure self is added to the dependency list
  add_dependency.call(self)
  dependency_context._dependency_paths.each do |path|
    paths[path] ||= {
      'path'      => path,
      'mtime'     => environment.stat(path).mtime,
      'hexdigest' => environment.file_digest(path).hexdigest
    }
  end
  dependency_context._dependency_assets.each do |path|
    # Skip if depending on self
    next if path == pathname.to_s
    # Recursively lookup required asset
    environment[path, @options].to_a.each do |asset|
      asset.dependency_paths.each do |dep|
        paths[dep['path']] ||= dep
      end
    end
  end
  @dependency_paths, @assets = paths.values, assets
  return @dependency_paths, @assets
end

def build_dependency_context_and_body

def build_dependency_context_and_body
  start_time = Time.now.to_f
  context = blank_context
  # Read original data once and pass it along to `Context`
  data = Sprockets::Utils.read_unicode(pathname)
  # Prime digest cache with data, since we happen to have it
  environment.file_digest(pathname, data)
  # Runs all processors on `Context`
  body = context.evaluate(pathname, :data => data)
  @dependency_context, @body = context, body
  elapsed_time = ((Time.now.to_f - start_time) * 1000).to_i
  logger.info "Compiled #{logical_path}  (#{elapsed_time}ms)  (pid #{Process.pid})"
  return context, body
end

def build_source

def build_source
  hash = environment.cache_hash("#{pathname}:source", id) do
    data = ""
    # Explode Asset into parts and gather the dependency bodies
    to_a.each { |dependency| data << dependency.body }
    # Run bundle processors on concatenated source
    data = blank_context.evaluate(pathname, :data => data,
      :processors => environment.bundle_processors(content_type))
    { 'length' => Rack::Utils.bytesize(data),
      'digest' => environment.digest.update(data).hexdigest,
      'source' => data }
  end
  hash['length'] = Integer(hash['length']) if hash['length'].is_a?(String)
  @length = hash['length']
  @digest = hash['digest']
  @source = hash['source']
  hash
end

def check_circular_dependency!

error. Otherwise you end up with a StackOverflow error.
Check if self has already been required and raise a fast
def check_circular_dependency!
  requires = @options[:_requires] ||= []
  if requires.include?(pathname.to_s)
    raise CircularDependencyError, "#{pathname} has already been required"
  end
  requires << pathname.to_s
end

def dependencies

Return an `Array` of `Asset` files that are declared dependencies.
def dependencies
  to_a - [self]
end

def dependency_context

trackes any dependencies that processors have added to it.
Get `Context` after processors have been ran on it. This
def dependency_context
  @dependency_context ||= build_dependency_context_and_body[0]
end

def dependency_paths

non-assets like directories.
All paths that this asset depends on. This list may include
def dependency_paths
  @dependency_paths ||= build_dependencies_paths_and_assets[0]
end

def digest

Compute digest of concatenated source.
def digest
  @digest ||= build_source['digest']
end

def encode_with(coder)

Serialize custom attributes in `BundledAsset`.
def encode_with(coder)
  super
  coder['body']        = body
  coder['asset_paths'] = to_a.map { |a| relativize_root_path(a.pathname) }
  coder['dependency_paths'] = dependency_paths.map { |h|
    h.merge('path' => relativize_root_path(h['path']))
  }
end

def fresh?

digest to the inmemory model.
Checks if Asset is stale by comparing the actual mtime and
def fresh?
  # Check freshness of all declared dependencies
  dependency_paths.all? { |h| dependency_fresh?(h) }
end

def init_with(environment, coder)

Initialize `BundledAsset` from serialized `Hash`.
def init_with(environment, coder)
  @options = {}
  super
  @body   = coder['body']
  @assets = coder['asset_paths'].map { |p|
    p = expand_root_path(p)
    p == pathname.to_s ? self : environment[p, @options]
  }
  @dependency_paths = coder['dependency_paths'].map { |h|
    h.merge('path' => expand_root_path(h['path']))
  }
  @dependency_paths.each do |dep|
    dep['mtime'] = Time.parse(dep['mtime']) if dep['mtime'].is_a?(String)
  end
end

def initialize(environment, logical_path, pathname, options)

def initialize(environment, logical_path, pathname, options)
  super(environment, logical_path, pathname)
  @options = options || {}
end

def length

Get size of concatenated source.
def length
  @length ||= build_source['length']
end

def logger

def logger
  environment.logger
end

def mtime

Get latest mtime of all its dependencies.
def mtime
  @mtime ||= dependency_paths.map { |h| h['mtime'] }.max
end

def to_a

Expand asset into an `Array` of parts.
def to_a
  @assets ||= build_dependencies_paths_and_assets[1]
end

def to_s

Return `String` of concatenated source.
def to_s
  @source ||= build_source['source']
end

def write_to(filename, options = {})

Save asset to disk.
def write_to(filename, options = {})
  # Gzip contents if filename has '.gz'
  options[:compress] ||= File.extname(filename) == '.gz'
  File.open("#{filename}+", 'wb') do |f|
    if options[:compress]
      # Run contents through `Zlib`
      gz = Zlib::GzipWriter.new(f, Zlib::BEST_COMPRESSION)
      gz.write to_s
      gz.close
    else
      # Write out as is
      f.write to_s
      f.close
    end
  end
  # Atomic write
  FileUtils.mv("#{filename}+", filename)
  # Set mtime correctly
  File.utime(mtime, mtime, filename)
  nil
ensure
  # Ensure tmp file gets cleaned up
  FileUtils.rm("#{filename}+") if File.exist?("#{filename}+")
end