dynamic_assets 0.4.1 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc
CHANGED
@@ -22,9 +22,10 @@ Out of the box it can (optionally):
|
|
22
22
|
penalty of downloading your admin styles.)
|
23
23
|
* Allow CSS assets to refer to static images through relative URLs. That is, it doesn't break URLs
|
24
24
|
embedded in CSS.
|
25
|
-
* Invalidate caches and CDNs by inserting a
|
26
|
-
Rails scheme of appending a URL
|
27
|
-
drop parameters from the URL, so cache-busting requires path-changing
|
25
|
+
* Invalidate caches and CDNs by inserting a SHA1 signature into the asset URL path instead of using the
|
26
|
+
Rails scheme of appending a URL timestamp. Some asset servers (notably Amazon CloudFront) will
|
27
|
+
drop parameters from the URL, so cache-busting requires path-changing, and since assets are often
|
28
|
+
moved from machine to machine, modification times can be unreliable.
|
28
29
|
* Honor Rails' scheme for asset hosts.
|
29
30
|
|
30
31
|
It seems that Rails 3.1 will offer many of these features off-the-shelf, which is
|
@@ -192,11 +193,11 @@ If no :media attribute is supplied, stylesheet_asset_tag will use "screen".
|
|
192
193
|
|
193
194
|
== Performance
|
194
195
|
|
195
|
-
In production, assets can typically be cached aggressively.
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
196
|
+
In production, assets can typically be cached aggressively. dynamic_assets
|
197
|
+
adds a signature to the asset path, and since it's based on the last-modified
|
198
|
+
time of the underlying assets, clients will be forced to reload to reload
|
199
|
+
assets when they change. With caching, dynamic assets are quite speedy
|
200
|
+
because you generate them rarely.
|
200
201
|
|
201
202
|
But during development they can be annoying <em>if</em> you set your
|
202
203
|
environment to maximum slowness. The sweet spot for my dev configuration
|
@@ -1,67 +1,67 @@
|
|
1
1
|
|
2
2
|
module DynamicAssetsHelpers
|
3
3
|
|
4
|
-
|
5
|
-
|
4
|
+
def stylesheet_asset_tag(group_key, http_attributes = {})
|
5
|
+
DynamicAssets::Manager.asset_references_for_group_key(:stylesheets, group_key).map do |asset_ref|
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
7
|
+
tag :link, {
|
8
|
+
:type => "text/css",
|
9
|
+
:rel => "stylesheet",
|
10
|
+
:media => "screen",
|
11
|
+
:href => asset_url(asset_ref)
|
12
|
+
}.merge!(http_attributes)
|
13
13
|
|
14
|
-
|
15
|
-
|
14
|
+
end.join.html_safe
|
15
|
+
end
|
16
16
|
|
17
|
-
|
18
|
-
|
17
|
+
def javascript_asset_tag(group_key, http_attributes = {})
|
18
|
+
DynamicAssets::Manager.asset_references_for_group_key(:javascripts, group_key).map do |asset_ref|
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
20
|
+
content_tag :script, "", {
|
21
|
+
:type => "text/javascript",
|
22
|
+
:src => asset_url(asset_ref)
|
23
|
+
}.merge!(http_attributes)
|
24
24
|
|
25
|
-
|
26
|
-
|
25
|
+
end.join.html_safe
|
26
|
+
end
|
27
27
|
|
28
28
|
|
29
|
-
|
29
|
+
protected
|
30
30
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
31
|
+
def asset_path(asset_ref)
|
32
|
+
path_args = []
|
33
|
+
path_args << asset_ref.name
|
34
|
+
path_args << { :signature => asset_ref.signature } if asset_ref.signature.present?
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
end
|
36
|
+
case asset_ref
|
37
|
+
when DynamicAssets::StylesheetReference then stylesheet_asset_path *path_args
|
38
|
+
when DynamicAssets::JavascriptReference then javascript_asset_path *path_args
|
39
|
+
else raise "Unknown asset type: #{asset_ref}"
|
41
40
|
end
|
41
|
+
end
|
42
42
|
|
43
|
-
|
44
|
-
|
45
|
-
|
43
|
+
def asset_url(asset_ref)
|
44
|
+
path = asset_path asset_ref
|
45
|
+
path = "/" + path unless path[0,1] == "/"
|
46
46
|
|
47
|
-
|
48
|
-
|
49
|
-
|
47
|
+
host = compute_asset_host path
|
48
|
+
host ? "#{host}#{path}" : path
|
49
|
+
end
|
50
50
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
else
|
60
|
-
host.call(source)
|
61
|
-
end
|
51
|
+
# Extracted from Rails' AssetTagHelper, where it's private
|
52
|
+
def compute_asset_host(source)
|
53
|
+
if host = config.asset_host
|
54
|
+
if host.is_a?(Proc) || host.respond_to?(:call)
|
55
|
+
case host.is_a?(Proc) ? host.arity : host.method(:call).arity
|
56
|
+
when 2
|
57
|
+
request = controller.respond_to?(:request) && controller.request
|
58
|
+
host.call(source, request)
|
62
59
|
else
|
63
|
-
|
60
|
+
host.call(source)
|
64
61
|
end
|
62
|
+
else
|
63
|
+
(host =~ /%d/) ? host % (source.hash % 4) : host
|
65
64
|
end
|
66
65
|
end
|
66
|
+
end
|
67
67
|
end
|
data/config/routes.rb
CHANGED
@@ -1,20 +1,18 @@
|
|
1
1
|
|
2
2
|
Rails.application.routes.draw do
|
3
3
|
|
4
|
-
match '/assets/javascripts(/:
|
4
|
+
match '/assets/javascripts(/v/:signature)/:name.:format' => 'assets#show_javascript',
|
5
5
|
:as => :javascript_asset,
|
6
6
|
:format => "js", # Important for action-caching non-HTML resources
|
7
7
|
:constraints => {
|
8
|
-
:name => /[^ ]
|
9
|
-
:timestamp => /\d+/
|
8
|
+
:name => /[^ ]+/ # By default, route segments can't have dots. We allow all but space.
|
10
9
|
}
|
11
10
|
|
12
|
-
match '/assets/stylesheets(/:
|
11
|
+
match '/assets/stylesheets(/v/:signature)/:name.:format' => 'assets#show_stylesheet',
|
13
12
|
:as => :stylesheet_asset,
|
14
13
|
:format => "css", # Important for action-caching non-HTML resources
|
15
14
|
:constraints => { # By default, segments can't have dots. We allow all but space.
|
16
|
-
:name => /[^ ]
|
17
|
-
:timestamp => /\d+/
|
15
|
+
:name => /[^ ]+/
|
18
16
|
}
|
19
17
|
|
20
18
|
end
|
@@ -57,8 +57,13 @@ module DynamicAssets
|
|
57
57
|
s
|
58
58
|
end
|
59
59
|
|
60
|
-
def
|
61
|
-
|
60
|
+
def signature
|
61
|
+
# Note that the signature is based on the context-free
|
62
|
+
# content. The context must depend on external factors
|
63
|
+
# in the route, like the domain name, since the signature
|
64
|
+
# will not change when the context changes.
|
65
|
+
|
66
|
+
Digest::SHA1.hexdigest content
|
62
67
|
end
|
63
68
|
|
64
69
|
def minify(content_string)
|
@@ -105,7 +110,7 @@ module DynamicAssets
|
|
105
110
|
def read_member(member_name)
|
106
111
|
path = path_for_member_name member_name
|
107
112
|
content_string = get_raw_content path
|
108
|
-
content_string = ERB.new(content_string).result(@context) if path_is_erb?(path)
|
113
|
+
content_string = ERB.new(content_string).result(@context) if @context && path_is_erb?(path)
|
109
114
|
content_string
|
110
115
|
end
|
111
116
|
|
@@ -42,10 +42,6 @@ module DynamicAssets
|
|
42
42
|
else raise "unknown format #{format}"
|
43
43
|
end
|
44
44
|
|
45
|
-
# PENDING: we could do something similar to insert the asset host,
|
46
|
-
# although we'd need to pass some context (namely the request) down
|
47
|
-
# from the controller to compute the asset host in the same way Rails
|
48
|
-
# does.
|
49
45
|
transform_urls member_name, content_string
|
50
46
|
end
|
51
47
|
|
@@ -22,9 +22,9 @@ describe DynamicAssetsHelpers do
|
|
22
22
|
before do
|
23
23
|
DynamicAssets::Manager.stub(:asset_references_for_group_key).with(:stylesheets, group_key).
|
24
24
|
and_return [
|
25
|
-
DynamicAssets::StylesheetReference.new.tap { |r| r.stub(:name => "a", :
|
26
|
-
DynamicAssets::StylesheetReference.new.tap { |r| r.stub(:name => "b", :
|
27
|
-
DynamicAssets::StylesheetReference.new.tap { |r| r.stub(:name => "c", :
|
25
|
+
DynamicAssets::StylesheetReference.new.tap { |r| r.stub(:name => "a", :signature => 123) },
|
26
|
+
DynamicAssets::StylesheetReference.new.tap { |r| r.stub(:name => "b", :signature => 456) },
|
27
|
+
DynamicAssets::StylesheetReference.new.tap { |r| r.stub(:name => "c", :signature => 789) }
|
28
28
|
]
|
29
29
|
end
|
30
30
|
|
@@ -56,10 +56,10 @@ describe DynamicAssetsHelpers do
|
|
56
56
|
context "when config.asset_host is nil" do
|
57
57
|
before { helper.config.asset_host.should be_nil }
|
58
58
|
|
59
|
-
it "is three tags with hrefs derived from the asset name and
|
60
|
-
should contain_string 'href="/assets/stylesheets/123/a.css"'
|
61
|
-
should contain_string 'href="/assets/stylesheets/456/b.css"'
|
62
|
-
should contain_string 'href="/assets/stylesheets/789/c.css"'
|
59
|
+
it "is three tags with hrefs derived from the asset name and signature" do
|
60
|
+
should contain_string 'href="/assets/stylesheets/v/123/a.css"'
|
61
|
+
should contain_string 'href="/assets/stylesheets/v/456/b.css"'
|
62
|
+
should contain_string 'href="/assets/stylesheets/v/789/c.css"'
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
@@ -67,9 +67,9 @@ describe DynamicAssetsHelpers do
|
|
67
67
|
before { helper.config.stub(:asset_host).and_return "http://a.example.com" }
|
68
68
|
|
69
69
|
it "is three tags with hrefs whose host is a.example.com" do
|
70
|
-
should contain_string 'href="http://a.example.com/assets/stylesheets/123/a.css"'
|
71
|
-
should contain_string 'href="http://a.example.com/assets/stylesheets/456/b.css"'
|
72
|
-
should contain_string 'href="http://a.example.com/assets/stylesheets/789/c.css"'
|
70
|
+
should contain_string 'href="http://a.example.com/assets/stylesheets/v/123/a.css"'
|
71
|
+
should contain_string 'href="http://a.example.com/assets/stylesheets/v/456/b.css"'
|
72
|
+
should contain_string 'href="http://a.example.com/assets/stylesheets/v/789/c.css"'
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
@@ -77,9 +77,9 @@ describe DynamicAssetsHelpers do
|
|
77
77
|
before { helper.config.stub(:asset_host).and_return "http://a%d.example.com" }
|
78
78
|
|
79
79
|
it "is three tags with hrefs whose host is a[0-3].example.com" do
|
80
|
-
should =~ /href="http:\/\/a[0-3].example.com\/assets\/stylesheets\/123\/a.css"/
|
81
|
-
should =~ /href="http:\/\/a[0-3].example.com\/assets\/stylesheets\/456\/b.css"/
|
82
|
-
should =~ /href="http:\/\/a[0-3].example.com\/assets\/stylesheets\/789\/c.css"/
|
80
|
+
should =~ /href="http:\/\/a[0-3].example.com\/assets\/stylesheets\/v\/123\/a.css"/
|
81
|
+
should =~ /href="http:\/\/a[0-3].example.com\/assets\/stylesheets\/v\/456\/b.css"/
|
82
|
+
should =~ /href="http:\/\/a[0-3].example.com\/assets\/stylesheets\/v\/789\/c.css"/
|
83
83
|
end
|
84
84
|
end
|
85
85
|
end
|
@@ -106,9 +106,9 @@ describe DynamicAssetsHelpers do
|
|
106
106
|
before do
|
107
107
|
DynamicAssets::Manager.stub(:asset_references_for_group_key).with(:javascripts, group_key).
|
108
108
|
and_return [
|
109
|
-
DynamicAssets::JavascriptReference.new.tap { |r| r.stub(:name => "a", :
|
110
|
-
DynamicAssets::JavascriptReference.new.tap { |r| r.stub(:name => "b", :
|
111
|
-
DynamicAssets::JavascriptReference.new.tap { |r| r.stub(:name => "c", :
|
109
|
+
DynamicAssets::JavascriptReference.new.tap { |r| r.stub(:name => "a", :signature => 123) },
|
110
|
+
DynamicAssets::JavascriptReference.new.tap { |r| r.stub(:name => "b", :signature => 456) },
|
111
|
+
DynamicAssets::JavascriptReference.new.tap { |r| r.stub(:name => "c", :signature => 789) }
|
112
112
|
]
|
113
113
|
end
|
114
114
|
|
@@ -131,10 +131,10 @@ describe DynamicAssetsHelpers do
|
|
131
131
|
context "when config.asset_host is nil" do
|
132
132
|
before { helper.config.asset_host.should be_nil }
|
133
133
|
|
134
|
-
it "is three tags with srcs derived from the asset name and
|
135
|
-
should contain_string 'src="/assets/javascripts/123/a.js"'
|
136
|
-
should contain_string 'src="/assets/javascripts/456/b.js"'
|
137
|
-
should contain_string 'src="/assets/javascripts/789/c.js"'
|
134
|
+
it "is three tags with srcs derived from the asset name and signature" do
|
135
|
+
should contain_string 'src="/assets/javascripts/v/123/a.js"'
|
136
|
+
should contain_string 'src="/assets/javascripts/v/456/b.js"'
|
137
|
+
should contain_string 'src="/assets/javascripts/v/789/c.js"'
|
138
138
|
end
|
139
139
|
end
|
140
140
|
|
@@ -142,9 +142,9 @@ describe DynamicAssetsHelpers do
|
|
142
142
|
before { helper.config.stub(:asset_host).and_return "http://a.example.com" }
|
143
143
|
|
144
144
|
it "is three tags with srcs whose host is a.example.com" do
|
145
|
-
should contain_string 'src="http://a.example.com/assets/javascripts/123/a.js"'
|
146
|
-
should contain_string 'src="http://a.example.com/assets/javascripts/456/b.js"'
|
147
|
-
should contain_string 'src="http://a.example.com/assets/javascripts/789/c.js"'
|
145
|
+
should contain_string 'src="http://a.example.com/assets/javascripts/v/123/a.js"'
|
146
|
+
should contain_string 'src="http://a.example.com/assets/javascripts/v/456/b.js"'
|
147
|
+
should contain_string 'src="http://a.example.com/assets/javascripts/v/789/c.js"'
|
148
148
|
end
|
149
149
|
end
|
150
150
|
|
@@ -152,9 +152,9 @@ describe DynamicAssetsHelpers do
|
|
152
152
|
before { helper.config.stub(:asset_host).and_return "http://a%d.example.com" }
|
153
153
|
|
154
154
|
it "is three tags with srcs whose host is a[0-3].example.com" do
|
155
|
-
should =~ /src="http:\/\/a[0-3].example.com\/assets\/javascripts\/123\/a.js"/
|
156
|
-
should =~ /src="http:\/\/a[0-3].example.com\/assets\/javascripts\/456\/b.js"/
|
157
|
-
should =~ /src="http:\/\/a[0-3].example.com\/assets\/javascripts\/789\/c.js"/
|
155
|
+
should =~ /src="http:\/\/a[0-3].example.com\/assets\/javascripts\/v\/123\/a.js"/
|
156
|
+
should =~ /src="http:\/\/a[0-3].example.com\/assets\/javascripts\/v\/456\/b.js"/
|
157
|
+
should =~ /src="http:\/\/a[0-3].example.com\/assets\/javascripts\/v\/789\/c.js"/
|
158
158
|
end
|
159
159
|
end
|
160
160
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dynamic_assets
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 11
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 5
|
9
|
+
- 0
|
10
|
+
version: 0.5.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Robert Davis
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-05-11 00:00:00 -05:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -72,15 +72,15 @@ dependencies:
|
|
72
72
|
version_requirements: &id004 !ruby/object:Gem::Requirement
|
73
73
|
none: false
|
74
74
|
requirements:
|
75
|
-
- -
|
75
|
+
- - "="
|
76
76
|
- !ruby/object:Gem::Version
|
77
|
-
hash:
|
77
|
+
hash: -1848230051
|
78
78
|
segments:
|
79
|
-
- 0
|
80
|
-
- 4
|
81
79
|
- 1
|
82
|
-
-
|
83
|
-
|
80
|
+
- 0
|
81
|
+
- 0
|
82
|
+
- beta1
|
83
|
+
version: 1.0.0.beta1
|
84
84
|
requirement: *id004
|
85
85
|
- !ruby/object:Gem::Dependency
|
86
86
|
prerelease: false
|
@@ -89,14 +89,15 @@ dependencies:
|
|
89
89
|
version_requirements: &id005 !ruby/object:Gem::Requirement
|
90
90
|
none: false
|
91
91
|
requirements:
|
92
|
-
- -
|
92
|
+
- - "="
|
93
93
|
- !ruby/object:Gem::Version
|
94
|
-
hash:
|
94
|
+
hash: 977940571
|
95
95
|
segments:
|
96
96
|
- 2
|
97
|
-
-
|
97
|
+
- 6
|
98
98
|
- 0
|
99
|
-
|
99
|
+
- rc6
|
100
|
+
version: 2.6.0.rc6
|
100
101
|
requirement: *id005
|
101
102
|
- !ruby/object:Gem::Dependency
|
102
103
|
prerelease: false
|