dynamic_assets 0.4.1 → 0.5.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/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
|