asset_timestamps_cache 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +1 -0
- data/README.md +53 -0
- data/Rakefile +22 -0
- data/VERSION +1 -0
- data/lib/asset_timestamps_cache.rb +35 -0
- data/test/test_asset_timestamps_cache.rb +49 -0
- metadata +60 -0
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
public/*
|
data/README.md
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
AssetTimestampsCache
|
2
|
+
====================
|
3
|
+
|
4
|
+
A simple asset timestamping solution. Adapted from asset timestamping functionality in ActionPack.
|
5
|
+
|
6
|
+
Allows you to set far-future expires headers on images, stylesheets, javascripts, flash etc. and
|
7
|
+
bust the browser's cache only when the file has changed.
|
8
|
+
|
9
|
+
For more on far-future expires headers, see [http://developer.yahoo.com/performance/rules.html#expires](http://developer.yahoo.com/performance/rules.html#expires)
|
10
|
+
|
11
|
+
|
12
|
+
View Helper
|
13
|
+
===========
|
14
|
+
|
15
|
+
AssetTimestampsCache::ViewHelper contains an timestamped_asset_path method,
|
16
|
+
which appends a timestamp of the file's last modified time to the asset path.
|
17
|
+
|
18
|
+
So,
|
19
|
+
|
20
|
+
<%= timestamped_asset_path "images/logo.png" %>
|
21
|
+
|
22
|
+
will output:
|
23
|
+
|
24
|
+
"images/logo.png?1267564623"
|
25
|
+
|
26
|
+
This timestamp value is cached, so that subsequent calls don't need to hit the filesystem.
|
27
|
+
|
28
|
+
Sinatra setup example:
|
29
|
+
|
30
|
+
class MyApp < Sinatra::Base
|
31
|
+
helper AssetTimestampsCache::ViewHelper
|
32
|
+
|
33
|
+
# etc...
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
Direct Cache Access
|
38
|
+
===================
|
39
|
+
|
40
|
+
# Will look for "public/images/log.png" and get last modified time.
|
41
|
+
# Subsequent lookups will read from internal hash cache instead of filesystem
|
42
|
+
AssetTimestampsCache["images/logo.png"] # => "1267564623"
|
43
|
+
|
44
|
+
# Change asset directory from default of "public"
|
45
|
+
AssetTimestampsCache.asset_dir = 'assets'
|
46
|
+
|
47
|
+
# Clear cache
|
48
|
+
AssetTimestampsCache.clear
|
49
|
+
|
50
|
+
|
51
|
+
Caveat: NOT THREADSAFE. This shouldn't be a problem if you're deploying to Passenger.
|
52
|
+
One could always add a Mutex around cache writes (as ActionPack does) if thread safety
|
53
|
+
is an issue.
|
data/Rakefile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rake/testtask'
|
2
|
+
|
3
|
+
Rake::TestTask.new do |t|
|
4
|
+
t.libs << "test"
|
5
|
+
t.test_files = FileList['test/test*.rb']
|
6
|
+
t.verbose = true
|
7
|
+
end
|
8
|
+
task :default => :test
|
9
|
+
|
10
|
+
begin
|
11
|
+
require 'jeweler'
|
12
|
+
Jeweler::Tasks.new do |gemspec|
|
13
|
+
gemspec.name = "asset_timestamps_cache"
|
14
|
+
gemspec.summary = "A simple asset timestamping solution."
|
15
|
+
gemspec.description = "Adapted from asset timestamping functionality in ActionPack."
|
16
|
+
gemspec.email = "gbuesing@gmail.com"
|
17
|
+
gemspec.homepage = "http://github.com/gbuesing/asset_timestamps_cache"
|
18
|
+
gemspec.authors = ["Geoff Buesing"]
|
19
|
+
end
|
20
|
+
rescue LoadError
|
21
|
+
puts "Jeweler not available. Install it with: gem install jeweler"
|
22
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module AssetTimestampsCache
|
2
|
+
|
3
|
+
@@asset_timestamps_cache = {}
|
4
|
+
@@asset_dir = 'public'
|
5
|
+
|
6
|
+
def self.asset_dir
|
7
|
+
@@asset_dir
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.asset_dir=(val)
|
11
|
+
@@asset_dir = val
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.[](asset_path)
|
15
|
+
if timestamp = @@asset_timestamps_cache[asset_path]
|
16
|
+
timestamp
|
17
|
+
else
|
18
|
+
file_path = File.join(*[@@asset_dir, asset_path].compact)
|
19
|
+
timestamp = File.exist?(file_path) ? File.mtime(file_path).to_i.to_s : ''
|
20
|
+
@@asset_timestamps_cache[asset_path] = timestamp
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.clear
|
25
|
+
@@asset_timestamps_cache.clear
|
26
|
+
end
|
27
|
+
|
28
|
+
module ViewHelper
|
29
|
+
def timestamped_asset_path(asset_path)
|
30
|
+
timestamp = AssetTimestampsCache[asset_path]
|
31
|
+
"#{asset_path}?#{timestamp}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'asset_timestamps_cache'
|
2
|
+
require 'test/unit'
|
3
|
+
require 'fileutils'
|
4
|
+
require 'rubygems'
|
5
|
+
require 'mocha'
|
6
|
+
|
7
|
+
class TestAssetTimestampsCache < Test::Unit::TestCase
|
8
|
+
def setup
|
9
|
+
AssetTimestampsCache.clear
|
10
|
+
FileUtils.mkdir_p 'public'
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_returns_mtime_for_file
|
14
|
+
FileUtils.touch 'public/fixture.txt'
|
15
|
+
mtime = File.mtime('public/fixture.txt').to_i.to_s
|
16
|
+
assert_equal mtime, AssetTimestampsCache['fixture.txt']
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_returns_blank_string_for_nonexistent_file
|
20
|
+
assert_equal '', AssetTimestampsCache['nonexistent.txt']
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_only_calls_file_mtime_once_on_repeated_access
|
24
|
+
File.expects(:mtime).once.returns '12345'
|
25
|
+
5.times do
|
26
|
+
assert_equal '12345', AssetTimestampsCache['fixture.txt']
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class TestAssetTimestampsCacheViewHelper < Test::Unit::TestCase
|
32
|
+
class Foo; include(AssetTimestampsCache::ViewHelper); end
|
33
|
+
|
34
|
+
def setup
|
35
|
+
AssetTimestampsCache.clear
|
36
|
+
FileUtils.mkdir_p 'public'
|
37
|
+
@scope = Foo.new
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_timestamped_asset_path
|
41
|
+
FileUtils.touch 'public/fixture.txt'
|
42
|
+
mtime = File.mtime('public/fixture.txt').to_i.to_s
|
43
|
+
assert_equal "fixture.txt?#{mtime}", @scope.timestamped_asset_path('fixture.txt')
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_timestamped_asset_path_for_nonexistent_asset
|
47
|
+
assert_equal "nonexistent.txt?", @scope.timestamped_asset_path('nonexistent.txt')
|
48
|
+
end
|
49
|
+
end
|
metadata
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: asset_timestamps_cache
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Geoff Buesing
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-03-02 00:00:00 -06:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Adapted from asset timestamping functionality in ActionPack.
|
17
|
+
email: gbuesing@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README.md
|
24
|
+
files:
|
25
|
+
- .gitignore
|
26
|
+
- README.md
|
27
|
+
- Rakefile
|
28
|
+
- VERSION
|
29
|
+
- lib/asset_timestamps_cache.rb
|
30
|
+
- test/test_asset_timestamps_cache.rb
|
31
|
+
has_rdoc: true
|
32
|
+
homepage: http://github.com/gbuesing/asset_timestamps_cache
|
33
|
+
licenses: []
|
34
|
+
|
35
|
+
post_install_message:
|
36
|
+
rdoc_options:
|
37
|
+
- --charset=UTF-8
|
38
|
+
require_paths:
|
39
|
+
- lib
|
40
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: "0"
|
45
|
+
version:
|
46
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: "0"
|
51
|
+
version:
|
52
|
+
requirements: []
|
53
|
+
|
54
|
+
rubyforge_project:
|
55
|
+
rubygems_version: 1.3.5
|
56
|
+
signing_key:
|
57
|
+
specification_version: 3
|
58
|
+
summary: A simple asset timestamping solution.
|
59
|
+
test_files:
|
60
|
+
- test/test_asset_timestamps_cache.rb
|