Module AssetHat

  1. lib/asset_hat/css.rb
  2. lib/asset_hat/js/vendors.rb
  3. lib/asset_hat/js.rb
  4. lib/asset_hat/vcs.rb
  5. lib/asset_hat/version.rb
  6. lib/asset_hat.rb
  7. show all

Your assets are covered.

With Rails’ default asset caching, CSS and JS are concatenated (not even minified) at runtime when that bundle is first requested. Not good enough. AssetHat can automatically:

  • Easily minify and bundle CSS and JS on deploy to reduce file sizes and HTTP requests.
  • Load popular third-party JS (like jQuery and Prototype) from Google's CDN when in production, or from localhost in development.
  • Force image URLs in your CSS to use CDN subdomains, not just the current host.
  • Add an image’s last Git commit ID to its CSS URLs to bust browser caches (e.g., /images/foo.png?ab12cd34e).

After setup, you can use these in your layouts and views:

<%= include_css :bundle => 'application' %>
  # => <link href="/stylesheets/bundles/application.min.css"
  #          media="screen,projection" rel="stylesheet" type="text/css" />

<%= include_js :bundles => ['plugins', 'common'] %>
  # => <script src="/javascripts/bundles/plugins.min.js"
  #            type="text/javascript"></script>
  #    <script src="/javascripts/bundles/common.min.js"
  #            type="text/javascript"></script>

And this in your deploy script:

rake asset_hat:minify

See README.rdoc for more.

Classes and Modules

Module AssetHat::CSS
Module AssetHat::JS

Constants

VERSION = self.version   This gem’s version number.
TYPES = [:css, :js]   Types of supported assets; currently [:css, :js].
ASSETS_DIR = defined?(Rails.public_path) ? Rails.public_path : 'public'   Base directory in which all assets are kept, e.g., ‘public/’.
STYLESHEETS_DIR = "#{ASSETS_DIR}/stylesheets"   Directory in which all stylesheets are kept, e.g., ‘public/stylesheets/’.
JAVASCRIPTS_DIR = "#{ASSETS_DIR}/javascripts"   Directory in which all JavaScripts are kept, e.g., ‘public/javascripts/’.
RELATIVE_CONFIG_FILEPATH = File.join('config', 'assets.yml')   Relative path for the config file.
CONFIG_FILEPATH = File.join(RAILS_ROOT, RELATIVE_CONFIG_FILEPATH)   Absolute path for the config file.

Public class methods

asset_exists? (filename, type)

Returns true if the specified asset exists in the file system:

AssetHat.asset_exists?('application', :css)
  # => true if /public/stylesheets/application.css exists
AssetHat.asset_exists?('some-plugin', :js)
  # => true if /public/javascripts/some-plugin.js exists

See also AssetHat::STYLESHEETS_DIR and AssetHat::JAVASCRIPTS_DIR.

[show source]
     # File lib/asset_hat.rb, line 92
 92:   def self.asset_exists?(filename, type)
 93:     # Process arguments
 94:     type = type.to_sym
 95:     unless TYPES.include?(type)
 96:       raise "Unknown type \"#{type}\"; should be one of: #{TYPES.join(', ')}."
 97:       return
 98:     end
 99: 
100:     @asset_exists ||= TYPES.inject({}) do |hsh, known_type|
101:       hsh.merge!(known_type => {})
102:     end
103:     if @asset_exists[type][filename].nil?
104:       @asset_exists[type][filename] =
105:         File.exist?(File.join(self.assets_dir(type), filename))
106:     end
107:     @asset_exists[type][filename]
108:   end
assets_dir (type)

Argument: :css or :js

Returns the path to the directory where CSS or JS files are stored.

[show source]
    # File lib/asset_hat.rb, line 75
75:   def self.assets_dir(type)
76:     case type.to_sym
77:     when :css ; STYLESHEETS_DIR
78:     when :js  ; JAVASCRIPTS_DIR
79:     else nil
80:     end
81:   end
bundle_filenames (bundle, type)

Returns the extension-less names of files in the given bundle:

AssetHat.bundle_filenames('application', :css)
  # => ['reset', 'application', 'clearfix']
AssetHat.bundle_filenames('non-existent-file', :css)
  # => nil
[show source]
     # File lib/asset_hat.rb, line 134
134:   def self.bundle_filenames(bundle, type)
135:     # Process arguments
136:     unless TYPES.include?(type.to_sym)
137:       raise "Unknown type \"#{type}\"; should be one of: #{TYPES.join(', ')}."
138:       return
139:     end
140: 
141:     self.config[type.to_s]['bundles'][bundle] rescue nil
142:   end
bundle_filepaths (bundle, type)

Returns the full paths of files in the given bundle:

AssetHat.bundle_filenames('application', :css)
  # => ['/path/to/app/public/stylesheets/reset.css',
        '/path/to/app/public/stylesheets/application.css',
        '/path/to/app/public/stylesheets/clearfix.css']
AssetHat.bundle_filenames('non-existent-file', :css)
  # => nil
[show source]
     # File lib/asset_hat.rb, line 152
152:   def self.bundle_filepaths(bundle, type)
153:     # Process arguments
154:     unless TYPES.include?(type.to_sym)
155:       raise "Unknown type \"#{type}\"; should be one of: #{TYPES.join(', ')}."
156:       return
157:     end
158: 
159:     dir = self.assets_dir(type)
160:     filenames = self.bundle_filenames(bundle, type)
161:     filepaths = filenames.present? ?
162:       filenames.map { |fn| File.join(dir, "#{fn}.#{type}") } : nil
163:   end
cache? ()

Returns true if bundles should be included as single minified files (e.g., in production), or false if bundles should be included as separate, unminified files (e.g., in development). To modify this value, set config.action_controller.perform_caching = true in your environment.

[show source]
     # File lib/asset_hat.rb, line 115
115:   def self.cache? ; ActionController::Base.perform_caching ; end
clear_html_cache ()
[show source]
     # File lib/asset_hat.rb, line 165
165:   def self.clear_html_cache
166:     html_cache = {}
167:   end
config ()

Nested-hash version of config/assets.yml.

[show source]
    # File lib/asset_hat.rb, line 65
65:   def self.config
66:     if !cache? || @config.blank?
67:       @config = YAML.load(File.open(CONFIG_FILEPATH, 'r'))
68:     end
69:     @config
70:   end
last_bundle_commit_id (bundle, type)

Usage:

AssetHat.last_bundle_commit_id('application', :css)

Returns a string of the latest commit ID for the given bundle, based on which of its files were most recently modified in the repository. If no ID can be found, `nil` is returned.

[show source]
    # File lib/asset_hat/vcs.rb, line 45
45:   def self.last_bundle_commit_id(bundle, type)
46:     # Process arguments
47:     type = type.to_sym
48:     unless TYPES.include?(type)
49:       raise "Unknown type \"#{type}\"; should be one of: #{TYPES.join(', ')}."
50:       return
51:     end
52: 
53:     # Default to `{:css => {}, :js => {}}`
54:     @last_bundle_commit_ids ||=
55:       TYPES.inject({}) { |hsh, t| hsh.merge(t => {}) }
56: 
57:     if @last_bundle_commit_ids[type][bundle].blank?
58:       dir = self.assets_dir(type)
59:       filepaths = self.bundle_filepaths(bundle, type)
60:       if filepaths.present?
61:         @last_bundle_commit_ids[type][bundle] = self.last_commit_id(*filepaths)
62:       end
63:     end
64: 
65:     @last_bundle_commit_ids[type][bundle]
66:   end
last_commit_id (*args)

Usage:

AssetHat.last_commit_id('public/stylesheets/application.css')
AssetHat.last_commit_id('public/stylesheets/ie.css',
                        'public/stylesheets/ie7.css',
                        'public/stylesheets/ie6.css')

Returns a string of the commit ID for the file with the most recent commit. If the file(s) cannot be found, `nil` is returned. Options:

vcs
Version control system. Currently, the only supported value is :git.
[show source]
    # File lib/asset_hat/vcs.rb, line 18
18:   def self.last_commit_id(*args)
19:     # Process arguments
20:     options = args.extract_options!
21:     options = options.symbolize_keys.reverse_merge(:vcs => :git)
22:     filepaths = args.join(' ')
23: 
24:     # Validate options
25:     if options[:vcs] != :git
26:       raise 'Git is currently the only supported VCS.' and return
27:     end
28: 
29:     @last_commit_ids ||= {}
30:     if @last_commit_ids[filepaths].blank?
31:       h = `git log -1 --pretty=format:%h #{filepaths} 2>/dev/null`
32:         # `h` has either the abbreviated Git commit hash or an empty string
33:       @last_commit_ids[filepaths] = h if h.present?
34:     end
35:     @last_commit_ids[filepaths]
36:   end
min_filepath (filepath, extension)

Returns the expected path for the minified version of an asset:

AssetHat.min_filepath('public/stylesheets/bundles/application.css', 'css')
  # => 'public/stylesheets/bundles/application.min.css'

See also AssetHat::CSS.min_filepath and AssetHat::JS.min_filepath.

[show source]
     # File lib/asset_hat.rb, line 124
124:   def self.min_filepath(filepath, extension)
125:     filepath.sub(/([^\.]*).#{extension}$/, "\\1.min.#{extension}")
126:   end
version ()

Returns this gem’s version number. See also VERSION.

[show source]
   # File lib/asset_hat/version.rb, line 3
3:   def self.version
4:     data_filepath = File.join(File.dirname(__FILE__), %w[.. .. VERSION.yml])
5:     data = YAML.load(File.open(data_filepath, 'r'))
6:     [:major, :minor, :patch, :build].
7:       map { |x| data[x] }.reject(&:blank?).join('.')
8:   end