actionview 5.0.7.2 → 5.1.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of actionview might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +92 -384
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/lib/action_view.rb +5 -5
- data/lib/action_view/base.rb +19 -19
- data/lib/action_view/buffers.rb +1 -1
- data/lib/action_view/context.rb +1 -1
- data/lib/action_view/dependency_tracker.rb +4 -5
- data/lib/action_view/digestor.rb +6 -7
- data/lib/action_view/flows.rb +5 -6
- data/lib/action_view/gem_version.rb +3 -3
- data/lib/action_view/helpers.rb +1 -1
- data/lib/action_view/helpers/active_model_helper.rb +8 -8
- data/lib/action_view/helpers/asset_tag_helper.rb +62 -36
- data/lib/action_view/helpers/asset_url_helper.rb +111 -49
- data/lib/action_view/helpers/atom_feed_helper.rb +12 -13
- data/lib/action_view/helpers/cache_helper.rb +34 -20
- data/lib/action_view/helpers/capture_helper.rb +2 -2
- data/lib/action_view/helpers/controller_helper.rb +3 -11
- data/lib/action_view/helpers/csrf_helper.rb +3 -3
- data/lib/action_view/helpers/date_helper.rb +109 -107
- data/lib/action_view/helpers/debug_helper.rb +2 -3
- data/lib/action_view/helpers/form_helper.rb +406 -31
- data/lib/action_view/helpers/form_options_helper.rb +12 -12
- data/lib/action_view/helpers/form_tag_helper.rb +19 -18
- data/lib/action_view/helpers/javascript_helper.rb +6 -6
- data/lib/action_view/helpers/number_helper.rb +48 -46
- data/lib/action_view/helpers/output_safety_helper.rb +8 -8
- data/lib/action_view/helpers/rendering_helper.rb +2 -2
- data/lib/action_view/helpers/sanitize_helper.rb +6 -8
- data/lib/action_view/helpers/tag_helper.rb +194 -77
- data/lib/action_view/helpers/tags/base.rb +121 -102
- data/lib/action_view/helpers/tags/check_box.rb +17 -17
- data/lib/action_view/helpers/tags/collection_check_boxes.rb +8 -8
- data/lib/action_view/helpers/tags/collection_helpers.rb +60 -60
- data/lib/action_view/helpers/tags/collection_radio_buttons.rb +2 -2
- data/lib/action_view/helpers/tags/collection_select.rb +2 -2
- data/lib/action_view/helpers/tags/date_select.rb +36 -36
- data/lib/action_view/helpers/tags/grouped_collection_select.rb +2 -2
- data/lib/action_view/helpers/tags/label.rb +4 -0
- data/lib/action_view/helpers/tags/password_field.rb +1 -1
- data/lib/action_view/helpers/tags/radio_button.rb +4 -4
- data/lib/action_view/helpers/tags/select.rb +9 -9
- data/lib/action_view/helpers/tags/text_area.rb +1 -1
- data/lib/action_view/helpers/tags/text_field.rb +5 -5
- data/lib/action_view/helpers/tags/translator.rb +14 -12
- data/lib/action_view/helpers/text_helper.rb +20 -19
- data/lib/action_view/helpers/translation_helper.rb +6 -6
- data/lib/action_view/helpers/url_helper.rb +42 -38
- data/lib/action_view/layouts.rb +51 -47
- data/lib/action_view/log_subscriber.rb +24 -9
- data/lib/action_view/lookup_context.rb +19 -25
- data/lib/action_view/path_set.rb +19 -19
- data/lib/action_view/railtie.rb +3 -3
- data/lib/action_view/record_identifier.rb +6 -6
- data/lib/action_view/renderer/abstract_renderer.rb +17 -17
- data/lib/action_view/renderer/partial_renderer.rb +188 -187
- data/lib/action_view/renderer/partial_renderer/collection_caching.rb +7 -1
- data/lib/action_view/renderer/streaming_template_renderer.rb +45 -47
- data/lib/action_view/renderer/template_renderer.rb +64 -66
- data/lib/action_view/rendering.rb +4 -5
- data/lib/action_view/routing_url_for.rb +9 -13
- data/lib/action_view/tasks/cache_digests.rake +7 -7
- data/lib/action_view/template.rb +26 -27
- data/lib/action_view/template/error.rb +5 -15
- data/lib/action_view/template/handlers.rb +4 -4
- data/lib/action_view/template/handlers/builder.rb +7 -7
- data/lib/action_view/template/handlers/erb.rb +9 -76
- data/lib/action_view/template/handlers/erb/deprecated_erubis.rb +9 -0
- data/lib/action_view/template/handlers/erb/erubi.rb +81 -0
- data/lib/action_view/template/handlers/erb/erubis.rb +81 -0
- data/lib/action_view/template/html.rb +2 -4
- data/lib/action_view/template/resolver.rb +107 -90
- data/lib/action_view/template/text.rb +5 -8
- data/lib/action_view/template/types.rb +1 -1
- data/lib/action_view/test_case.rb +20 -21
- data/lib/action_view/testing/resolvers.rb +29 -30
- data/lib/action_view/version.rb +1 -1
- data/lib/action_view/view_paths.rb +20 -8
- data/lib/assets/compiled/rails-ujs.js +648 -0
- metadata +19 -14
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "zlib"
|
2
2
|
|
3
3
|
module ActionView
|
4
4
|
# = Action View Asset URL Helpers
|
@@ -36,7 +36,7 @@ module ActionView
|
|
36
36
|
# some asset downloads to wait for previous assets to finish before they can
|
37
37
|
# begin. You can use the <tt>%d</tt> wildcard in the +asset_host+ to
|
38
38
|
# distribute the requests over four hosts. For example,
|
39
|
-
# <tt>assets%d.example.com
|
39
|
+
# <tt>assets%d.example.com</tt> will spread the asset requests over
|
40
40
|
# "assets0.example.com", ..., "assets3.example.com".
|
41
41
|
#
|
42
42
|
# image_tag("rails.png")
|
@@ -96,8 +96,8 @@ module ActionView
|
|
96
96
|
# have SSL certificates for each of the asset hosts this technique allows you
|
97
97
|
# to avoid warnings in the client about mixed media.
|
98
98
|
# Note that the request parameter might not be supplied, e.g. when the assets
|
99
|
-
# are precompiled via a Rake task. Make sure to use a Proc instead of a lambda,
|
100
|
-
# since a Proc allows missing parameters and sets them to nil
|
99
|
+
# are precompiled via a Rake task. Make sure to use a +Proc+ instead of a lambda,
|
100
|
+
# since a +Proc+ allows missing parameters and sets them to +nil+.
|
101
101
|
#
|
102
102
|
# config.action_controller.asset_host = Proc.new { |source, request|
|
103
103
|
# if request && request.ssl?
|
@@ -117,31 +117,86 @@ module ActionView
|
|
117
117
|
module AssetUrlHelper
|
118
118
|
URI_REGEXP = %r{^[-a-z]+://|^(?:cid|data):|^//}i
|
119
119
|
|
120
|
-
#
|
121
|
-
#
|
122
|
-
#
|
120
|
+
# This is the entry point for all assets.
|
121
|
+
# When using the asset pipeline (i.e. sprockets and sprockets-rails), the
|
122
|
+
# behavior is "enhanced". You can bypass the asset pipeline by passing in
|
123
|
+
# <tt>skip_pipeline: true</tt> to the options.
|
123
124
|
#
|
124
125
|
# All other asset *_path helpers delegate through this method.
|
125
126
|
#
|
126
|
-
#
|
127
|
-
#
|
128
|
-
#
|
129
|
-
#
|
127
|
+
# === With the asset pipeline
|
128
|
+
#
|
129
|
+
# All options passed to +asset_path+ will be passed to +compute_asset_path+
|
130
|
+
# which is implemented by sprockets-rails.
|
131
|
+
#
|
132
|
+
# asset_path("application.js") # => "/assets/application-60aa4fdc5cea14baf5400fba1abf4f2a46a5166bad4772b1effe341570f07de9.js"
|
133
|
+
#
|
134
|
+
# === Without the asset pipeline (<tt>skip_pipeline: true</tt>)
|
135
|
+
#
|
136
|
+
# Accepts a <tt>type</tt> option that can specify the asset's extension. No error
|
137
|
+
# checking is done to verify the source passed into +asset_path+ is valid
|
138
|
+
# and that the file exists on disk.
|
139
|
+
#
|
140
|
+
# asset_path("application.js", skip_pipeline: true) # => "application.js"
|
141
|
+
# asset_path("filedoesnotexist.png", skip_pipeline: true) # => "filedoesnotexist.png"
|
142
|
+
# asset_path("application", type: :javascript, skip_pipeline: true) # => "/javascripts/application.js"
|
143
|
+
# asset_path("application", type: :stylesheet, skip_pipeline: true) # => "/stylesheets/application.css"
|
144
|
+
#
|
145
|
+
# === Options applying to all assets
|
146
|
+
#
|
147
|
+
# Below lists scenarios that apply to +asset_path+ whether or not you're
|
148
|
+
# using the asset pipeline.
|
149
|
+
#
|
150
|
+
# - All fully qualified urls are returned immediately. This bypasses the
|
151
|
+
# asset pipeline and all other behavior described.
|
152
|
+
#
|
153
|
+
# asset_path("http://www.example.com/js/xmlhr.js") # => "http://www.example.com/js/xmlhr.js"
|
154
|
+
#
|
155
|
+
# - All assets that begin with a forward slash are assumed to be full
|
156
|
+
# urls and will not be expanded. This will bypass the asset pipeline.
|
157
|
+
#
|
158
|
+
# asset_path("/foo.png") # => "/foo.png"
|
159
|
+
#
|
160
|
+
# - All blank strings will be returned immediately. This bypasses the
|
161
|
+
# asset pipeline and all other behavior described.
|
162
|
+
#
|
163
|
+
# asset_path("") # => ""
|
164
|
+
#
|
165
|
+
# - If <tt>config.relative_url_root</tt> is specified, all assets will have that
|
166
|
+
# root prepended.
|
167
|
+
#
|
168
|
+
# Rails.application.config.relative_url_root = "bar"
|
169
|
+
# asset_path("foo.js", skip_pipeline: true) # => "bar/foo.js"
|
170
|
+
#
|
171
|
+
# - A different asset host can be specified via <tt>config.action_controller.asset_host</tt>
|
172
|
+
# this is commonly used in conjunction with a CDN.
|
173
|
+
#
|
174
|
+
# Rails.application.config.action_controller.asset_host = "assets.example.com"
|
175
|
+
# asset_path("foo.js", skip_pipeline: true) # => "http://assets.example.com/foo.js"
|
176
|
+
#
|
177
|
+
# - An extension name can be specified manually with <tt>extname</tt>.
|
178
|
+
#
|
179
|
+
# asset_path("foo", skip_pipeline: true, extname: ".js") # => "/foo.js"
|
180
|
+
# asset_path("foo.css", skip_pipeline: true, extname: ".js") # => "/foo.css.js"
|
130
181
|
def asset_path(source, options = {})
|
131
182
|
raise ArgumentError, "nil is not a valid asset source" if source.nil?
|
132
183
|
|
133
184
|
source = source.to_s
|
134
|
-
return ""
|
135
|
-
return source if source
|
185
|
+
return "" if source.blank?
|
186
|
+
return source if URI_REGEXP.match?(source)
|
136
187
|
|
137
|
-
tail, source = source[/([\?#].+)$/], source.sub(/([\?#].+)$/,
|
188
|
+
tail, source = source[/([\?#].+)$/], source.sub(/([\?#].+)$/, "".freeze)
|
138
189
|
|
139
190
|
if extname = compute_asset_extname(source, options)
|
140
191
|
source = "#{source}#{extname}"
|
141
192
|
end
|
142
193
|
|
143
194
|
if source[0] != ?/
|
144
|
-
|
195
|
+
if options[:skip_pipeline]
|
196
|
+
source = public_compute_asset_path(source, options)
|
197
|
+
else
|
198
|
+
source = compute_asset_path(source, options)
|
199
|
+
end
|
145
200
|
end
|
146
201
|
|
147
202
|
relative_url_root = defined?(config.relative_url_root) && config.relative_url_root
|
@@ -168,31 +223,35 @@ module ActionView
|
|
168
223
|
# asset_url "application.js", host: "http://cdn.example.com" # => http://cdn.example.com/assets/application.js
|
169
224
|
#
|
170
225
|
def asset_url(source, options = {})
|
171
|
-
path_to_asset(source, options.merge(:
|
226
|
+
path_to_asset(source, options.merge(protocol: :request))
|
172
227
|
end
|
173
228
|
alias_method :url_to_asset, :asset_url # aliased to avoid conflicts with an asset_url named route
|
174
229
|
|
175
230
|
ASSET_EXTENSIONS = {
|
176
|
-
javascript:
|
177
|
-
stylesheet:
|
231
|
+
javascript: ".js",
|
232
|
+
stylesheet: ".css"
|
178
233
|
}
|
179
234
|
|
180
|
-
# Compute extname to append to asset path. Returns nil if
|
235
|
+
# Compute extname to append to asset path. Returns +nil+ if
|
181
236
|
# nothing should be added.
|
182
237
|
def compute_asset_extname(source, options = {})
|
183
238
|
return if options[:extname] == false
|
184
239
|
extname = options[:extname] || ASSET_EXTENSIONS[options[:type]]
|
185
|
-
|
240
|
+
if extname && File.extname(source) != extname
|
241
|
+
extname
|
242
|
+
else
|
243
|
+
nil
|
244
|
+
end
|
186
245
|
end
|
187
246
|
|
188
247
|
# Maps asset types to public directory.
|
189
248
|
ASSET_PUBLIC_DIRECTORIES = {
|
190
|
-
audio:
|
191
|
-
font:
|
192
|
-
image:
|
193
|
-
javascript:
|
194
|
-
stylesheet:
|
195
|
-
video:
|
249
|
+
audio: "/audios",
|
250
|
+
font: "/fonts",
|
251
|
+
image: "/images",
|
252
|
+
javascript: "/javascripts",
|
253
|
+
stylesheet: "/stylesheets",
|
254
|
+
video: "/videos"
|
196
255
|
}
|
197
256
|
|
198
257
|
# Computes asset path to public directory. Plugins and
|
@@ -202,6 +261,7 @@ module ActionView
|
|
202
261
|
dir = ASSET_PUBLIC_DIRECTORIES[options[:type]] || ""
|
203
262
|
File.join(dir, source)
|
204
263
|
end
|
264
|
+
alias :public_compute_asset_path :compute_asset_path
|
205
265
|
|
206
266
|
# Pick an asset host for this source. Returns +nil+ if no host is set,
|
207
267
|
# the host if no wildcard is set, the host interpolated with the
|
@@ -213,19 +273,21 @@ module ActionView
|
|
213
273
|
host = options[:host]
|
214
274
|
host ||= config.asset_host if defined? config.asset_host
|
215
275
|
|
216
|
-
if host
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
276
|
+
if host
|
277
|
+
if host.respond_to?(:call)
|
278
|
+
arity = host.respond_to?(:arity) ? host.arity : host.method(:call).arity
|
279
|
+
args = [source]
|
280
|
+
args << request if request && (arity > 1 || arity < 0)
|
281
|
+
host = host.call(*args)
|
282
|
+
elsif host.include?("%d")
|
283
|
+
host = host % (Zlib.crc32(source) % 4)
|
284
|
+
end
|
223
285
|
end
|
224
286
|
|
225
287
|
host ||= request.base_url if request && options[:protocol] == :request
|
226
288
|
return unless host
|
227
289
|
|
228
|
-
if host
|
290
|
+
if URI_REGEXP.match?(host)
|
229
291
|
host
|
230
292
|
else
|
231
293
|
protocol = options[:protocol] || config.default_asset_host_protocol || (request ? :request : :relative)
|
@@ -251,7 +313,7 @@ module ActionView
|
|
251
313
|
# javascript_path "http://www.example.com/js/xmlhr" # => http://www.example.com/js/xmlhr
|
252
314
|
# javascript_path "http://www.example.com/js/xmlhr.js" # => http://www.example.com/js/xmlhr.js
|
253
315
|
def javascript_path(source, options = {})
|
254
|
-
path_to_asset(source, {type: :javascript}.merge!(options))
|
316
|
+
path_to_asset(source, { type: :javascript }.merge!(options))
|
255
317
|
end
|
256
318
|
alias_method :path_to_javascript, :javascript_path # aliased to avoid conflicts with a javascript_path named route
|
257
319
|
|
@@ -263,7 +325,7 @@ module ActionView
|
|
263
325
|
# javascript_url "js/xmlhr.js", host: "http://stage.example.com" # => http://stage.example.com/assets/dir/xmlhr.js
|
264
326
|
#
|
265
327
|
def javascript_url(source, options = {})
|
266
|
-
url_to_asset(source, {type: :javascript}.merge!(options))
|
328
|
+
url_to_asset(source, { type: :javascript }.merge!(options))
|
267
329
|
end
|
268
330
|
alias_method :url_to_javascript, :javascript_url # aliased to avoid conflicts with a javascript_url named route
|
269
331
|
|
@@ -278,7 +340,7 @@ module ActionView
|
|
278
340
|
# stylesheet_path "http://www.example.com/css/style" # => http://www.example.com/css/style
|
279
341
|
# stylesheet_path "http://www.example.com/css/style.css" # => http://www.example.com/css/style.css
|
280
342
|
def stylesheet_path(source, options = {})
|
281
|
-
path_to_asset(source, {type: :stylesheet}.merge!(options))
|
343
|
+
path_to_asset(source, { type: :stylesheet }.merge!(options))
|
282
344
|
end
|
283
345
|
alias_method :path_to_stylesheet, :stylesheet_path # aliased to avoid conflicts with a stylesheet_path named route
|
284
346
|
|
@@ -290,7 +352,7 @@ module ActionView
|
|
290
352
|
# stylesheet_url "css/style.css", host: "http://stage.example.com" # => http://stage.example.com/css/style.css
|
291
353
|
#
|
292
354
|
def stylesheet_url(source, options = {})
|
293
|
-
url_to_asset(source, {type: :stylesheet}.merge!(options))
|
355
|
+
url_to_asset(source, { type: :stylesheet }.merge!(options))
|
294
356
|
end
|
295
357
|
alias_method :url_to_stylesheet, :stylesheet_url # aliased to avoid conflicts with a stylesheet_url named route
|
296
358
|
|
@@ -308,7 +370,7 @@ module ActionView
|
|
308
370
|
# The alias +path_to_image+ is provided to avoid that. Rails uses the alias internally, and
|
309
371
|
# plugin authors are encouraged to do so.
|
310
372
|
def image_path(source, options = {})
|
311
|
-
path_to_asset(source, {type: :image}.merge!(options))
|
373
|
+
path_to_asset(source, { type: :image }.merge!(options))
|
312
374
|
end
|
313
375
|
alias_method :path_to_image, :image_path # aliased to avoid conflicts with an image_path named route
|
314
376
|
|
@@ -320,7 +382,7 @@ module ActionView
|
|
320
382
|
# image_url "edit.png", host: "http://stage.example.com" # => http://stage.example.com/edit.png
|
321
383
|
#
|
322
384
|
def image_url(source, options = {})
|
323
|
-
url_to_asset(source, {type: :image}.merge!(options))
|
385
|
+
url_to_asset(source, { type: :image }.merge!(options))
|
324
386
|
end
|
325
387
|
alias_method :url_to_image, :image_url # aliased to avoid conflicts with an image_url named route
|
326
388
|
|
@@ -334,7 +396,7 @@ module ActionView
|
|
334
396
|
# video_path("/trailers/hd.avi") # => /trailers/hd.avi
|
335
397
|
# video_path("http://www.example.com/vid/hd.avi") # => http://www.example.com/vid/hd.avi
|
336
398
|
def video_path(source, options = {})
|
337
|
-
path_to_asset(source, {type: :video}.merge!(options))
|
399
|
+
path_to_asset(source, { type: :video }.merge!(options))
|
338
400
|
end
|
339
401
|
alias_method :path_to_video, :video_path # aliased to avoid conflicts with a video_path named route
|
340
402
|
|
@@ -346,9 +408,9 @@ module ActionView
|
|
346
408
|
# video_url "hd.avi", host: "http://stage.example.com" # => http://stage.example.com/hd.avi
|
347
409
|
#
|
348
410
|
def video_url(source, options = {})
|
349
|
-
url_to_asset(source, {type: :video}.merge!(options))
|
411
|
+
url_to_asset(source, { type: :video }.merge!(options))
|
350
412
|
end
|
351
|
-
alias_method :url_to_video, :video_url # aliased to avoid conflicts with
|
413
|
+
alias_method :url_to_video, :video_url # aliased to avoid conflicts with a video_url named route
|
352
414
|
|
353
415
|
# Computes the path to an audio asset in the public audios directory.
|
354
416
|
# Full paths from the document root will be passed through.
|
@@ -360,7 +422,7 @@ module ActionView
|
|
360
422
|
# audio_path("/sounds/horse.wav") # => /sounds/horse.wav
|
361
423
|
# audio_path("http://www.example.com/sounds/horse.wav") # => http://www.example.com/sounds/horse.wav
|
362
424
|
def audio_path(source, options = {})
|
363
|
-
path_to_asset(source, {type: :audio}.merge!(options))
|
425
|
+
path_to_asset(source, { type: :audio }.merge!(options))
|
364
426
|
end
|
365
427
|
alias_method :path_to_audio, :audio_path # aliased to avoid conflicts with an audio_path named route
|
366
428
|
|
@@ -372,7 +434,7 @@ module ActionView
|
|
372
434
|
# audio_url "horse.wav", host: "http://stage.example.com" # => http://stage.example.com/horse.wav
|
373
435
|
#
|
374
436
|
def audio_url(source, options = {})
|
375
|
-
url_to_asset(source, {type: :audio}.merge!(options))
|
437
|
+
url_to_asset(source, { type: :audio }.merge!(options))
|
376
438
|
end
|
377
439
|
alias_method :url_to_audio, :audio_url # aliased to avoid conflicts with an audio_url named route
|
378
440
|
|
@@ -385,9 +447,9 @@ module ActionView
|
|
385
447
|
# font_path("/dir/font.ttf") # => /dir/font.ttf
|
386
448
|
# font_path("http://www.example.com/dir/font.ttf") # => http://www.example.com/dir/font.ttf
|
387
449
|
def font_path(source, options = {})
|
388
|
-
path_to_asset(source, {type: :font}.merge!(options))
|
450
|
+
path_to_asset(source, { type: :font }.merge!(options))
|
389
451
|
end
|
390
|
-
alias_method :path_to_font, :font_path # aliased to avoid conflicts with
|
452
|
+
alias_method :path_to_font, :font_path # aliased to avoid conflicts with a font_path named route
|
391
453
|
|
392
454
|
# Computes the full URL to a font asset.
|
393
455
|
# This will use +font_path+ internally, so most of their behaviors will be the same.
|
@@ -397,9 +459,9 @@ module ActionView
|
|
397
459
|
# font_url "font.ttf", host: "http://stage.example.com" # => http://stage.example.com/font.ttf
|
398
460
|
#
|
399
461
|
def font_url(source, options = {})
|
400
|
-
url_to_asset(source, {type: :font}.merge!(options))
|
462
|
+
url_to_asset(source, { type: :font }.merge!(options))
|
401
463
|
end
|
402
|
-
alias_method :url_to_font, :font_url # aliased to avoid conflicts with
|
464
|
+
alias_method :url_to_font, :font_url # aliased to avoid conflicts with a font_url named route
|
403
465
|
end
|
404
466
|
end
|
405
467
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "set"
|
2
2
|
|
3
3
|
module ActionView
|
4
4
|
# = Action View Atom Feed Helpers
|
@@ -103,7 +103,7 @@ module ActionView
|
|
103
103
|
xml = options.delete(:xml) || eval("xml", block.binding)
|
104
104
|
xml.instruct!
|
105
105
|
if options[:instruct]
|
106
|
-
options[:instruct].each do |target,attrs|
|
106
|
+
options[:instruct].each do |target, attrs|
|
107
107
|
if attrs.respond_to?(:keys)
|
108
108
|
xml.instruct!(target, attrs)
|
109
109
|
elsif attrs.respond_to?(:each)
|
@@ -112,13 +112,13 @@ module ActionView
|
|
112
112
|
end
|
113
113
|
end
|
114
114
|
|
115
|
-
feed_opts = {"xml:lang" => options[:language] || "en-US", "xmlns" =>
|
116
|
-
feed_opts.merge!(options).reject!{|k,v| !k.to_s.match(/^xml/)}
|
115
|
+
feed_opts = { "xml:lang" => options[:language] || "en-US", "xmlns" => "http://www.w3.org/2005/Atom" }
|
116
|
+
feed_opts.merge!(options).reject! { |k, v| !k.to_s.match(/^xml/) }
|
117
117
|
|
118
118
|
xml.feed(feed_opts) do
|
119
119
|
xml.id(options[:id] || "tag:#{request.host},#{options[:schema_date]}:#{request.fullpath.split(".")[0]}")
|
120
|
-
xml.link(:
|
121
|
-
xml.link(:
|
120
|
+
xml.link(rel: "alternate", type: "text/html", href: options[:root_url] || (request.protocol + request.host_with_port))
|
121
|
+
xml.link(rel: "self", type: "application/atom+xml", href: options[:url] || request.url)
|
122
122
|
|
123
123
|
yield AtomFeedBuilder.new(xml, self, options)
|
124
124
|
end
|
@@ -138,7 +138,7 @@ module ActionView
|
|
138
138
|
def method_missing(method, *arguments, &block)
|
139
139
|
if xhtml_block?(method, arguments)
|
140
140
|
@xml.__send__(method, *arguments) do
|
141
|
-
@xml.div(:
|
141
|
+
@xml.div(xmlns: "http://www.w3.org/1999/xhtml") do |xhtml|
|
142
142
|
block.call(xhtml)
|
143
143
|
end
|
144
144
|
end
|
@@ -153,7 +153,7 @@ module ActionView
|
|
153
153
|
def xhtml_block?(method, arguments)
|
154
154
|
if XHTML_TAG_NAMES.include?(method.to_s)
|
155
155
|
last = arguments.last
|
156
|
-
last.is_a?(Hash) && last[:type].to_s ==
|
156
|
+
last.is_a?(Hash) && last[:type].to_s == "xhtml"
|
157
157
|
end
|
158
158
|
end
|
159
159
|
end
|
@@ -163,7 +163,7 @@ module ActionView
|
|
163
163
|
@xml, @view, @feed_options = xml, view, feed_options
|
164
164
|
end
|
165
165
|
|
166
|
-
# Accepts a Date or Time object and inserts it in the proper format. If nil is passed, current time in UTC is used.
|
166
|
+
# Accepts a Date or Time object and inserts it in the proper format. If +nil+ is passed, current time in UTC is used.
|
167
167
|
def updated(date_or_time = nil)
|
168
168
|
@xml.updated((date_or_time || Time.now.utc).xmlschema)
|
169
169
|
end
|
@@ -174,7 +174,7 @@ module ActionView
|
|
174
174
|
#
|
175
175
|
# * <tt>:published</tt>: Time first published. Defaults to the created_at attribute on the record if one such exists.
|
176
176
|
# * <tt>:updated</tt>: Time of update. Defaults to the updated_at attribute on the record if one such exists.
|
177
|
-
# * <tt>:url</tt>: The URL for this entry or false or nil for not having a link tag. Defaults to the polymorphic_url for the record.
|
177
|
+
# * <tt>:url</tt>: The URL for this entry or +false+ or +nil+ for not having a link tag. Defaults to the +polymorphic_url+ for the record.
|
178
178
|
# * <tt>:id</tt>: The ID for this entry. Defaults to "tag:#{@view.request.host},#{@feed_options[:schema_date]}:#{record.class}/#{record.id}"
|
179
179
|
# * <tt>:type</tt>: The TYPE for this entry. Defaults to "text/html".
|
180
180
|
def entry(record, options = {})
|
@@ -189,16 +189,15 @@ module ActionView
|
|
189
189
|
@xml.updated((options[:updated] || record.updated_at).xmlschema)
|
190
190
|
end
|
191
191
|
|
192
|
-
type = options.fetch(:type,
|
192
|
+
type = options.fetch(:type, "text/html")
|
193
193
|
|
194
194
|
url = options.fetch(:url) { @view.polymorphic_url(record) }
|
195
|
-
@xml.link(:
|
195
|
+
@xml.link(rel: "alternate", type: type, href: url) if url
|
196
196
|
|
197
197
|
yield AtomBuilder.new(@xml)
|
198
198
|
end
|
199
199
|
end
|
200
200
|
end
|
201
|
-
|
202
201
|
end
|
203
202
|
end
|
204
203
|
end
|
@@ -41,11 +41,11 @@ module ActionView
|
|
41
41
|
#
|
42
42
|
# ==== \Template digest
|
43
43
|
#
|
44
|
-
# The template digest that's added to the cache key is computed by taking an
|
44
|
+
# The template digest that's added to the cache key is computed by taking an MD5 of the
|
45
45
|
# contents of the entire template file. This ensures that your caches will automatically
|
46
46
|
# expire when you change the template file.
|
47
47
|
#
|
48
|
-
# Note that the
|
48
|
+
# Note that the MD5 is taken of the entire template file, not just what's within the
|
49
49
|
# cache do/end call. So it's possible that changing something outside of that call will
|
50
50
|
# still expire the cache.
|
51
51
|
#
|
@@ -69,11 +69,11 @@ module ActionView
|
|
69
69
|
# render 'comments/comments'
|
70
70
|
# render('comments/comments')
|
71
71
|
#
|
72
|
-
# render "header"
|
72
|
+
# render "header" translates to render("comments/header")
|
73
73
|
#
|
74
|
-
# render(@topic)
|
75
|
-
# render(topics)
|
76
|
-
# render(message.topics)
|
74
|
+
# render(@topic) translates to render("topics/topic")
|
75
|
+
# render(topics) translates to render("topics/topic")
|
76
|
+
# render(message.topics) translates to render("topics/topic")
|
77
77
|
#
|
78
78
|
# It's not possible to derive all render calls like that, though.
|
79
79
|
# Here are a few examples of things that can't be derived:
|
@@ -88,7 +88,7 @@ module ActionView
|
|
88
88
|
#
|
89
89
|
# === Explicit dependencies
|
90
90
|
#
|
91
|
-
#
|
91
|
+
# Sometimes you'll have template dependencies that can't be derived at all. This is typically
|
92
92
|
# the case when you have template rendering that happens in helpers. Here's an example:
|
93
93
|
#
|
94
94
|
# <%= render_sortable_todolists @project.todolists %>
|
@@ -118,7 +118,7 @@ module ActionView
|
|
118
118
|
#
|
119
119
|
# If you use a helper method, for example, inside a cached block and
|
120
120
|
# you then update that helper, you'll have to bump the cache as well.
|
121
|
-
# It doesn't really matter how you do it, but the
|
121
|
+
# It doesn't really matter how you do it, but the MD5 of the template file
|
122
122
|
# must change. One recommendation is to simply be explicit in a comment, like:
|
123
123
|
#
|
124
124
|
# <%# Helper Dependency Updated: May 6, 2012 at 6pm %>
|
@@ -130,9 +130,10 @@ module ActionView
|
|
130
130
|
#
|
131
131
|
# When rendering a collection of objects that each use the same partial, a `cached`
|
132
132
|
# option can be passed.
|
133
|
+
#
|
133
134
|
# For collections rendered such:
|
134
135
|
#
|
135
|
-
# <%= render partial: '
|
136
|
+
# <%= render partial: 'projects/project', collection: @projects, cached: true %>
|
136
137
|
#
|
137
138
|
# The `cached: true` will make Action View's rendering read several templates
|
138
139
|
# from cache at once instead of one call per template.
|
@@ -142,13 +143,21 @@ module ActionView
|
|
142
143
|
# Works great alongside individual template fragment caching.
|
143
144
|
# For instance if the template the collection renders is cached like:
|
144
145
|
#
|
145
|
-
# #
|
146
|
-
# <% cache
|
146
|
+
# # projects/_project.html.erb
|
147
|
+
# <% cache project do %>
|
147
148
|
# <%# ... %>
|
148
149
|
# <% end %>
|
149
150
|
#
|
150
151
|
# Any collection renders will find those cached templates when attempting
|
151
152
|
# to read multiple templates at once.
|
153
|
+
#
|
154
|
+
# If your collection cache depends on multiple sources (try to avoid this to keep things simple),
|
155
|
+
# you can name all these dependencies as part of a block that returns an array:
|
156
|
+
#
|
157
|
+
# <%= render partial: 'projects/project', collection: @projects, cached: -> project { [ project, current_user ] } %>
|
158
|
+
#
|
159
|
+
# This will include both records as part of the cache key and updating either of them will
|
160
|
+
# expire the cache.
|
152
161
|
def cache(name = {}, options = {}, &block)
|
153
162
|
if controller.respond_to?(:perform_caching) && controller.perform_caching
|
154
163
|
name_options = options.slice(:skip_digest, :virtual_path)
|
@@ -202,12 +211,14 @@ module ActionView
|
|
202
211
|
end
|
203
212
|
end
|
204
213
|
|
214
|
+
attr_reader :cache_hit # :nodoc:
|
215
|
+
|
205
216
|
private
|
206
217
|
|
207
|
-
def fragment_name_with_digest(name, virtual_path)
|
218
|
+
def fragment_name_with_digest(name, virtual_path)
|
208
219
|
virtual_path ||= @virtual_path
|
209
220
|
if virtual_path
|
210
|
-
name
|
221
|
+
name = controller.url_for(name).split("://").last if name.is_a?(Hash)
|
211
222
|
digest = Digestor.digest name: virtual_path, finder: lookup_context, dependencies: view_cache_dependencies
|
212
223
|
[ name, digest ]
|
213
224
|
else
|
@@ -215,18 +226,21 @@ module ActionView
|
|
215
226
|
end
|
216
227
|
end
|
217
228
|
|
218
|
-
|
219
|
-
|
220
|
-
|
229
|
+
def fragment_for(name = {}, options = nil, &block)
|
230
|
+
if content = read_fragment_for(name, options)
|
231
|
+
@cache_hit = true
|
232
|
+
content
|
233
|
+
else
|
234
|
+
@cache_hit = false
|
235
|
+
write_fragment_for(name, options, &block)
|
236
|
+
end
|
221
237
|
end
|
222
238
|
|
223
|
-
def read_fragment_for(name, options)
|
239
|
+
def read_fragment_for(name, options)
|
224
240
|
controller.read_fragment(name, options)
|
225
241
|
end
|
226
242
|
|
227
|
-
def write_fragment_for(name, options)
|
228
|
-
# VIEW TODO: Make #capture usable outside of ERB
|
229
|
-
# This dance is needed because Builder can't use capture
|
243
|
+
def write_fragment_for(name, options)
|
230
244
|
pos = output_buffer.length
|
231
245
|
yield
|
232
246
|
output_safe = output_buffer.html_safe?
|