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 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