actionpack 3.1.0.rc4 → 3.1.0.rc5
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of actionpack might be problematic. Click here for more details.
- data/CHANGELOG +6 -0
- data/lib/abstract_controller/asset_paths.rb +1 -1
- data/lib/abstract_controller/layouts.rb +10 -8
- data/lib/action_controller/base.rb +13 -11
- data/lib/action_controller/caching/sweeping.rb +1 -0
- data/lib/action_controller/metal/redirecting.rb +1 -0
- data/lib/action_controller/metal/request_forgery_protection.rb +10 -9
- data/lib/action_controller/metal/responder.rb +5 -0
- data/lib/action_controller/metal/streaming.rb +6 -14
- data/lib/action_controller/railtie.rb +0 -1
- data/lib/action_controller/test_case.rb +19 -0
- data/lib/action_dispatch/http/upload.rb +11 -1
- data/lib/action_dispatch/middleware/cookies.rb +5 -0
- data/lib/action_dispatch/routing/mapper.rb +10 -9
- data/lib/action_dispatch/routing/polymorphic_routes.rb +4 -9
- data/lib/action_dispatch/testing/test_request.rb +1 -1
- data/lib/action_pack/version.rb +1 -1
- data/lib/action_view.rb +1 -0
- data/lib/action_view/asset_paths.rb +148 -0
- data/lib/action_view/base.rb +1 -1
- data/lib/action_view/helpers/asset_paths.rb +2 -78
- data/lib/action_view/helpers/asset_tag_helper.rb +8 -2
- data/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb +11 -12
- data/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb +2 -2
- data/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb +4 -3
- data/lib/action_view/helpers/cache_helper.rb +4 -6
- data/lib/action_view/helpers/controller_helper.rb +2 -0
- data/lib/action_view/helpers/date_helper.rb +47 -47
- data/lib/action_view/helpers/form_helper.rb +45 -11
- data/lib/action_view/helpers/form_tag_helper.rb +1 -1
- data/lib/action_view/helpers/number_helper.rb +3 -1
- data/lib/action_view/helpers/text_helper.rb +5 -6
- data/lib/action_view/helpers/translation_helper.rb +2 -2
- data/lib/action_view/helpers/url_helper.rb +11 -11
- data/lib/action_view/renderer/partial_renderer.rb +27 -22
- data/lib/sprockets/assets.rake +23 -0
- data/lib/sprockets/compressors.rb +21 -0
- data/lib/sprockets/helpers/rails_helper.rb +44 -19
- data/lib/sprockets/railtie.rb +29 -18
- metadata +29 -54
data/CHANGELOG
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
*Rails 3.1.0 (unreleased)*
|
2
2
|
|
3
|
+
* The submit form helper does not generate an id "object_name_id" anymore. [fbrusatti]
|
4
|
+
|
5
|
+
* Make sure respond_with with :js tries to render a template in all cases [José Valim]
|
6
|
+
|
7
|
+
* json_escape will now return a SafeBuffer string if it receives SafeBuffer string [tenderlove]
|
8
|
+
|
3
9
|
* Make sure escape_js returns SafeBuffer string if it receives SafeBuffer string [Prem Sichanugrist]
|
4
10
|
|
5
11
|
* Fix escape_js to work correctly with the new SafeBuffer restriction [Paul Gallagher]
|
@@ -3,7 +3,7 @@ module AbstractController
|
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
5
|
included do
|
6
|
-
config_accessor :asset_host, :asset_path, :assets_dir, :javascripts_dir, :stylesheets_dir
|
6
|
+
config_accessor :asset_host, :asset_path, :assets_dir, :javascripts_dir, :stylesheets_dir
|
7
7
|
end
|
8
8
|
end
|
9
9
|
end
|
@@ -81,11 +81,12 @@ module AbstractController
|
|
81
81
|
# class EmployeeController < BankController
|
82
82
|
# layout nil
|
83
83
|
#
|
84
|
-
#
|
85
|
-
#
|
86
|
-
#
|
87
|
-
# The TellerController uses +teller.html.erb
|
88
|
-
#
|
84
|
+
# In these examples:
|
85
|
+
# * The InformationController uses the "bank_standard" layout, inherited from BankController.
|
86
|
+
# * The TellerController follows convention and uses +app/views/layouts/teller.html.erb+.
|
87
|
+
# * The TillController inherits the layout from TellerController and uses +teller.html.erb+ as well.
|
88
|
+
# * The VaultController chooses a layout dynamically by calling the <tt>access_level_layout</tt> method.
|
89
|
+
# * The EmployeeController does not use a layout at all.
|
89
90
|
#
|
90
91
|
# == Types of layouts
|
91
92
|
#
|
@@ -138,8 +139,8 @@ module AbstractController
|
|
138
139
|
#
|
139
140
|
# end
|
140
141
|
#
|
141
|
-
# This will assign "weblog_standard" as the WeblogController's layout
|
142
|
-
# around the rendered view.
|
142
|
+
# This will assign "weblog_standard" as the WeblogController's layout for all actions except for the +rss+ action, which will
|
143
|
+
# be rendered directly, without wrapping a layout around the rendered view.
|
143
144
|
#
|
144
145
|
# Both the <tt>:only</tt> and <tt>:except</tt> condition can accept an arbitrary number of method references, so
|
145
146
|
# #<tt>:except => [ :rss, :text_only ]</tt> is valid, as is <tt>:except => :rss</tt>.
|
@@ -158,7 +159,7 @@ module AbstractController
|
|
158
159
|
# end
|
159
160
|
# end
|
160
161
|
#
|
161
|
-
# This will render the help action with the "help" layout instead
|
162
|
+
# This will override the controller-wide "weblog_standard" layout, and will render the help action with the "help" layout instead.
|
162
163
|
module Layouts
|
163
164
|
extend ActiveSupport::Concern
|
164
165
|
|
@@ -166,6 +167,7 @@ module AbstractController
|
|
166
167
|
|
167
168
|
included do
|
168
169
|
class_attribute :_layout_conditions
|
170
|
+
remove_possible_method :_layout_conditions
|
169
171
|
delegate :_layout_conditions, :to => :'self.class'
|
170
172
|
self._layout_conditions = {}
|
171
173
|
_write_layout_method
|
@@ -31,7 +31,7 @@ module ActionController
|
|
31
31
|
# "302 Moved" HTTP response that takes the user to the index action.
|
32
32
|
#
|
33
33
|
# These two methods represent the two basic action archetypes used in Action Controllers. Get-and-show and do-and-redirect.
|
34
|
-
# Most actions are variations
|
34
|
+
# Most actions are variations on these themes.
|
35
35
|
#
|
36
36
|
# == Requests
|
37
37
|
#
|
@@ -116,8 +116,8 @@ module ActionController
|
|
116
116
|
#
|
117
117
|
# Title: <%= @post.title %>
|
118
118
|
#
|
119
|
-
# You don't have to rely on the automated rendering.
|
120
|
-
# the manual rendering methods:
|
119
|
+
# You don't have to rely on the automated rendering. For example, actions that could result in the rendering of different templates
|
120
|
+
# will use the manual rendering methods:
|
121
121
|
#
|
122
122
|
# def search
|
123
123
|
# @results = Search.find(params[:query])
|
@@ -132,9 +132,9 @@ module ActionController
|
|
132
132
|
#
|
133
133
|
# == Redirects
|
134
134
|
#
|
135
|
-
# Redirects are used to move from one action to another. For example, after a <tt>create</tt> action, which stores a blog entry to
|
136
|
-
# we might like to show the user the new entry. Because we're following good DRY principles (Don't Repeat Yourself), we're
|
137
|
-
# a <tt>show</tt> action that we'll assume has already been created. The code might look like this:
|
135
|
+
# Redirects are used to move from one action to another. For example, after a <tt>create</tt> action, which stores a blog entry to the
|
136
|
+
# database, we might like to show the user the new entry. Because we're following good DRY principles (Don't Repeat Yourself), we're
|
137
|
+
# going to reuse (and redirect to) a <tt>show</tt> action that we'll assume has already been created. The code might look like this:
|
138
138
|
#
|
139
139
|
# def create
|
140
140
|
# @entry = Entry.new(params[:entry])
|
@@ -146,7 +146,9 @@ module ActionController
|
|
146
146
|
# end
|
147
147
|
# end
|
148
148
|
#
|
149
|
-
# In this case, after saving our new entry to the database, the user is redirected to the <tt>show</tt> method which is then executed.
|
149
|
+
# In this case, after saving our new entry to the database, the user is redirected to the <tt>show</tt> method, which is then executed.
|
150
|
+
# Note that this is an external HTTP-level redirection which will cause the browser to make a second request (a GET to the show action),
|
151
|
+
# and not some internal re-routing which calls both "create" and then "show" within one request.
|
150
152
|
#
|
151
153
|
# Learn more about <tt>redirect_to</tt> and what options you have in ActionController::Redirecting.
|
152
154
|
#
|
@@ -210,16 +212,16 @@ module ActionController
|
|
210
212
|
# also include them at the bottom.
|
211
213
|
AbstractController::Callbacks,
|
212
214
|
|
215
|
+
# Append rescue at the bottom to wrap as much as possible.
|
216
|
+
Rescue,
|
217
|
+
|
213
218
|
# Add instrumentations hooks at the bottom, to ensure they instrument
|
214
219
|
# all the methods properly.
|
215
220
|
Instrumentation,
|
216
221
|
|
217
222
|
# Params wrapper should come before instrumentation so they are
|
218
223
|
# properly showed in logs
|
219
|
-
ParamsWrapper
|
220
|
-
|
221
|
-
# The same with rescue, append it at the end to wrap as much as possible.
|
222
|
-
Rescue
|
224
|
+
ParamsWrapper
|
223
225
|
]
|
224
226
|
|
225
227
|
MODULES.each do |mod|
|
@@ -43,6 +43,7 @@ module ActionController
|
|
43
43
|
#
|
44
44
|
# The status code can either be a standard {HTTP Status code}[http://www.iana.org/assignments/http-status-codes] as an
|
45
45
|
# integer, or a symbol representing the downcased, underscored and symbolized description.
|
46
|
+
# Note that the status code must be a 3xx HTTP code, or redirection will not occur.
|
46
47
|
#
|
47
48
|
# It is also possible to assign a flash message as part of the redirection. There are two special accessors for commonly used the flash names
|
48
49
|
# +alert+ and +notice+ as well as a general purpose +flash+ bucket.
|
@@ -7,17 +7,16 @@ module ActionController #:nodoc:
|
|
7
7
|
# Controller actions are protected from Cross-Site Request Forgery (CSRF) attacks
|
8
8
|
# by including a token in the rendered html for your application. This token is
|
9
9
|
# stored as a random string in the session, to which an attacker does not have
|
10
|
-
# access. When a request reaches your application, \Rails
|
11
|
-
# token with the token in the session. Only HTML and
|
10
|
+
# access. When a request reaches your application, \Rails verifies the received
|
11
|
+
# token with the token in the session. Only HTML and JavaScript requests are checked,
|
12
12
|
# so this will not protect your XML API (presumably you'll have a different
|
13
13
|
# authentication scheme there anyway). Also, GET requests are not protected as these
|
14
14
|
# should be idempotent.
|
15
15
|
#
|
16
16
|
# CSRF protection is turned on with the <tt>protect_from_forgery</tt> method,
|
17
|
-
# which
|
18
|
-
#
|
19
|
-
#
|
20
|
-
# public/422.html.
|
17
|
+
# which checks the token and resets the session if it doesn't match what was expected.
|
18
|
+
# A call to this method is generated for new \Rails applications by default.
|
19
|
+
# You can customize the error message by editing public/422.html.
|
21
20
|
#
|
22
21
|
# The token parameter is named <tt>authenticity_token</tt> by default. The name and
|
23
22
|
# value of this token must be added to every layout that renders forms by including
|
@@ -63,7 +62,7 @@ module ActionController #:nodoc:
|
|
63
62
|
#
|
64
63
|
# Valid Options:
|
65
64
|
#
|
66
|
-
# * <tt>:only/:except</tt> - Passed to the <tt>before_filter</tt> call.
|
65
|
+
# * <tt>:only/:except</tt> - Passed to the <tt>before_filter</tt> call. Set which actions are verified.
|
67
66
|
def protect_from_forgery(options = {})
|
68
67
|
self.request_forgery_protection_token ||= :authenticity_token
|
69
68
|
prepend_before_filter :verify_authenticity_token, options
|
@@ -71,7 +70,7 @@ module ActionController #:nodoc:
|
|
71
70
|
end
|
72
71
|
|
73
72
|
protected
|
74
|
-
# The actual before_filter that is used.
|
73
|
+
# The actual before_filter that is used. Modify this to change how you handle unverified requests.
|
75
74
|
def verify_authenticity_token
|
76
75
|
unless verified_request?
|
77
76
|
logger.debug "WARNING: Can't verify CSRF token authenticity" if logger
|
@@ -79,11 +78,13 @@ module ActionController #:nodoc:
|
|
79
78
|
end
|
80
79
|
end
|
81
80
|
|
81
|
+
# This is the method that defines the application behavior when a request is found to be unverified.
|
82
|
+
# By default, \Rails resets the session when it finds an unverified request.
|
82
83
|
def handle_unverified_request
|
83
84
|
reset_session
|
84
85
|
end
|
85
86
|
|
86
|
-
# Returns true or false if a request is verified.
|
87
|
+
# Returns true or false if a request is verified. Checks:
|
87
88
|
#
|
88
89
|
# * is it a GET request? Gets should be safe and idempotent
|
89
90
|
# * Does the form_authenticity_token match the given token value from the params?
|
@@ -162,6 +162,11 @@ module ActionController #:nodoc:
|
|
162
162
|
navigation_behavior(e)
|
163
163
|
end
|
164
164
|
|
165
|
+
# to_js simply tries to render a template. If no template is found, raises the error.
|
166
|
+
def to_js
|
167
|
+
default_render
|
168
|
+
end
|
169
|
+
|
165
170
|
# All other formats follow the procedure below. First we try to render a
|
166
171
|
# template, if the template is not available, we verify if the resource
|
167
172
|
# responds to :to_format and display it.
|
@@ -24,20 +24,8 @@ module ActionController #:nodoc:
|
|
24
24
|
#
|
25
25
|
# == Examples
|
26
26
|
#
|
27
|
-
# Streaming can be added to a
|
28
|
-
#
|
29
|
-
#
|
30
|
-
# class PostsController
|
31
|
-
# stream
|
32
|
-
# end
|
33
|
-
#
|
34
|
-
# The +stream+ method accepts the same options as +before_filter+ and friends:
|
35
|
-
#
|
36
|
-
# class PostsController
|
37
|
-
# stream :only => :index
|
38
|
-
# end
|
39
|
-
#
|
40
|
-
# You can also selectively turn on streaming for specific actions:
|
27
|
+
# Streaming can be added to a given template easily, all you need to do is
|
28
|
+
# to pass the :stream option.
|
41
29
|
#
|
42
30
|
# class PostsController
|
43
31
|
# def index
|
@@ -72,6 +60,9 @@ module ActionController #:nodoc:
|
|
72
60
|
# render :stream => true
|
73
61
|
# end
|
74
62
|
#
|
63
|
+
# Notice that :stream only works with templates. Rendering :json
|
64
|
+
# or :xml with :stream won't work.
|
65
|
+
#
|
75
66
|
# == Communication between layout and template
|
76
67
|
#
|
77
68
|
# When streaming, rendering happens top-down instead of inside-out.
|
@@ -215,6 +206,7 @@ module ActionController #:nodoc:
|
|
215
206
|
# Render streaming templates. It accepts :only, :except, :if and :unless as options
|
216
207
|
# to specify when to stream, as in ActionController filters.
|
217
208
|
def stream(options={})
|
209
|
+
ActiveSupport::Deprecation.warn "stream class method is deprecated. Please give the :stream option to render instead"
|
218
210
|
if defined?(Fiber)
|
219
211
|
before_filter :_stream_filter, options
|
220
212
|
else
|
@@ -395,7 +395,26 @@ module ActionController
|
|
395
395
|
end
|
396
396
|
alias xhr :xml_http_request
|
397
397
|
|
398
|
+
def paramify_values(hash_or_array_or_value)
|
399
|
+
case hash_or_array_or_value
|
400
|
+
when Hash
|
401
|
+
hash_or_array_or_value.each do |key, value|
|
402
|
+
hash_or_array_or_value[key] = paramify_values(value)
|
403
|
+
end
|
404
|
+
when Array
|
405
|
+
hash_or_array_or_value.map {|i| paramify_values(i)}
|
406
|
+
when Rack::Test::UploadedFile
|
407
|
+
hash_or_array_or_value
|
408
|
+
else
|
409
|
+
hash_or_array_or_value.to_param
|
410
|
+
end
|
411
|
+
end
|
412
|
+
|
398
413
|
def process(action, parameters = nil, session = nil, flash = nil, http_method = 'GET')
|
414
|
+
# Ensure that numbers and symbols passed as params are converted to
|
415
|
+
# proper params, as is the case when engaging rack.
|
416
|
+
paramify_values(parameters)
|
417
|
+
|
399
418
|
# Sanity check for required instance variables so we can give an
|
400
419
|
# understandable error message.
|
401
420
|
%w(@routes @controller @request @response).each do |iv_name|
|
@@ -4,7 +4,7 @@ module ActionDispatch
|
|
4
4
|
attr_accessor :original_filename, :content_type, :tempfile, :headers
|
5
5
|
|
6
6
|
def initialize(hash)
|
7
|
-
@original_filename = hash[:filename]
|
7
|
+
@original_filename = encode_filename(hash[:filename])
|
8
8
|
@content_type = hash[:type]
|
9
9
|
@headers = hash[:head]
|
10
10
|
@tempfile = hash[:tempfile]
|
@@ -30,6 +30,16 @@ module ActionDispatch
|
|
30
30
|
def size
|
31
31
|
@tempfile.size
|
32
32
|
end
|
33
|
+
|
34
|
+
private
|
35
|
+
def encode_filename(filename)
|
36
|
+
# Encode the filename in the utf8 encoding, unless it is nil or we're in 1.8
|
37
|
+
if "ruby".encoding_aware? && filename
|
38
|
+
filename.force_encoding("UTF-8").encode!
|
39
|
+
else
|
40
|
+
filename
|
41
|
+
end
|
42
|
+
end
|
33
43
|
end
|
34
44
|
|
35
45
|
module Upload
|
@@ -116,6 +116,8 @@ module ActionDispatch
|
|
116
116
|
path
|
117
117
|
elsif path.include?(":format") || path.end_with?('/')
|
118
118
|
path
|
119
|
+
elsif @options[:format] == true
|
120
|
+
"#{path}.:format"
|
119
121
|
else
|
120
122
|
"#{path}(.:format)"
|
121
123
|
end
|
@@ -187,13 +189,12 @@ module ActionDispatch
|
|
187
189
|
end
|
188
190
|
|
189
191
|
def blocks
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
192
|
+
constraints = @options[:constraints]
|
193
|
+
if constraints.present? && !constraints.is_a?(Hash)
|
194
|
+
[constraints]
|
195
|
+
else
|
196
|
+
@scope[:blocks] || []
|
194
197
|
end
|
195
|
-
|
196
|
-
block
|
197
198
|
end
|
198
199
|
|
199
200
|
def constraints
|
@@ -1102,9 +1103,9 @@ module ActionDispatch
|
|
1102
1103
|
#
|
1103
1104
|
# The +comments+ resource here will have the following routes generated for it:
|
1104
1105
|
#
|
1105
|
-
# post_comments GET /
|
1106
|
-
# post_comments POST /
|
1107
|
-
# new_post_comment GET /
|
1106
|
+
# post_comments GET /posts/:post_id/comments(.:format)
|
1107
|
+
# post_comments POST /posts/:post_id/comments(.:format)
|
1108
|
+
# new_post_comment GET /posts/:post_id/comments/new(.:format)
|
1108
1109
|
# edit_comment GET /sekret/comments/:id/edit(.:format)
|
1109
1110
|
# comment GET /sekret/comments/:id(.:format)
|
1110
1111
|
# comment PUT /sekret/comments/:id(.:format)
|
@@ -124,14 +124,7 @@ module ActionDispatch
|
|
124
124
|
args.last.kind_of?(Hash) ? args.last.merge!(url_options) : args << url_options
|
125
125
|
end
|
126
126
|
|
127
|
-
|
128
|
-
proxy.send(named_route, *args)
|
129
|
-
else
|
130
|
-
# we need to use url_for, because polymorphic_url can be used in context of other than
|
131
|
-
# current routes (e.g. engine's routes). As named routes from engine are not included
|
132
|
-
# calling engine's named route directly would fail.
|
133
|
-
url_for _routes.url_helpers.__send__("hash_for_#{named_route}", *args)
|
134
|
-
end
|
127
|
+
(proxy || self).send(named_route, *args)
|
135
128
|
end
|
136
129
|
|
137
130
|
# Returns the path component of a URL for the given record. It uses
|
@@ -182,10 +175,12 @@ module ActionDispatch
|
|
182
175
|
|
183
176
|
if record.is_a?(Symbol) || record.is_a?(String)
|
184
177
|
route << record
|
185
|
-
|
178
|
+
elsif record
|
186
179
|
route << ActiveModel::Naming.route_key(record)
|
187
180
|
route = [route.join("_").singularize] if inflection == :singular
|
188
181
|
route << "index" if ActiveModel::Naming.uncountable?(record) && inflection == :plural
|
182
|
+
else
|
183
|
+
raise ArgumentError, "Nil location provided. Can't build URI."
|
189
184
|
end
|
190
185
|
|
191
186
|
route << routing_type(options)
|
data/lib/action_pack/version.rb
CHANGED
data/lib/action_view.rb
CHANGED
@@ -0,0 +1,148 @@
|
|
1
|
+
require 'zlib'
|
2
|
+
require 'active_support/core_ext/file'
|
3
|
+
|
4
|
+
module ActionView
|
5
|
+
|
6
|
+
class AssetPaths #:nodoc:
|
7
|
+
attr_reader :config, :controller
|
8
|
+
|
9
|
+
def initialize(config, controller = nil)
|
10
|
+
@config = config
|
11
|
+
@controller = controller
|
12
|
+
end
|
13
|
+
|
14
|
+
# Add the extension +ext+ if not present. Return full or scheme-relative URLs otherwise untouched.
|
15
|
+
# Prefix with <tt>/dir/</tt> if lacking a leading +/+. Account for relative URL
|
16
|
+
# roots. Rewrite the asset path for cache-busting asset ids. Include
|
17
|
+
# asset host, if configured, with the correct request protocol.
|
18
|
+
#
|
19
|
+
# When include_host is true and the asset host does not specify the protocol
|
20
|
+
# the protocol parameter specifies how the protocol will be added.
|
21
|
+
# When :relative (default), the protocol will be determined by the client using current protocol
|
22
|
+
# When :request, the protocol will be the request protocol
|
23
|
+
# Otherwise, the protocol is used (E.g. :http, :https, etc)
|
24
|
+
def compute_public_path(source, dir, ext = nil, include_host = true, protocol = nil)
|
25
|
+
source = source.to_s
|
26
|
+
return source if is_uri?(source)
|
27
|
+
|
28
|
+
source = rewrite_extension(source, dir, ext) if ext
|
29
|
+
source = rewrite_asset_path(source, dir)
|
30
|
+
source = rewrite_relative_url_root(source, relative_url_root) if has_request?
|
31
|
+
source = rewrite_host_and_protocol(source, protocol) if include_host
|
32
|
+
source
|
33
|
+
end
|
34
|
+
|
35
|
+
# Return the filesystem path for the source
|
36
|
+
def compute_source_path(source, dir, ext)
|
37
|
+
source = rewrite_extension(source, dir, ext) if ext
|
38
|
+
File.join(config.assets_dir, dir, source)
|
39
|
+
end
|
40
|
+
|
41
|
+
def is_uri?(path)
|
42
|
+
path =~ %r{^[-a-z]+://|^cid:|^//}
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def rewrite_extension(source, dir, ext)
|
48
|
+
raise NotImplementedError
|
49
|
+
end
|
50
|
+
|
51
|
+
def rewrite_asset_path(source, path = nil)
|
52
|
+
raise NotImplementedError
|
53
|
+
end
|
54
|
+
|
55
|
+
def rewrite_relative_url_root(source, relative_url_root)
|
56
|
+
relative_url_root && !source.starts_with?("#{relative_url_root}/") ? "#{relative_url_root}#{source}" : source
|
57
|
+
end
|
58
|
+
|
59
|
+
def has_request?
|
60
|
+
controller.respond_to?(:request)
|
61
|
+
end
|
62
|
+
|
63
|
+
def rewrite_host_and_protocol(source, protocol = nil)
|
64
|
+
host = compute_asset_host(source)
|
65
|
+
if host && !is_uri?(host)
|
66
|
+
if (protocol || default_protocol) == :request && !has_request?
|
67
|
+
host = nil
|
68
|
+
else
|
69
|
+
host = "#{compute_protocol(protocol)}#{host}"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
host.nil? ? source : "#{host}#{source}"
|
73
|
+
end
|
74
|
+
|
75
|
+
def compute_protocol(protocol)
|
76
|
+
protocol ||= default_protocol
|
77
|
+
case protocol
|
78
|
+
when :relative
|
79
|
+
"//"
|
80
|
+
when :request
|
81
|
+
unless @controller
|
82
|
+
invalid_asset_host!("The protocol requested was :request. Consider using :relative instead.")
|
83
|
+
end
|
84
|
+
@controller.request.protocol
|
85
|
+
else
|
86
|
+
"#{protocol}://"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def default_protocol
|
91
|
+
protocol = @config.action_controller.default_asset_host_protocol if @config.action_controller.present?
|
92
|
+
protocol ||= @config.default_asset_host_protocol
|
93
|
+
protocol || (has_request? ? :request : :relative)
|
94
|
+
end
|
95
|
+
|
96
|
+
def invalid_asset_host!(help_message)
|
97
|
+
raise ActionController::RoutingError, "This asset host cannot be computed without a request in scope. #{help_message}"
|
98
|
+
end
|
99
|
+
|
100
|
+
# Pick an asset host for this source. Returns +nil+ if no host is set,
|
101
|
+
# the host if no wildcard is set, the host interpolated with the
|
102
|
+
# numbers 0-3 if it contains <tt>%d</tt> (the number is the source hash mod 4),
|
103
|
+
# or the value returned from invoking the proc if it's a proc or the value from
|
104
|
+
# invoking call if it's an object responding to call.
|
105
|
+
def compute_asset_host(source)
|
106
|
+
if host = asset_host_config
|
107
|
+
if host.respond_to?(:call)
|
108
|
+
args = [source]
|
109
|
+
arity = arity_of(host)
|
110
|
+
if arity > 1 && !has_request?
|
111
|
+
invalid_asset_host!("Remove the second argument to your asset_host Proc if you do not need the request.")
|
112
|
+
end
|
113
|
+
args << current_request if (arity > 1 || arity < 0) && has_request?
|
114
|
+
host.call(*args)
|
115
|
+
else
|
116
|
+
(host =~ /%d/) ? host % (Zlib.crc32(source) % 4) : host
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def relative_url_root
|
122
|
+
config = controller.config if controller.respond_to?(:config)
|
123
|
+
config ||= config.action_controller if config.action_controller.present?
|
124
|
+
config ||= config
|
125
|
+
config.relative_url_root
|
126
|
+
end
|
127
|
+
|
128
|
+
def asset_host_config
|
129
|
+
if config.action_controller.present?
|
130
|
+
config.action_controller.asset_host
|
131
|
+
else
|
132
|
+
config.asset_host
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
# Returns the current request if one exists.
|
137
|
+
def current_request
|
138
|
+
controller.request if has_request?
|
139
|
+
end
|
140
|
+
|
141
|
+
# Returns the arity of a callable
|
142
|
+
def arity_of(callable)
|
143
|
+
callable.respond_to?(:arity) ? callable.arity : callable.method(:call).arity
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|