Skip to content

Commit

Permalink
Added wildcards. Improved caching considerably for Rack::Cache and Ra…
Browse files Browse the repository at this point in the history
…ck::ConditionalGet by including etags. Performance improvements.
  • Loading branch information
pbhogan committed Apr 1, 2010
1 parent 33931cd commit 140cd0e
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 13 deletions.
18 changes: 12 additions & 6 deletions lib/sinatra/bundles.rb
Expand Up @@ -11,7 +11,7 @@ module Bundles
# @param [Symbol,String] key The bundle name
# @param [Array(String)] files The list of filenames, without extension,
# assumed to be in the public directory, under 'javascripts'
def javascript_bundle(key, files)
def javascript_bundle(key, files = nil)
javascript_bundles[key] = JavascriptBundle.new(self, files)
end

Expand All @@ -20,7 +20,7 @@ def javascript_bundle(key, files)
# @param [Symbol,String] key The bundle name
# @param [Array(String)] files The list of filenames, without extension,
# assumed to be in the public directory, under 'stylesheets'
def stylesheet_bundle(key, files)
def stylesheet_bundle(key, files = nil)
stylesheet_bundles[key] = StylesheetBundle.new(self, files)
end

Expand All @@ -46,15 +46,21 @@ def self.registered(app)
app.get('/stylesheets/bundles/:bundle.css') do |bundle|
content_type('text/css')
headers['Vary'] = 'Accept-Encoding'
expires(options.bundle_cache_time, :public, :must_revalidate) if options.cache_bundles
options.stylesheet_bundles[bundle.intern]
if options.cache_bundles
expires(options.bundle_cache_time, :public, :must_revalidate)
etag options.stylesheet_bundles[bundle.intern].etag
end
options.stylesheet_bundles[bundle.intern].content
end

app.get('/javascripts/bundles/:bundle.js') do |bundle|
content_type('text/javascript; charset=utf-8')
headers['Vary'] = 'Accept-Encoding'
expires(options.bundle_cache_time, :public, :must_revalidate) if options.cache_bundles
options.javascript_bundles[bundle.intern]
if options.cache_bundles
expires(options.bundle_cache_time, :public, :must_revalidate)
etag options.javascript_bundles[bundle.intern].etag
end
options.javascript_bundles[bundle.intern].content
end
end
end
Expand Down
37 changes: 34 additions & 3 deletions lib/sinatra/bundles/bundle.rb
Expand Up @@ -4,9 +4,29 @@ module Bundles
# The developer user sinatra-bundles should
# never have to deal with this directly
class Bundle
def initialize(app, files)
include Enumerable

def initialize(app, files = nil)
@app = app
@files = files
@files = Array.new
files ||= ["**"]
files.each do |f|
full_path = path(f)
if File.file? full_path
@files << f
else
dir = File.dirname(full_path)
ext = File.extname(full_path)
pattern = File.join(dir, f, "**", "*#{ext}")
Dir.glob(pattern) do |file|
file.chomp!(ext).slice!(0..dir.length)
@files << file
end
end
end
@files.uniq!
etag
# puts @files.inspect
end

# Since we pass Bundles back as the body,
Expand All @@ -21,8 +41,19 @@ def each
end
end

private
# Returns the bundled content.
# Cached in a local variable to prevent rebundling on future requests.
def content
@content ||= self.to_a.join('')
end

# Returns an etag for the bundled content.
# Cached in a local variable to prevent recomputing on future requests.
def etag
@etag ||= Digest::MD5.hexdigest(content)
end

private
# The timestamp of the bundle, which is the newest file in the bundle.
#
# @return [Integer] The timestamp of the bundle
Expand Down
4 changes: 2 additions & 2 deletions lib/sinatra/bundles/helpers.rb
Expand Up @@ -14,8 +14,8 @@ def javascript_bundle_include_tag(bundle)
#
# @param [Symbol,String] bundle The bundle name
# @return [String] HTML link tag
def stylesheet_bundle_link_tag(bundle)
options.stylesheet_bundles[bundle].to_html(bundle)
def stylesheet_bundle_link_tag(bundle, media = nil)
options.stylesheet_bundles[bundle].to_html(bundle, media)
end
end
end
Expand Down
6 changes: 4 additions & 2 deletions lib/sinatra/bundles/stylesheet_bundle.rb
Expand Up @@ -9,8 +9,10 @@ class StylesheetBundle < Bundle
#
# @param [String] name The name of a bundle
# @return [String] The HTML that can be inserted into the doc
def to_html(name)
"<link type='text/css' href='/stylesheets/bundles/#{name}.css#{@app.stamp_bundles ? "?#{stamp}" : ''}' rel='stylesheet' media='screen' />"
def to_html(name, media = nil)
media ||= :all
media = media.join(", ") if media.is_a? Array
"<link type='text/css' href='/stylesheets/bundles/#{name}.css#{@app.stamp_bundles ? "?#{stamp}" : ''}' rel='stylesheet' media='#{media}' />"
end

protected
Expand Down

0 comments on commit 140cd0e

Please sign in to comment.