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 timestamp into the asset URL path instead of using the
26
- Rails scheme of appending a URL parameter. Some asset servers (notably Amazon CloudFront) will
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. Like Rails,
196
- dynamic_assets adds a URL parameter to the asset path that will change
197
- if any of the underlying assets is modified, forcing clients to reload
198
- the asset. With action caching and/or an external cache like Varnish or
199
- a CDN, dynamic assets are quite speedy because you generate them rarely.
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
- def stylesheet_asset_tag(group_key, http_attributes = {})
5
- DynamicAssets::Manager.asset_references_for_group_key(:stylesheets, group_key).map do |asset_ref|
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
- tag :link, {
8
- :type => "text/css",
9
- :rel => "stylesheet",
10
- :media => "screen",
11
- :href => asset_url(asset_ref)
12
- }.merge!(http_attributes)
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
- end.join.html_safe
15
- end
14
+ end.join.html_safe
15
+ end
16
16
 
17
- def javascript_asset_tag(group_key, http_attributes = {})
18
- DynamicAssets::Manager.asset_references_for_group_key(:javascripts, group_key).map do |asset_ref|
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
- content_tag :script, "", {
21
- :type => "text/javascript",
22
- :src => asset_url(asset_ref)
23
- }.merge!(http_attributes)
20
+ content_tag :script, "", {
21
+ :type => "text/javascript",
22
+ :src => asset_url(asset_ref)
23
+ }.merge!(http_attributes)
24
24
 
25
- end.join.html_safe
26
- end
25
+ end.join.html_safe
26
+ end
27
27
 
28
28
 
29
- protected
29
+ protected
30
30
 
31
- def asset_path(asset_ref)
32
- path_args = []
33
- path_args << asset_ref.name
34
- path_args << { :timestamp => asset_ref.mtime.to_i.to_s } if asset_ref.mtime.present?
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
- 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}"
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
- def asset_url(asset_ref)
44
- path = asset_path asset_ref
45
- path = "/" + path unless path[0,1] == "/"
43
+ def asset_url(asset_ref)
44
+ path = asset_path asset_ref
45
+ path = "/" + path unless path[0,1] == "/"
46
46
 
47
- host = compute_asset_host path
48
- host ? "#{host}#{path}" : path
49
- end
47
+ host = compute_asset_host path
48
+ host ? "#{host}#{path}" : path
49
+ end
50
50
 
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)
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
- (host =~ /%d/) ? host % (source.hash % 4) : host
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(/:timestamp)/:name.:format' => 'assets#show_javascript',
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 => /[^ ]+/, # By default, route segments can't have dots. We allow all but space.
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(/:timestamp)/:name.:format' => 'assets#show_stylesheet',
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 mtime
61
- paths.map { |p| File.mtime p }.max
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", :mtime => 123) },
26
- DynamicAssets::StylesheetReference.new.tap { |r| r.stub(:name => "b", :mtime => 456) },
27
- DynamicAssets::StylesheetReference.new.tap { |r| r.stub(:name => "c", :mtime => 789) }
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 mtime" do
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", :mtime => 123) },
110
- DynamicAssets::JavascriptReference.new.tap { |r| r.stub(:name => "b", :mtime => 456) },
111
- DynamicAssets::JavascriptReference.new.tap { |r| r.stub(:name => "c", :mtime => 789) }
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 mtime" do
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: 13
4
+ hash: 11
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 4
9
- - 1
10
- version: 0.4.1
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-04-27 00:00:00 -05:00
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: 111
77
+ hash: -1848230051
78
78
  segments:
79
- - 0
80
- - 4
81
79
  - 1
82
- - 2
83
- version: 0.4.1.2
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: 27
94
+ hash: 977940571
95
95
  segments:
96
96
  - 2
97
- - 5
97
+ - 6
98
98
  - 0
99
- version: 2.5.0
99
+ - rc6
100
+ version: 2.6.0.rc6
100
101
  requirement: *id005
101
102
  - !ruby/object:Gem::Dependency
102
103
  prerelease: false