actionview 4.2.11.1 → 5.2.4.2
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 +4 -4
- data/CHANGELOG.md +89 -282
- data/MIT-LICENSE +1 -1
- data/README.rdoc +5 -6
- data/lib/action_view/base.rb +38 -28
- data/lib/action_view/buffers.rb +3 -1
- data/lib/action_view/context.rb +3 -3
- data/lib/action_view/dependency_tracker.rb +54 -20
- data/lib/action_view/digestor.rb +94 -83
- data/lib/action_view/flows.rb +11 -11
- data/lib/action_view/gem_version.rb +5 -3
- data/lib/action_view/helpers/active_model_helper.rb +17 -11
- data/lib/action_view/helpers/asset_tag_helper.rb +244 -62
- data/lib/action_view/helpers/asset_url_helper.rb +170 -67
- data/lib/action_view/helpers/atom_feed_helper.rb +19 -17
- data/lib/action_view/helpers/cache_helper.rb +105 -42
- data/lib/action_view/helpers/capture_helper.rb +16 -13
- data/lib/action_view/helpers/controller_helper.rb +15 -4
- data/lib/action_view/helpers/csp_helper.rb +24 -0
- data/lib/action_view/helpers/csrf_helper.rb +7 -5
- data/lib/action_view/helpers/date_helper.rb +170 -112
- data/lib/action_view/helpers/debug_helper.rb +7 -6
- data/lib/action_view/helpers/form_helper.rb +521 -127
- data/lib/action_view/helpers/form_options_helper.rb +109 -63
- data/lib/action_view/helpers/form_tag_helper.rb +110 -67
- data/lib/action_view/helpers/javascript_helper.rb +27 -12
- data/lib/action_view/helpers/number_helper.rb +77 -58
- data/lib/action_view/helpers/output_safety_helper.rb +36 -4
- data/lib/action_view/helpers/record_tag_helper.rb +14 -99
- data/lib/action_view/helpers/rendering_helper.rb +6 -5
- data/lib/action_view/helpers/sanitize_helper.rb +20 -15
- data/lib/action_view/helpers/tag_helper.rb +198 -73
- data/lib/action_view/helpers/tags/base.rb +134 -97
- data/lib/action_view/helpers/tags/check_box.rb +20 -18
- data/lib/action_view/helpers/tags/checkable.rb +4 -2
- data/lib/action_view/helpers/tags/collection_check_boxes.rb +12 -33
- data/lib/action_view/helpers/tags/collection_helpers.rb +70 -36
- data/lib/action_view/helpers/tags/collection_radio_buttons.rb +6 -11
- data/lib/action_view/helpers/tags/collection_select.rb +4 -2
- data/lib/action_view/helpers/tags/color_field.rb +3 -1
- data/lib/action_view/helpers/tags/date_field.rb +2 -0
- data/lib/action_view/helpers/tags/date_select.rb +38 -36
- data/lib/action_view/helpers/tags/datetime_field.rb +4 -2
- data/lib/action_view/helpers/tags/datetime_local_field.rb +2 -0
- data/lib/action_view/helpers/tags/datetime_select.rb +2 -0
- data/lib/action_view/helpers/tags/email_field.rb +2 -0
- data/lib/action_view/helpers/tags/file_field.rb +2 -0
- data/lib/action_view/helpers/tags/grouped_collection_select.rb +4 -2
- data/lib/action_view/helpers/tags/hidden_field.rb +2 -0
- data/lib/action_view/helpers/tags/label.rb +3 -1
- data/lib/action_view/helpers/tags/month_field.rb +2 -0
- data/lib/action_view/helpers/tags/number_field.rb +2 -0
- data/lib/action_view/helpers/tags/password_field.rb +3 -1
- data/lib/action_view/helpers/tags/placeholderable.rb +3 -1
- data/lib/action_view/helpers/tags/radio_button.rb +7 -5
- data/lib/action_view/helpers/tags/range_field.rb +2 -0
- data/lib/action_view/helpers/tags/search_field.rb +14 -9
- data/lib/action_view/helpers/tags/select.rb +11 -9
- data/lib/action_view/helpers/tags/tel_field.rb +2 -0
- data/lib/action_view/helpers/tags/text_area.rb +4 -2
- data/lib/action_view/helpers/tags/text_field.rb +8 -7
- data/lib/action_view/helpers/tags/time_field.rb +2 -0
- data/lib/action_view/helpers/tags/time_select.rb +2 -0
- data/lib/action_view/helpers/tags/time_zone_select.rb +3 -1
- data/lib/action_view/helpers/tags/translator.rb +17 -13
- data/lib/action_view/helpers/tags/url_field.rb +2 -0
- data/lib/action_view/helpers/tags/week_field.rb +2 -0
- data/lib/action_view/helpers/tags.rb +3 -1
- data/lib/action_view/helpers/text_helper.rb +55 -36
- data/lib/action_view/helpers/translation_helper.rb +62 -31
- data/lib/action_view/helpers/url_helper.rb +159 -104
- data/lib/action_view/helpers.rb +5 -1
- data/lib/action_view/layouts.rb +65 -58
- data/lib/action_view/log_subscriber.rb +60 -8
- data/lib/action_view/lookup_context.rb +80 -65
- data/lib/action_view/model_naming.rb +3 -1
- data/lib/action_view/path_set.rb +30 -19
- data/lib/action_view/railtie.rb +39 -6
- data/lib/action_view/record_identifier.rb +53 -25
- data/lib/action_view/renderer/abstract_renderer.rb +21 -15
- data/lib/action_view/renderer/partial_renderer/collection_caching.rb +57 -0
- data/lib/action_view/renderer/partial_renderer.rb +218 -214
- data/lib/action_view/renderer/renderer.rb +8 -6
- data/lib/action_view/renderer/streaming_template_renderer.rb +50 -48
- data/lib/action_view/renderer/template_renderer.rb +67 -66
- data/lib/action_view/rendering.rb +19 -14
- data/lib/action_view/routing_url_for.rb +27 -17
- data/lib/action_view/tasks/cache_digests.rake +25 -0
- data/lib/action_view/template/error.rb +16 -16
- data/lib/action_view/template/handlers/builder.rb +10 -11
- data/lib/action_view/template/handlers/erb/erubi.rb +83 -0
- data/lib/action_view/template/handlers/erb.rb +9 -80
- data/lib/action_view/template/handlers/html.rb +11 -0
- data/lib/action_view/template/handlers/raw.rb +3 -3
- data/lib/action_view/template/handlers.rb +11 -7
- data/lib/action_view/template/html.rb +5 -5
- data/lib/action_view/template/resolver.rb +140 -115
- data/lib/action_view/template/text.rb +8 -9
- data/lib/action_view/template/types.rb +18 -18
- data/lib/action_view/template.rb +56 -31
- data/lib/action_view/test_case.rb +50 -29
- data/lib/action_view/testing/resolvers.rb +31 -31
- data/lib/action_view/version.rb +3 -1
- data/lib/action_view/view_paths.rb +28 -34
- data/lib/action_view.rb +8 -7
- data/lib/assets/compiled/rails-ujs.js +720 -0
- metadata +25 -24
- data/lib/action_view/tasks/dependencies.rake +0 -23
data/lib/action_view/layouts.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "action_view/rendering"
|
2
|
-
require "active_support/core_ext/module/
|
4
|
+
require "active_support/core_ext/module/redefine_method"
|
3
5
|
|
4
6
|
module ActionView
|
5
7
|
# Layouts reverse the common pattern of including shared headers and footers in many templates to isolate changes in
|
@@ -91,16 +93,16 @@ module ActionView
|
|
91
93
|
# layout false
|
92
94
|
#
|
93
95
|
# In these examples, we have three implicit lookup scenarios:
|
94
|
-
# * The BankController uses the "bank" layout.
|
95
|
-
# * The ExchangeController uses the "exchange" layout.
|
96
|
-
# * The CurrencyController inherits the layout from BankController.
|
96
|
+
# * The +BankController+ uses the "bank" layout.
|
97
|
+
# * The +ExchangeController+ uses the "exchange" layout.
|
98
|
+
# * The +CurrencyController+ inherits the layout from BankController.
|
97
99
|
#
|
98
100
|
# However, when a layout is explicitly set, the explicitly set layout wins:
|
99
|
-
# * The InformationController uses the "information" layout, explicitly set.
|
100
|
-
# * The TellerController also uses the "information" layout, because the parent explicitly set it.
|
101
|
-
# * The EmployeeController uses the "employee" layout, because it set the layout to nil
|
102
|
-
# * The VaultController chooses a layout dynamically by calling the <tt>access_level_layout</tt> method.
|
103
|
-
# * The TillController does not use a layout at all.
|
101
|
+
# * The +InformationController+ uses the "information" layout, explicitly set.
|
102
|
+
# * The +TellerController+ also uses the "information" layout, because the parent explicitly set it.
|
103
|
+
# * The +EmployeeController+ uses the "employee" layout, because it set the layout to +nil+, resetting the parent configuration.
|
104
|
+
# * The +VaultController+ chooses a layout dynamically by calling the <tt>access_level_layout</tt> method.
|
105
|
+
# * The +TillController+ does not use a layout at all.
|
104
106
|
#
|
105
107
|
# == Types of layouts
|
106
108
|
#
|
@@ -148,8 +150,8 @@ module ActionView
|
|
148
150
|
# The template will be looked always in <tt>app/views/layouts/</tt> folder. But you can point
|
149
151
|
# <tt>layouts</tt> folder direct also. <tt>layout "layouts/demo"</tt> is the same as <tt>layout "demo"</tt>.
|
150
152
|
#
|
151
|
-
# Setting the layout to nil forces it to be looked up in the filesystem and fallbacks to the parent behavior if none exists.
|
152
|
-
# Setting it to nil is useful to re-enable template lookup overriding a previous configuration set in the parent:
|
153
|
+
# Setting the layout to +nil+ forces it to be looked up in the filesystem and fallbacks to the parent behavior if none exists.
|
154
|
+
# Setting it to +nil+ is useful to re-enable template lookup overriding a previous configuration set in the parent:
|
153
155
|
#
|
154
156
|
# class ApplicationController < ActionController::Base
|
155
157
|
# layout "application"
|
@@ -204,9 +206,9 @@ module ActionView
|
|
204
206
|
include ActionView::Rendering
|
205
207
|
|
206
208
|
included do
|
207
|
-
class_attribute :_layout, :
|
208
|
-
|
209
|
-
|
209
|
+
class_attribute :_layout, instance_accessor: false
|
210
|
+
class_attribute :_layout_conditions, instance_accessor: false, default: {}
|
211
|
+
|
210
212
|
_write_layout_method
|
211
213
|
end
|
212
214
|
|
@@ -223,36 +225,39 @@ module ActionView
|
|
223
225
|
module LayoutConditions # :nodoc:
|
224
226
|
private
|
225
227
|
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
228
|
+
# Determines whether the current action has a layout definition by
|
229
|
+
# checking the action name against the :only and :except conditions
|
230
|
+
# set by the <tt>layout</tt> method.
|
231
|
+
#
|
232
|
+
# ==== Returns
|
233
|
+
# * <tt>Boolean</tt> - True if the action has a layout definition, false otherwise.
|
234
|
+
def _conditional_layout?
|
235
|
+
return unless super
|
236
|
+
|
237
|
+
conditions = _layout_conditions
|
238
|
+
|
239
|
+
if only = conditions[:only]
|
240
|
+
only.include?(action_name)
|
241
|
+
elsif except = conditions[:except]
|
242
|
+
!except.include?(action_name)
|
243
|
+
else
|
244
|
+
true
|
245
|
+
end
|
243
246
|
end
|
244
|
-
end
|
245
247
|
end
|
246
248
|
|
247
249
|
# Specify the layout to use for this class.
|
248
250
|
#
|
249
251
|
# If the specified layout is a:
|
250
252
|
# String:: the String is the template name
|
251
|
-
# Symbol:: call the method specified by the symbol
|
253
|
+
# Symbol:: call the method specified by the symbol
|
254
|
+
# Proc:: call the passed Proc
|
252
255
|
# false:: There is no layout
|
253
256
|
# true:: raise an ArgumentError
|
254
257
|
# nil:: Force default layout behavior with inheritance
|
255
258
|
#
|
259
|
+
# Return value of +Proc+ and +Symbol+ arguments should be +String+, +false+, +true+ or +nil+
|
260
|
+
# with the same meaning as described above.
|
256
261
|
# ==== Parameters
|
257
262
|
# * <tt>layout</tt> - The layout to use.
|
258
263
|
#
|
@@ -262,7 +267,7 @@ module ActionView
|
|
262
267
|
def layout(layout, conditions = {})
|
263
268
|
include LayoutConditions unless conditions.empty?
|
264
269
|
|
265
|
-
conditions.each {|k, v| conditions[k] = Array(v).map
|
270
|
+
conditions.each { |k, v| conditions[k] = Array(v).map(&:to_s) }
|
266
271
|
self._layout_conditions = conditions
|
267
272
|
|
268
273
|
self._layout = layout
|
@@ -274,10 +279,10 @@ module ActionView
|
|
274
279
|
# If a layout is not explicitly mentioned then look for a layout with the controller's name.
|
275
280
|
# if nothing is found then try same procedure to find super class's layout.
|
276
281
|
def _write_layout_method # :nodoc:
|
277
|
-
|
282
|
+
silence_redefinition_of_method(:_layout)
|
278
283
|
|
279
|
-
prefixes
|
280
|
-
default_behavior = "lookup_context.find_all('#{_implied_layout_name}', #{prefixes.inspect}).first || super"
|
284
|
+
prefixes = /\blayouts/.match?(_implied_layout_name) ? [] : ["layouts"]
|
285
|
+
default_behavior = "lookup_context.find_all('#{_implied_layout_name}', #{prefixes.inspect}, false, [], { formats: formats }).first || super"
|
281
286
|
name_clause = if name
|
282
287
|
default_behavior
|
283
288
|
else
|
@@ -286,7 +291,8 @@ module ActionView
|
|
286
291
|
RUBY
|
287
292
|
end
|
288
293
|
|
289
|
-
layout_definition =
|
294
|
+
layout_definition = \
|
295
|
+
case _layout
|
290
296
|
when String
|
291
297
|
_layout.inspect
|
292
298
|
when Symbol
|
@@ -313,10 +319,10 @@ module ActionView
|
|
313
319
|
raise ArgumentError, "Layouts must be specified as a String, Symbol, Proc, false, or nil"
|
314
320
|
when nil
|
315
321
|
name_clause
|
316
|
-
|
322
|
+
end
|
317
323
|
|
318
|
-
|
319
|
-
def _layout
|
324
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
325
|
+
def _layout(formats)
|
320
326
|
if _conditional_layout?
|
321
327
|
#{layout_definition}
|
322
328
|
else
|
@@ -329,14 +335,14 @@ module ActionView
|
|
329
335
|
|
330
336
|
private
|
331
337
|
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
338
|
+
# If no layout is supplied, look for a template named the return
|
339
|
+
# value of this method.
|
340
|
+
#
|
341
|
+
# ==== Returns
|
342
|
+
# * <tt>String</tt> - A template name
|
343
|
+
def _implied_layout_name
|
344
|
+
controller_path
|
345
|
+
end
|
340
346
|
end
|
341
347
|
|
342
348
|
def _normalize_options(options) # :nodoc:
|
@@ -372,7 +378,7 @@ module ActionView
|
|
372
378
|
end
|
373
379
|
|
374
380
|
# This will be overwritten by _write_layout_method
|
375
|
-
def _layout; end
|
381
|
+
def _layout(*); end
|
376
382
|
|
377
383
|
# Determine the layout for a given name, taking into account the name type.
|
378
384
|
#
|
@@ -382,8 +388,8 @@ module ActionView
|
|
382
388
|
case name
|
383
389
|
when String then _normalize_layout(name)
|
384
390
|
when Proc then name
|
385
|
-
when true then Proc.new { _default_layout(true) }
|
386
|
-
when :default then Proc.new { _default_layout(false) }
|
391
|
+
when true then Proc.new { |formats| _default_layout(formats, true) }
|
392
|
+
when :default then Proc.new { |formats| _default_layout(formats, false) }
|
387
393
|
when false, nil then nil
|
388
394
|
else
|
389
395
|
raise ArgumentError,
|
@@ -399,14 +405,15 @@ module ActionView
|
|
399
405
|
# Optionally raises an exception if the layout could not be found.
|
400
406
|
#
|
401
407
|
# ==== Parameters
|
402
|
-
# * <tt>
|
403
|
-
#
|
408
|
+
# * <tt>formats</tt> - The formats accepted to this layout
|
409
|
+
# * <tt>require_layout</tt> - If set to +true+ and layout is not found,
|
410
|
+
# an +ArgumentError+ exception is raised (defaults to +false+)
|
404
411
|
#
|
405
412
|
# ==== Returns
|
406
|
-
# * <tt>template</tt> - The template object for the default layout (or nil)
|
407
|
-
def _default_layout(require_layout = false)
|
413
|
+
# * <tt>template</tt> - The template object for the default layout (or +nil+)
|
414
|
+
def _default_layout(formats, require_layout = false)
|
408
415
|
begin
|
409
|
-
value = _layout if action_has_layout?
|
416
|
+
value = _layout(formats) if action_has_layout?
|
410
417
|
rescue NameError => e
|
411
418
|
raise e, "Could not render layout: #{e.message}"
|
412
419
|
end
|
@@ -420,7 +427,7 @@ module ActionView
|
|
420
427
|
end
|
421
428
|
|
422
429
|
def _include_layout?(options)
|
423
|
-
(options.keys & [:body, :
|
430
|
+
(options.keys & [:body, :plain, :html, :inline, :partial]).empty? || options.key?(:layout)
|
424
431
|
end
|
425
432
|
end
|
426
433
|
end
|
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/log_subscriber"
|
2
4
|
|
3
5
|
module ActionView
|
4
6
|
# = Action View Log Subscriber
|
@@ -14,30 +16,80 @@ module ActionView
|
|
14
16
|
|
15
17
|
def render_template(event)
|
16
18
|
info do
|
17
|
-
message = " Rendered #{from_rails_root(event.payload[:identifier])}"
|
19
|
+
message = " Rendered #{from_rails_root(event.payload[:identifier])}".dup
|
20
|
+
message << " within #{from_rails_root(event.payload[:layout])}" if event.payload[:layout]
|
21
|
+
message << " (#{event.duration.round(1)}ms)"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def render_partial(event)
|
26
|
+
info do
|
27
|
+
message = " Rendered #{from_rails_root(event.payload[:identifier])}".dup
|
18
28
|
message << " within #{from_rails_root(event.payload[:layout])}" if event.payload[:layout]
|
19
29
|
message << " (#{event.duration.round(1)}ms)"
|
30
|
+
message << " #{cache_message(event.payload)}" unless event.payload[:cache_hit].nil?
|
31
|
+
message
|
20
32
|
end
|
21
33
|
end
|
22
|
-
|
23
|
-
|
34
|
+
|
35
|
+
def render_collection(event)
|
36
|
+
identifier = event.payload[:identifier] || "templates"
|
37
|
+
|
38
|
+
info do
|
39
|
+
" Rendered collection of #{from_rails_root(identifier)}" \
|
40
|
+
" #{render_count(event.payload)} (#{event.duration.round(1)}ms)"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def start(name, id, payload)
|
45
|
+
if name == "render_template.action_view"
|
46
|
+
log_rendering_start(payload)
|
47
|
+
end
|
48
|
+
|
49
|
+
super
|
50
|
+
end
|
24
51
|
|
25
52
|
def logger
|
26
53
|
ActionView::Base.logger
|
27
54
|
end
|
28
55
|
|
29
|
-
|
56
|
+
private
|
30
57
|
|
31
|
-
EMPTY =
|
32
|
-
def from_rails_root(string)
|
58
|
+
EMPTY = ""
|
59
|
+
def from_rails_root(string) # :doc:
|
33
60
|
string = string.sub(rails_root, EMPTY)
|
34
61
|
string.sub!(VIEWS_PATTERN, EMPTY)
|
35
62
|
string
|
36
63
|
end
|
37
64
|
|
38
|
-
def rails_root
|
65
|
+
def rails_root # :doc:
|
39
66
|
@root ||= "#{Rails.root}/"
|
40
67
|
end
|
68
|
+
|
69
|
+
def render_count(payload) # :doc:
|
70
|
+
if payload[:cache_hits]
|
71
|
+
"[#{payload[:cache_hits]} / #{payload[:count]} cache hits]"
|
72
|
+
else
|
73
|
+
"[#{payload[:count]} times]"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def cache_message(payload) # :doc:
|
78
|
+
case payload[:cache_hit]
|
79
|
+
when :hit
|
80
|
+
"[cache hit]"
|
81
|
+
when :miss
|
82
|
+
"[cache miss]"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def log_rendering_start(payload)
|
87
|
+
info do
|
88
|
+
message = " Rendering #{from_rails_root(payload[:identifier])}".dup
|
89
|
+
message << " within #{from_rails_root(payload[:layout])}" if payload[:layout]
|
90
|
+
message
|
91
|
+
end
|
92
|
+
end
|
41
93
|
end
|
42
94
|
end
|
43
95
|
|
@@ -1,27 +1,28 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "concurrent/map"
|
4
|
+
require "active_support/core_ext/module/remove_method"
|
5
|
+
require "active_support/core_ext/module/attribute_accessors"
|
6
|
+
require "action_view/template/resolver"
|
5
7
|
|
6
8
|
module ActionView
|
7
9
|
# = Action View Lookup Context
|
8
10
|
#
|
9
|
-
# LookupContext is the object responsible
|
10
|
-
# templates, i.e. view paths and details.
|
11
|
-
#
|
12
|
-
#
|
11
|
+
# <tt>LookupContext</tt> is the object responsible for holding all information
|
12
|
+
# required for looking up templates, i.e. view paths and details.
|
13
|
+
# <tt>LookupContext</tt> is also responsible for generating a key, given to
|
14
|
+
# view paths, used in the resolver cache lookup. Since this key is generated
|
15
|
+
# only once during the request, it speeds up all cache accesses.
|
13
16
|
class LookupContext #:nodoc:
|
14
17
|
attr_accessor :prefixes, :rendered_format
|
15
18
|
|
16
|
-
mattr_accessor :fallbacks
|
17
|
-
@@fallbacks = FallbackFileSystemResolver.instances
|
19
|
+
mattr_accessor :fallbacks, default: FallbackFileSystemResolver.instances
|
18
20
|
|
19
|
-
mattr_accessor :registered_details
|
20
|
-
self.registered_details = []
|
21
|
+
mattr_accessor :registered_details, default: []
|
21
22
|
|
22
|
-
def self.register_detail(name,
|
23
|
-
|
24
|
-
|
23
|
+
def self.register_detail(name, &block)
|
24
|
+
registered_details << name
|
25
|
+
Accessors::DEFAULT_PROCS[name] = block
|
25
26
|
|
26
27
|
Accessors.send :define_method, :"default_#{name}", &block
|
27
28
|
Accessors.module_eval <<-METHOD, __FILE__, __LINE__ + 1
|
@@ -33,16 +34,12 @@ module ActionView
|
|
33
34
|
value = value.present? ? Array(value) : default_#{name}
|
34
35
|
_set_detail(:#{name}, value) if value != @details[:#{name}]
|
35
36
|
end
|
36
|
-
|
37
|
-
remove_possible_method :initialize_details
|
38
|
-
def initialize_details(details)
|
39
|
-
#{initialize.join("\n")}
|
40
|
-
end
|
41
37
|
METHOD
|
42
38
|
end
|
43
39
|
|
44
40
|
# Holds accessors for the registered details.
|
45
41
|
module Accessors #:nodoc:
|
42
|
+
DEFAULT_PROCS = {}
|
46
43
|
end
|
47
44
|
|
48
45
|
register_detail(:locale) do
|
@@ -54,29 +51,27 @@ module ActionView
|
|
54
51
|
end
|
55
52
|
register_detail(:formats) { ActionView::Base.default_formats || [:html, :text, :js, :css, :xml, :json] }
|
56
53
|
register_detail(:variants) { [] }
|
57
|
-
register_detail(:handlers){ Template::Handlers.extensions }
|
54
|
+
register_detail(:handlers) { Template::Handlers.extensions }
|
58
55
|
|
59
56
|
class DetailsKey #:nodoc:
|
60
57
|
alias :eql? :equal?
|
61
|
-
alias :object_hash :hash
|
62
58
|
|
63
|
-
|
64
|
-
@details_keys = ThreadSafe::Cache.new
|
59
|
+
@details_keys = Concurrent::Map.new
|
65
60
|
|
66
61
|
def self.get(details)
|
67
62
|
if details[:formats]
|
68
63
|
details = details.dup
|
69
|
-
details[:formats] &=
|
64
|
+
details[:formats] &= Template::Types.symbols
|
70
65
|
end
|
71
|
-
@details_keys[details] ||= new
|
66
|
+
@details_keys[details] ||= Concurrent::Map.new
|
72
67
|
end
|
73
68
|
|
74
69
|
def self.clear
|
75
70
|
@details_keys.clear
|
76
71
|
end
|
77
72
|
|
78
|
-
def
|
79
|
-
@
|
73
|
+
def self.digest_caches
|
74
|
+
@details_keys.values
|
80
75
|
end
|
81
76
|
end
|
82
77
|
|
@@ -98,9 +93,9 @@ module ActionView
|
|
98
93
|
@cache = old_value
|
99
94
|
end
|
100
95
|
|
101
|
-
|
96
|
+
private
|
102
97
|
|
103
|
-
def _set_detail(key, value)
|
98
|
+
def _set_detail(key, value) # :doc:
|
104
99
|
@details = @details.dup if @details_key
|
105
100
|
@details_key = nil
|
106
101
|
@details[key] = value
|
@@ -130,11 +125,16 @@ module ActionView
|
|
130
125
|
@view_paths.find_all(*args_for_lookup(name, prefixes, partial, keys, options))
|
131
126
|
end
|
132
127
|
|
133
|
-
def exists?(name, prefixes = [], partial = false, keys = [], options
|
128
|
+
def exists?(name, prefixes = [], partial = false, keys = [], **options)
|
134
129
|
@view_paths.exists?(*args_for_lookup(name, prefixes, partial, keys, options))
|
135
130
|
end
|
136
131
|
alias :template_exists? :exists?
|
137
132
|
|
133
|
+
def any?(name, prefixes = [], partial = false)
|
134
|
+
@view_paths.exists?(*args_for_any(name, prefixes, partial))
|
135
|
+
end
|
136
|
+
alias :any_templates? :any?
|
137
|
+
|
138
138
|
# Adds fallbacks to the view paths. Useful in cases when you are rendering
|
139
139
|
# a :file.
|
140
140
|
def with_fallbacks
|
@@ -149,16 +149,16 @@ module ActionView
|
|
149
149
|
added_resolvers.times { view_paths.pop }
|
150
150
|
end
|
151
151
|
|
152
|
-
|
152
|
+
private
|
153
153
|
|
154
|
-
def args_for_lookup(name, prefixes, partial, keys, details_options)
|
154
|
+
def args_for_lookup(name, prefixes, partial, keys, details_options)
|
155
155
|
name, prefixes = normalize_name(name, prefixes)
|
156
156
|
details, details_key = detail_args_for(details_options)
|
157
157
|
[name, prefixes, partial || false, details, details_key, keys]
|
158
158
|
end
|
159
159
|
|
160
160
|
# Compute details hash and key according to user options (e.g. passed from #render).
|
161
|
-
def detail_args_for(options)
|
161
|
+
def detail_args_for(options) # :doc:
|
162
162
|
return @details, details_key if options.empty? # most common path.
|
163
163
|
user_details = @details.merge(options)
|
164
164
|
|
@@ -171,18 +171,44 @@ module ActionView
|
|
171
171
|
[user_details, details_key]
|
172
172
|
end
|
173
173
|
|
174
|
+
def args_for_any(name, prefixes, partial)
|
175
|
+
name, prefixes = normalize_name(name, prefixes)
|
176
|
+
details, details_key = detail_args_for_any
|
177
|
+
[name, prefixes, partial || false, details, details_key]
|
178
|
+
end
|
179
|
+
|
180
|
+
def detail_args_for_any
|
181
|
+
@detail_args_for_any ||= begin
|
182
|
+
details = {}
|
183
|
+
|
184
|
+
registered_details.each do |k|
|
185
|
+
if k == :variants
|
186
|
+
details[k] = :any
|
187
|
+
else
|
188
|
+
details[k] = Accessors::DEFAULT_PROCS[k].call
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
if @cache
|
193
|
+
[details, DetailsKey.get(details)]
|
194
|
+
else
|
195
|
+
[details, nil]
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
174
200
|
# Support legacy foo.erb names even though we now ignore .erb
|
175
201
|
# as well as incorrectly putting part of the path in the template
|
176
202
|
# name instead of the prefix.
|
177
|
-
def normalize_name(name, prefixes)
|
203
|
+
def normalize_name(name, prefixes)
|
178
204
|
prefixes = prefixes.presence
|
179
|
-
parts = name.to_s.split(
|
205
|
+
parts = name.to_s.split("/".freeze)
|
180
206
|
parts.shift if parts.first.empty?
|
181
|
-
name
|
207
|
+
name = parts.pop
|
182
208
|
|
183
209
|
return name, prefixes || [""] if parts.empty?
|
184
210
|
|
185
|
-
parts = parts.join(
|
211
|
+
parts = parts.join("/".freeze)
|
186
212
|
prefixes = prefixes ? prefixes.map { |p| "#{p}/#{parts}" } : [parts]
|
187
213
|
|
188
214
|
return name, prefixes
|
@@ -194,21 +220,32 @@ module ActionView
|
|
194
220
|
include ViewPaths
|
195
221
|
|
196
222
|
def initialize(view_paths, details = {}, prefixes = [])
|
197
|
-
@
|
198
|
-
@skip_default_locale = false
|
223
|
+
@details_key = nil
|
199
224
|
@cache = true
|
200
225
|
@prefixes = prefixes
|
201
226
|
@rendered_format = nil
|
202
227
|
|
228
|
+
@details = initialize_details({}, details)
|
203
229
|
self.view_paths = view_paths
|
204
|
-
initialize_details(details)
|
205
230
|
end
|
206
231
|
|
232
|
+
def digest_cache
|
233
|
+
details_key
|
234
|
+
end
|
235
|
+
|
236
|
+
def initialize_details(target, details)
|
237
|
+
registered_details.each do |k|
|
238
|
+
target[k] = details[k] || Accessors::DEFAULT_PROCS[k].call
|
239
|
+
end
|
240
|
+
target
|
241
|
+
end
|
242
|
+
private :initialize_details
|
243
|
+
|
207
244
|
# Override formats= to expand ["*/*"] values and automatically
|
208
245
|
# add :html as fallback to :js.
|
209
246
|
def formats=(values)
|
210
247
|
if values
|
211
|
-
values.concat(default_formats) if values.delete "*/*"
|
248
|
+
values.concat(default_formats) if values.delete "*/*".freeze
|
212
249
|
if values == [:js]
|
213
250
|
values << :html
|
214
251
|
@html_fallback_for_js = true
|
@@ -217,12 +254,6 @@ module ActionView
|
|
217
254
|
super(values)
|
218
255
|
end
|
219
256
|
|
220
|
-
# Do not use the default locale on template lookup.
|
221
|
-
def skip_default_locale!
|
222
|
-
@skip_default_locale = true
|
223
|
-
self.locale = nil
|
224
|
-
end
|
225
|
-
|
226
257
|
# Override locale to return a symbol instead of array.
|
227
258
|
def locale
|
228
259
|
@details[:locale].first
|
@@ -237,23 +268,7 @@ module ActionView
|
|
237
268
|
config.locale = value
|
238
269
|
end
|
239
270
|
|
240
|
-
super(
|
241
|
-
end
|
242
|
-
|
243
|
-
# Uses the first format in the formats array for layout lookup.
|
244
|
-
def with_layout_format
|
245
|
-
if formats.size == 1
|
246
|
-
yield
|
247
|
-
else
|
248
|
-
old_formats = formats
|
249
|
-
_set_detail(:formats, formats[0,1])
|
250
|
-
|
251
|
-
begin
|
252
|
-
yield
|
253
|
-
ensure
|
254
|
-
_set_detail(:formats, old_formats)
|
255
|
-
end
|
256
|
-
end
|
271
|
+
super(default_locale)
|
257
272
|
end
|
258
273
|
end
|
259
274
|
end
|
data/lib/action_view/path_set.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActionView #:nodoc:
|
2
4
|
# = Action View PathSet
|
3
5
|
#
|
@@ -58,32 +60,41 @@ module ActionView #:nodoc:
|
|
58
60
|
find_all(path, prefixes, *args).any?
|
59
61
|
end
|
60
62
|
|
63
|
+
def find_all_with_query(query) # :nodoc:
|
64
|
+
paths.each do |resolver|
|
65
|
+
templates = resolver.find_all_with_query(query)
|
66
|
+
return templates unless templates.empty?
|
67
|
+
end
|
68
|
+
|
69
|
+
[]
|
70
|
+
end
|
71
|
+
|
61
72
|
private
|
62
73
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
74
|
+
def _find_all(path, prefixes, args, outside_app)
|
75
|
+
prefixes = [prefixes] if String === prefixes
|
76
|
+
prefixes.each do |prefix|
|
77
|
+
paths.each do |resolver|
|
78
|
+
if outside_app
|
79
|
+
templates = resolver.find_all_anywhere(path, prefix, *args)
|
80
|
+
else
|
81
|
+
templates = resolver.find_all(path, prefix, *args)
|
82
|
+
end
|
83
|
+
return templates unless templates.empty?
|
71
84
|
end
|
72
|
-
return templates unless templates.empty?
|
73
85
|
end
|
86
|
+
[]
|
74
87
|
end
|
75
|
-
[]
|
76
|
-
end
|
77
88
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
89
|
+
def typecast(paths)
|
90
|
+
paths.map do |path|
|
91
|
+
case path
|
92
|
+
when Pathname, String
|
93
|
+
OptimizedFileSystemResolver.new path.to_s
|
94
|
+
else
|
95
|
+
path
|
96
|
+
end
|
85
97
|
end
|
86
98
|
end
|
87
|
-
end
|
88
99
|
end
|
89
100
|
end
|