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/railtie.rb
  5. lib/asset_hat/vcs.rb
  6. lib/asset_hat/version.rb
  7. lib/asset_hat.rb
  8. show all

Your assets are covered. 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.present? ? Rails.public_path : 'public'   Base directory in which all assets are kept, e.g., ‘public/’.
STYLESHEETS_PATH = '/stylesheets'   Root URL path for all stylesheets. For public-facing use.
JAVASCRIPTS_PATH = '/javascripts'   Root URL path for all JavaScripts. For public-facing use.
STYLESHEETS_DIR = File.join(ASSETS_DIR, 'stylesheets')   Directory in which all stylesheets are kept, e.g., ‘public/stylesheets’. For internal filesystem use.
JAVASCRIPTS_DIR = File.join(ASSETS_DIR, 'javascripts')   Directory in which all JavaScripts are kept, e.g., ‘public/javascripts’. For internal filesystem use.
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', :css)
  # => true if public/stylesheets/application.css exists
AssetHat.asset_exists?('some-plugin.js', :js)
  # => true if public/javascripts/some-plugin.js exists

See also AssetHat.assets_dir.

[show source]
     # File lib/asset_hat.rb, line 154
154:   def self.asset_exists?(filename, type)
155:     # Process arguments
156:     type = type.to_sym
157:     unless TYPES.include?(type)
158:       raise %{Unknown type "#{type}"; should be one of: #{TYPES.join(', ')}.}
159:       return
160:     end
161: 
162:     # Default to `{:css => {}, :js => {}}`
163:     @asset_exists ||= TYPES.inject({}) { |hsh, t| hsh.merge(t => {}) }
164: 
165:     if @asset_exists[type][filename].nil?
166:       @asset_exists[type][filename] =
167:         File.exist?(File.join(self.assets_dir(type), filename))
168:     end
169:     @asset_exists[type][filename]
170:   end
assets_dir (type)

Returns the relative path to the directory where the original CSS or JS files are stored. For internal filesystem use.

type argument: :css or :js

[show source]
    # File lib/asset_hat.rb, line 63
63:   def self.assets_dir(type)
64:     case type.to_sym
65:     when :css ; STYLESHEETS_DIR
66:     when :js  ; JAVASCRIPTS_DIR
67:     else
68:       raise %{Unknown type "#{type}"; should be one of: #{TYPES.join(', ')}.}
69:       nil
70:     end
71:   end
assets_path (type)

Returns the root URL path where the original CSS or JS files are stored. For external URL-building use.

type argument: :css or :js

[show source]
    # File lib/asset_hat.rb, line 77
77:   def self.assets_path(type)
78:     case type.to_sym
79:     when :css ; STYLESHEETS_PATH
80:     when :js  ; JAVASCRIPTS_PATH
81:     else
82:       raise %{Unknown type "#{type}"; should be one of: #{TYPES.join(', ')}.}
83:       nil
84:     end
85:   end
bundle_filenames (bundle, type)

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

AssetHat.bundle_filenames('application', :css)
  # => ['reset', 'application']
AssetHat.bundle_filenames('non-existent-file', :css)
  # => nil
[show source]
     # File lib/asset_hat.rb, line 210
210:   def self.bundle_filenames(bundle, type)
211:     # Process arguments
212:     unless TYPES.include?(type.to_sym)
213:       raise %{Unknown type "#{type}"; should be one of: #{TYPES.join(', ')}.}
214:       return
215:     end
216: 
217:     self.config[type.to_s]['bundles'][bundle.to_s] rescue nil
218:   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']
AssetHat.bundle_filenames('non-existent-file', :css)
  # => nil
[show source]
     # File lib/asset_hat.rb, line 227
227:   def self.bundle_filepaths(bundle, type)
228:     # Process arguments
229:     unless TYPES.include?(type.to_sym)
230:       raise %{Unknown type "#{type}"; should be one of: #{TYPES.join(', ')}.}
231:       return
232:     end
233: 
234:     dir = self.assets_dir(type)
235:     filenames = self.bundle_filenames(bundle, type)
236:     filepaths = filenames.present? ?
237:       filenames.map { |fn| File.join(dir, "#{fn}.#{type}") } : nil
238:   end
bundles_dir (*args)

Returns the relative path to the directory where CSS or JS bundles are stored. For internal filesystem use.

Usage:

AssetHat.bundles_dir
  # => 'bundles'
AssetHat.bundles_dir(:ssl => true)
  # => 'bundles/ssl'
AssetHat.bundles_dir(:css)
  # => 'public/stylesheets/bundles'
AssetHat.bundles_dir(:js, :ssl => true)
  # => 'public/javascripts/bundles/ssl

Options:

ssl
Set this to true if the stylesheet references images via SSL. Defaults to false.
[show source]
     # File lib/asset_hat.rb, line 105
105:   def self.bundles_dir(*args)
106:     options = args.extract_options!
107:     options.symbolize_keys!.reverse_merge!(:ssl => false)
108:     type = args.first
109: 
110:     dir = type.present? ? File.join(assets_dir(type), 'bundles') : 'bundles'
111:     dir = File.join(dir, 'ssl') if options[:ssl]
112:     dir
113:   end
bundles_path (type, options={})

Returns the root URL path where CSS or JS bundles are stored. For external URL-building use.

Usage:

AssetHat.bundles_path(:css)
  # => 'public/stylesheets/bundles'
AssetHat.bundles_path(:js, :ssl => true)
  # => 'public/javascripts/bundles/ssl

Options:

ssl
Set this to true if the stylesheet references images via SSL. Defaults to false.
[show source]
     # File lib/asset_hat.rb, line 129
129:   def self.bundles_path(type, options={})
130:     type = type.to_sym
131:     unless TYPES.include?(type)
132:       raise %{Unknown type "#{type}"; should be one of: #{TYPES.join(', ')}.}
133:       return
134:     end
135: 
136:     path =  case type
137:             when :css ; STYLESHEETS_PATH
138:             when :js  ; JAVASCRIPTS_PATH
139:             else nil
140:             end
141:     path += '/bundles'
142:     path += '/ssl' if options[:ssl]
143:     path
144:   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 (boolean) in your environment.

[show source]
     # File lib/asset_hat.rb, line 178
178:   def self.cache? ; ActionController::Base.perform_caching ; end
cache_last_commit_ids ()

Precomputes and caches the last commit ID for all bundles. Your web server process(es) should run this at boot to avoid overhead during user runtime.

[show source]
    # File lib/asset_hat/vcs.rb, line 75
75:   def self.cache_last_commit_ids
76:     AssetHat::TYPES.each do |type|
77:       next if AssetHat.config[type.to_s].blank? ||
78:               AssetHat.config[type.to_s]['bundles'].blank?
79: 
80:       AssetHat.config[type.to_s]['bundles'].keys.each do |bundle|
81:         # Memoize commit ID for this bundle
82:         AssetHat.last_bundle_commit_id(bundle, type) if AssetHat.cache?
83: 
84:         # Memoize commit IDs for each file in this bundle
85:         AssetHat.bundle_filepaths(bundle, type).each do |filepath|
86:           AssetHat.last_commit_id(filepath)
87:         end
88:       end
89:     end
90:   end
clear_html_cache ()
[show source]
     # File lib/asset_hat.rb, line 294
294:   def self.clear_html_cache
295:     html_cache = {}
296:   end
compute_asset_host (asset_host, source, options={})

Reads ActionController::Base.asset_host, which can be a String or Proc, and returns a String. Should behave just like Rails 2.3.x’s private `compute_asset_host` method, but with a simulated request.

Example environment config for CDN support via SSL:

# In config/environments/production.rb:
config.action_controller.asset_host = Proc.new do |source, request|
  "#{request.protocol}cdn#{source.hash % 4}.example.com"
    # => 'http://cdn0.example.com', 'https://cdn1.example.com', etc.
end

If your CDN doesn’t have SSL support, you can instead revert SSL pages to serving assets from your web server:

config.action_controller.asset_host = Proc.new do |source, request|
  request.ssl? ? nil : "http://cdn#{source.hash % 4}.example.com"
end

Options:

ssl
Set to true to simulate a request via SSL. Defaults to false.
[show source]
     # File lib/asset_hat.rb, line 263
263:   def self.compute_asset_host(asset_host, source, options={})
264:     host = asset_host
265:     if host.is_a?(Proc) || host.respond_to?(:call)
266:       case host.is_a?(Proc) ?
267:            host.arity : host.method(:call).arity
268:       when 2
269:         if defined?(ActionDispatch)
270:           request_class = ActionDispatch::Request
271:         else # Rails 2.x
272:           request_class = ActionController::Request
273:         end
274:         request = request_class.new(
275:           'HTTPS' => options[:ssl] ? 'on' : 'off')
276:         host = host.call(source, request)
277:       else
278:         host = host.call(source)
279:       end
280:     else
281:       host %= (source.hash % 4) if host =~ /%d/
282:     end
283:     host
284:   end
config ()

Nested-hash version of config/assets.yml.

[show source]
    # File lib/asset_hat.rb, line 47
47:   def self.config
48:     unless File.exists?(CONFIG_FILEPATH)
49:       raise '`config/assets.yml` is missing! ' +
50:             'Run `rake asset_hat:config` to generate it.' and return
51:     end
52: 
53:     if !cache? || @config.blank?
54:       @config = YAML.load(ERB.new(File.read(CONFIG_FILEPATH)).result)
55:     end
56:     @config
57:   end
consider_all_requests_local? ()

Returns the value of Rails.application.config.consider_all_requests_local or its equivalent in older versions of Rails. To modify this value, set config.consider_all_requests_local (boolean) in your environment.

[show source]
     # File lib/asset_hat.rb, line 185
185:   def self.consider_all_requests_local?
186:     if defined?(Rails) && Rails.respond_to?(:application)
187:       Rails.application.config.consider_all_requests_local
188:     else # Rails 2.x
189:       ActionController::Base.consider_all_requests_local
190:     end
191:   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] =
62:           self.last_commit_id(*filepaths)
63:       end
64:     end
65: 
66:     @last_bundle_commit_ids[type][bundle]
67:   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 200
200:   def self.min_filepath(filepath, extension)
201:     filepath.sub(/([^\.]*).#{extension}$/, "\\1.min.#{extension}")
202:   end
ssl_asset_host_differs? ()

Returns true if the asset host differs between SSL and non-SSL pages, or false if the asset host doesn’t change.

[show source]
     # File lib/asset_hat.rb, line 288
288:   def self.ssl_asset_host_differs?
289:     asset_host = ActionController::Base.asset_host
290:     AssetHat.compute_asset_host(asset_host, 'x.png') !=
291:       AssetHat.compute_asset_host(asset_host, 'x.png', :ssl => true)
292:   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