actionview 6.0.4.6 → 6.1.0.rc1
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 +152 -288
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/lib/action_view/base.rb +21 -52
- data/lib/action_view/cache_expiry.rb +1 -2
- data/lib/action_view/context.rb +0 -1
- data/lib/action_view/dependency_tracker.rb +10 -4
- data/lib/action_view/digestor.rb +3 -2
- data/lib/action_view/gem_version.rb +3 -3
- data/lib/action_view/helpers/asset_tag_helper.rb +40 -15
- data/lib/action_view/helpers/asset_url_helper.rb +6 -4
- data/lib/action_view/helpers/atom_feed_helper.rb +2 -1
- data/lib/action_view/helpers/cache_helper.rb +10 -16
- data/lib/action_view/helpers/date_helper.rb +4 -4
- data/lib/action_view/helpers/form_helper.rb +59 -17
- data/lib/action_view/helpers/form_options_helper.rb +7 -16
- data/lib/action_view/helpers/form_tag_helper.rb +8 -6
- data/lib/action_view/helpers/javascript_helper.rb +3 -3
- data/lib/action_view/helpers/number_helper.rb +6 -6
- data/lib/action_view/helpers/rendering_helper.rb +11 -3
- data/lib/action_view/helpers/sanitize_helper.rb +2 -2
- data/lib/action_view/helpers/tag_helper.rb +92 -17
- data/lib/action_view/helpers/tags/base.rb +9 -5
- data/lib/action_view/helpers/tags/date_field.rb +1 -1
- data/lib/action_view/helpers/tags/date_select.rb +2 -2
- data/lib/action_view/helpers/tags/datetime_local_field.rb +1 -1
- data/lib/action_view/helpers/tags/label.rb +4 -0
- data/lib/action_view/helpers/tags/month_field.rb +1 -1
- data/lib/action_view/helpers/tags/select.rb +1 -1
- data/lib/action_view/helpers/tags/time_field.rb +1 -1
- data/lib/action_view/helpers/tags/week_field.rb +1 -1
- data/lib/action_view/helpers/text_helper.rb +1 -1
- data/lib/action_view/helpers/translation_helper.rb +88 -53
- data/lib/action_view/helpers/url_helper.rb +107 -13
- data/lib/action_view/layouts.rb +3 -2
- data/lib/action_view/log_subscriber.rb +26 -10
- data/lib/action_view/lookup_context.rb +3 -18
- data/lib/action_view/path_set.rb +0 -3
- data/lib/action_view/railtie.rb +35 -46
- data/lib/action_view/renderer/abstract_renderer.rb +93 -14
- data/lib/action_view/renderer/collection_renderer.rb +192 -0
- data/lib/action_view/renderer/object_renderer.rb +34 -0
- data/lib/action_view/renderer/partial_renderer/collection_caching.rb +25 -26
- data/lib/action_view/renderer/partial_renderer.rb +20 -282
- data/lib/action_view/renderer/renderer.rb +44 -1
- data/lib/action_view/renderer/streaming_template_renderer.rb +5 -1
- data/lib/action_view/renderer/template_renderer.rb +15 -12
- data/lib/action_view/rendering.rb +3 -1
- data/lib/action_view/routing_url_for.rb +1 -1
- data/lib/action_view/template/handlers/erb/erubi.rb +9 -7
- data/lib/action_view/template/handlers/erb.rb +10 -14
- data/lib/action_view/template/handlers.rb +0 -26
- data/lib/action_view/template/html.rb +1 -11
- data/lib/action_view/template/raw_file.rb +0 -3
- data/lib/action_view/template/renderable.rb +24 -0
- data/lib/action_view/template/resolver.rb +82 -40
- data/lib/action_view/template/text.rb +0 -3
- data/lib/action_view/template.rb +9 -49
- data/lib/action_view/test_case.rb +18 -25
- data/lib/action_view/testing/resolvers.rb +10 -31
- data/lib/action_view/unbound_template.rb +3 -3
- data/lib/action_view/view_paths.rb +34 -36
- data/lib/action_view.rb +4 -1
- data/lib/assets/compiled/rails-ujs.js +1 -1
- metadata +20 -17
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionView
|
4
|
+
# = Action View Renderable Template for objects that respond to #render_in
|
5
|
+
class Template
|
6
|
+
class Renderable # :nodoc:
|
7
|
+
def initialize(renderable)
|
8
|
+
@renderable = renderable
|
9
|
+
end
|
10
|
+
|
11
|
+
def identifier
|
12
|
+
@renderable.class.name
|
13
|
+
end
|
14
|
+
|
15
|
+
def render(context, *args)
|
16
|
+
@renderable.render_in(context)
|
17
|
+
end
|
18
|
+
|
19
|
+
def format
|
20
|
+
@renderable.format
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -35,6 +35,41 @@ module ActionView
|
|
35
35
|
alias :to_s :to_str
|
36
36
|
end
|
37
37
|
|
38
|
+
class PathParser # :nodoc:
|
39
|
+
def build_path_regex
|
40
|
+
handlers = Template::Handlers.extensions.map { |x| Regexp.escape(x) }.join("|")
|
41
|
+
formats = Template::Types.symbols.map { |x| Regexp.escape(x) }.join("|")
|
42
|
+
locales = "[a-z]{2}(?:-[A-Z]{2})?"
|
43
|
+
variants = "[^.]*"
|
44
|
+
|
45
|
+
%r{
|
46
|
+
\A
|
47
|
+
(?:(?<prefix>.*)/)?
|
48
|
+
(?<partial>_)?
|
49
|
+
(?<action>.*?)
|
50
|
+
(?:\.(?<locale>#{locales}))??
|
51
|
+
(?:\.(?<format>#{formats}))??
|
52
|
+
(?:\+(?<variant>#{variants}))??
|
53
|
+
(?:\.(?<handler>#{handlers}))?
|
54
|
+
\z
|
55
|
+
}x
|
56
|
+
end
|
57
|
+
|
58
|
+
def parse(path)
|
59
|
+
@regex ||= build_path_regex
|
60
|
+
match = @regex.match(path)
|
61
|
+
{
|
62
|
+
prefix: match[:prefix] || "",
|
63
|
+
action: match[:action],
|
64
|
+
partial: !!match[:partial],
|
65
|
+
locale: match[:locale]&.to_sym,
|
66
|
+
handler: match[:handler]&.to_sym,
|
67
|
+
format: match[:format]&.to_sym,
|
68
|
+
variant: match[:variant]
|
69
|
+
}
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
38
73
|
# Threadsafe template cache
|
39
74
|
class Cache #:nodoc:
|
40
75
|
class SmallCache < Concurrent::Map
|
@@ -43,13 +78,13 @@ module ActionView
|
|
43
78
|
end
|
44
79
|
end
|
45
80
|
|
46
|
-
#
|
81
|
+
# Preallocate all the default blocks for performance/memory consumption reasons
|
47
82
|
PARTIAL_BLOCK = lambda { |cache, partial| cache[partial] = SmallCache.new }
|
48
83
|
PREFIX_BLOCK = lambda { |cache, prefix| cache[prefix] = SmallCache.new(&PARTIAL_BLOCK) }
|
49
84
|
NAME_BLOCK = lambda { |cache, name| cache[name] = SmallCache.new(&PREFIX_BLOCK) }
|
50
85
|
KEY_BLOCK = lambda { |cache, key| cache[key] = SmallCache.new(&NAME_BLOCK) }
|
51
86
|
|
52
|
-
#
|
87
|
+
# Usually a majority of template look ups return nothing, use this canonical preallocated array to save memory
|
53
88
|
NO_TEMPLATES = [].freeze
|
54
89
|
|
55
90
|
def initialize
|
@@ -58,7 +93,7 @@ module ActionView
|
|
58
93
|
end
|
59
94
|
|
60
95
|
def inspect
|
61
|
-
"
|
96
|
+
"#{to_s[0..-2]} keys=#{@data.size} queries=#{@query_cache.size}>"
|
62
97
|
end
|
63
98
|
|
64
99
|
# Cache the templates returned by the block
|
@@ -75,7 +110,7 @@ module ActionView
|
|
75
110
|
@query_cache.clear
|
76
111
|
end
|
77
112
|
|
78
|
-
# Get the cache size.
|
113
|
+
# Get the cache size. Do not call this
|
79
114
|
# method. This method is not guaranteed to be here ever.
|
80
115
|
def size # :nodoc:
|
81
116
|
size = 0
|
@@ -121,9 +156,6 @@ module ActionView
|
|
121
156
|
end
|
122
157
|
end
|
123
158
|
|
124
|
-
alias :find_all_anywhere :find_all
|
125
|
-
deprecate :find_all_anywhere
|
126
|
-
|
127
159
|
def find_all_with_query(query) # :nodoc:
|
128
160
|
@cache.cache_query(query) { find_template_paths(File.join(@path, query)) }
|
129
161
|
end
|
@@ -164,20 +196,17 @@ module ActionView
|
|
164
196
|
EXTENSIONS = { locale: ".", formats: ".", variants: "+", handlers: "." }
|
165
197
|
DEFAULT_PATTERN = ":prefix/:action{.:locale,}{.:formats,}{+:variants,}{.:handlers,}"
|
166
198
|
|
167
|
-
def initialize
|
168
|
-
|
169
|
-
ActiveSupport::Deprecation.warn "Specifying a custom path for #{self.class} is deprecated. Implement a custom Resolver subclass instead."
|
170
|
-
@pattern = pattern
|
171
|
-
else
|
172
|
-
@pattern = DEFAULT_PATTERN
|
173
|
-
end
|
199
|
+
def initialize
|
200
|
+
@pattern = DEFAULT_PATTERN
|
174
201
|
@unbound_templates = Concurrent::Map.new
|
175
|
-
|
202
|
+
@path_parser = PathParser.new
|
203
|
+
super
|
176
204
|
end
|
177
205
|
|
178
206
|
def clear_cache
|
179
207
|
@unbound_templates.clear
|
180
|
-
|
208
|
+
@path_parser = PathParser.new
|
209
|
+
super
|
181
210
|
end
|
182
211
|
|
183
212
|
private
|
@@ -204,9 +233,13 @@ module ActionView
|
|
204
233
|
end
|
205
234
|
end
|
206
235
|
|
236
|
+
def source_for_template(template)
|
237
|
+
Template::Sources::File.new(template)
|
238
|
+
end
|
239
|
+
|
207
240
|
def build_unbound_template(template, virtual_path)
|
208
241
|
handler, format, variant = extract_handler_and_format_and_variant(template)
|
209
|
-
source =
|
242
|
+
source = source_for_template(template)
|
210
243
|
|
211
244
|
UnboundTemplate.new(
|
212
245
|
source,
|
@@ -223,6 +256,10 @@ module ActionView
|
|
223
256
|
end
|
224
257
|
|
225
258
|
def find_template_paths_from_details(path, details)
|
259
|
+
if path.name.include?(".")
|
260
|
+
ActiveSupport::Deprecation.warn("Rendering actions with '.' in the name is deprecated: #{path}")
|
261
|
+
end
|
262
|
+
|
226
263
|
query = build_query(path, details)
|
227
264
|
find_template_paths(query)
|
228
265
|
end
|
@@ -249,7 +286,7 @@ module ActionView
|
|
249
286
|
query.gsub!(/:prefix(\/)?/, prefix)
|
250
287
|
|
251
288
|
partial = escape_entry(path.partial? ? "_#{path.name}" : path.name)
|
252
|
-
query.gsub!(
|
289
|
+
query.gsub!(":action", partial)
|
253
290
|
|
254
291
|
details.each do |ext, candidates|
|
255
292
|
if ext == :variants && candidates == :any
|
@@ -270,22 +307,11 @@ module ActionView
|
|
270
307
|
# from the path, or the handler, we should return the array of formats given
|
271
308
|
# to the resolver.
|
272
309
|
def extract_handler_and_format_and_variant(path)
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
handler = Template.handler_for_extension(extension)
|
279
|
-
format, variant = pieces.last.split(EXTENSIONS[:variants], 2) if pieces.last
|
280
|
-
format = if format
|
281
|
-
Template::Types[format]&.ref
|
282
|
-
else
|
283
|
-
if handler.respond_to?(:default_format) # default_format can return nil
|
284
|
-
handler.default_format
|
285
|
-
else
|
286
|
-
nil
|
287
|
-
end
|
288
|
-
end
|
310
|
+
details = @path_parser.parse(path)
|
311
|
+
|
312
|
+
handler = Template.handler_for_extension(details[:handler])
|
313
|
+
format = details[:format] || handler.try(:default_format)
|
314
|
+
variant = details[:variant]
|
289
315
|
|
290
316
|
# Template::Types[format] and handler.default_format can return nil
|
291
317
|
[handler, format, variant]
|
@@ -296,9 +322,9 @@ module ActionView
|
|
296
322
|
class FileSystemResolver < PathResolver
|
297
323
|
attr_reader :path
|
298
324
|
|
299
|
-
def initialize(path
|
325
|
+
def initialize(path)
|
300
326
|
raise ArgumentError, "path already is a Resolver class" if path.is_a?(Resolver)
|
301
|
-
super(
|
327
|
+
super()
|
302
328
|
@path = File.expand_path(path)
|
303
329
|
end
|
304
330
|
|
@@ -320,14 +346,27 @@ module ActionView
|
|
320
346
|
end
|
321
347
|
|
322
348
|
private
|
323
|
-
def
|
349
|
+
def find_candidate_template_paths(path)
|
324
350
|
# Instead of checking for every possible path, as our other globs would
|
325
351
|
# do, scan the directory for files with the right prefix.
|
326
352
|
query = "#{escape_entry(File.join(@path, path))}*"
|
327
353
|
|
354
|
+
Dir[query].reject do |filename|
|
355
|
+
File.directory?(filename)
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
def find_template_paths_from_details(path, details)
|
360
|
+
if path.name.include?(".")
|
361
|
+
# Fall back to the unoptimized resolver, which will warn
|
362
|
+
return super
|
363
|
+
end
|
364
|
+
|
365
|
+
candidates = find_candidate_template_paths(path)
|
366
|
+
|
328
367
|
regex = build_regex(path, details)
|
329
368
|
|
330
|
-
|
369
|
+
candidates.uniq.reject do |filename|
|
331
370
|
# This regex match does double duty of finding only files which match
|
332
371
|
# details (instead of just matching the prefix) and also filtering for
|
333
372
|
# case-insensitive file systems.
|
@@ -339,7 +378,7 @@ module ActionView
|
|
339
378
|
# We can use the matches found by the regex and sort by their index in
|
340
379
|
# details.
|
341
380
|
match = filename.match(regex)
|
342
|
-
EXTENSIONS.keys.
|
381
|
+
EXTENSIONS.keys.map do |ext|
|
343
382
|
if ext == :variants && details[ext] == :any
|
344
383
|
match[ext].nil? ? 0 : 1
|
345
384
|
elsif match[ext].nil?
|
@@ -360,7 +399,10 @@ module ActionView
|
|
360
399
|
if ext == :variants && details[ext] == :any
|
361
400
|
".*?"
|
362
401
|
else
|
363
|
-
details[ext].compact
|
402
|
+
arr = details[ext].compact
|
403
|
+
arr.uniq!
|
404
|
+
arr.map! { |e| Regexp.escape(e) }
|
405
|
+
arr.join("|")
|
364
406
|
end
|
365
407
|
prefix = Regexp.escape(prefix)
|
366
408
|
"(#{prefix}(?<#{ext}>#{match}))?"
|
data/lib/action_view/template.rb
CHANGED
@@ -1,8 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "active_support/core_ext/object/try"
|
4
|
-
require "active_support/core_ext/kernel/singleton_class"
|
5
|
-
require "active_support/deprecation"
|
6
3
|
require "thread"
|
7
4
|
require "delegate"
|
8
5
|
|
@@ -11,14 +8,6 @@ module ActionView
|
|
11
8
|
class Template
|
12
9
|
extend ActiveSupport::Autoload
|
13
10
|
|
14
|
-
def self.finalize_compiled_template_methods
|
15
|
-
ActiveSupport::Deprecation.warn "ActionView::Template.finalize_compiled_template_methods is deprecated and has no effect"
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.finalize_compiled_template_methods=(_)
|
19
|
-
ActiveSupport::Deprecation.warn "ActionView::Template.finalize_compiled_template_methods= is deprecated and has no effect"
|
20
|
-
end
|
21
|
-
|
22
11
|
# === Encodings in ActionView::Template
|
23
12
|
#
|
24
13
|
# ActionView::Template is one of a few sources of potential
|
@@ -114,6 +103,7 @@ module ActionView
|
|
114
103
|
eager_autoload do
|
115
104
|
autoload :Error
|
116
105
|
autoload :RawFile
|
106
|
+
autoload :Renderable
|
117
107
|
autoload :Handlers
|
118
108
|
autoload :HTML
|
119
109
|
autoload :Inline
|
@@ -124,15 +114,10 @@ module ActionView
|
|
124
114
|
|
125
115
|
extend Template::Handlers
|
126
116
|
|
127
|
-
attr_reader :identifier, :handler
|
117
|
+
attr_reader :identifier, :handler
|
128
118
|
attr_reader :variable, :format, :variant, :locals, :virtual_path
|
129
119
|
|
130
|
-
def initialize(source, identifier, handler, format: nil, variant: nil,
|
131
|
-
unless locals
|
132
|
-
ActiveSupport::Deprecation.warn "ActionView::Template#initialize requires a locals parameter"
|
133
|
-
locals = []
|
134
|
-
end
|
135
|
-
|
120
|
+
def initialize(source, identifier, handler, locals:, format: nil, variant: nil, virtual_path: nil)
|
136
121
|
@source = source
|
137
122
|
@identifier = identifier
|
138
123
|
@handler = handler
|
@@ -141,32 +126,16 @@ module ActionView
|
|
141
126
|
@virtual_path = virtual_path
|
142
127
|
|
143
128
|
@variable = if @virtual_path
|
144
|
-
base = @virtual_path
|
129
|
+
base = @virtual_path.end_with?("/") ? "" : ::File.basename(@virtual_path)
|
145
130
|
base =~ /\A_?(.*?)(?:\.\w+)*\z/
|
146
131
|
$1.to_sym
|
147
132
|
end
|
148
133
|
|
149
|
-
if updated_at
|
150
|
-
ActiveSupport::Deprecation.warn "ActionView::Template#updated_at is deprecated"
|
151
|
-
@updated_at = updated_at
|
152
|
-
else
|
153
|
-
@updated_at = Time.now
|
154
|
-
end
|
155
134
|
@format = format
|
156
135
|
@variant = variant
|
157
136
|
@compile_mutex = Mutex.new
|
158
137
|
end
|
159
138
|
|
160
|
-
deprecate :original_encoding
|
161
|
-
deprecate :updated_at
|
162
|
-
deprecate def virtual_path=(_); end
|
163
|
-
deprecate def locals=(_); end
|
164
|
-
deprecate def formats=(_); end
|
165
|
-
deprecate def formats; Array(format); end
|
166
|
-
deprecate def variants=(_); end
|
167
|
-
deprecate def variants; [variant]; end
|
168
|
-
deprecate def refresh(_); self; end
|
169
|
-
|
170
139
|
# Returns whether the underlying handler supports streaming. If so,
|
171
140
|
# a streaming buffer *may* be passed when it starts rendering.
|
172
141
|
def supports_streaming?
|
@@ -179,10 +148,10 @@ module ActionView
|
|
179
148
|
# This method is instrumented as "!render_template.action_view". Notice that
|
180
149
|
# we use a bang in this instrumentation because you don't want to
|
181
150
|
# consume this in production. This is only slow if it's being listened to.
|
182
|
-
def render(view, locals, buffer = ActionView::OutputBuffer.new, &block)
|
151
|
+
def render(view, locals, buffer = ActionView::OutputBuffer.new, add_to_stack: true, &block)
|
183
152
|
instrument_render_template do
|
184
153
|
compile!(view)
|
185
|
-
view._run(method_name, self, locals, buffer, &block)
|
154
|
+
view._run(method_name, self, locals, buffer, add_to_stack: add_to_stack, &block)
|
186
155
|
end
|
187
156
|
rescue => e
|
188
157
|
handle_render_error(view, e)
|
@@ -193,7 +162,7 @@ module ActionView
|
|
193
162
|
end
|
194
163
|
|
195
164
|
def short_identifier
|
196
|
-
@short_identifier ||= defined?(Rails.root) ? identifier.
|
165
|
+
@short_identifier ||= defined?(Rails.root) ? identifier.delete_prefix("#{Rails.root}/") : identifier
|
197
166
|
end
|
198
167
|
|
199
168
|
def inspect
|
@@ -255,11 +224,11 @@ module ActionView
|
|
255
224
|
# to ensure that references to the template object can be marshalled as well. This means forgoing
|
256
225
|
# the marshalling of the compiler mutex and instantiating that again on unmarshalling.
|
257
226
|
def marshal_dump # :nodoc:
|
258
|
-
[ @source, @identifier, @handler, @compiled, @locals, @virtual_path, @
|
227
|
+
[ @source, @identifier, @handler, @compiled, @locals, @virtual_path, @format, @variant ]
|
259
228
|
end
|
260
229
|
|
261
230
|
def marshal_load(array) # :nodoc:
|
262
|
-
@source, @identifier, @handler, @compiled, @locals, @virtual_path, @
|
231
|
+
@source, @identifier, @handler, @compiled, @locals, @virtual_path, @format, @variant = *array
|
263
232
|
@compile_mutex = Mutex.new
|
264
233
|
end
|
265
234
|
|
@@ -288,15 +257,6 @@ module ActionView
|
|
288
257
|
end
|
289
258
|
end
|
290
259
|
|
291
|
-
class LegacyTemplate < DelegateClass(Template) # :nodoc:
|
292
|
-
attr_reader :source
|
293
|
-
|
294
|
-
def initialize(template, source)
|
295
|
-
super(template)
|
296
|
-
@source = source
|
297
|
-
end
|
298
|
-
end
|
299
|
-
|
300
260
|
# Among other things, this method is responsible for properly setting
|
301
261
|
# the encoding of the compiled template.
|
302
262
|
#
|
@@ -16,11 +16,12 @@ module ActionView
|
|
16
16
|
attr_accessor :request, :response, :params
|
17
17
|
|
18
18
|
class << self
|
19
|
-
|
19
|
+
# Overrides AbstractController::Base#controller_path
|
20
|
+
attr_accessor :controller_path
|
20
21
|
end
|
21
22
|
|
22
23
|
def controller_path=(path)
|
23
|
-
self.class.controller_path =
|
24
|
+
self.class.controller_path = path
|
24
25
|
end
|
25
26
|
|
26
27
|
def initialize
|
@@ -73,7 +74,7 @@ module ActionView
|
|
73
74
|
def helper_method(*methods)
|
74
75
|
# Almost a duplicate from ActionController::Helpers
|
75
76
|
methods.flatten.each do |method|
|
76
|
-
|
77
|
+
_helpers_for_modification.module_eval <<-end_eval, __FILE__, __LINE__ + 1
|
77
78
|
def #{method}(*args, &block) # def current_user(*args, &block)
|
78
79
|
_test_case.send(:'#{method}', *args, &block) # _test_case.send(:'current_user', *args, &block)
|
79
80
|
end # end
|
@@ -101,7 +102,8 @@ module ActionView
|
|
101
102
|
end
|
102
103
|
|
103
104
|
def setup_with_controller
|
104
|
-
|
105
|
+
controller_class = Class.new(ActionView::TestCase::TestController)
|
106
|
+
@controller = controller_class.new
|
105
107
|
@request = @controller.request
|
106
108
|
@view_flow = ActionView::OutputFlow.new
|
107
109
|
# empty string ensures buffer has UTF-8 encoding as
|
@@ -109,8 +111,8 @@ module ActionView
|
|
109
111
|
@output_buffer = ActiveSupport::SafeBuffer.new ""
|
110
112
|
@rendered = +""
|
111
113
|
|
112
|
-
|
113
|
-
|
114
|
+
test_case_instance = self
|
115
|
+
controller_class.define_method(:_test_case) { test_case_instance }
|
114
116
|
end
|
115
117
|
|
116
118
|
def config
|
@@ -160,33 +162,24 @@ module ActionView
|
|
160
162
|
included do
|
161
163
|
setup :setup_with_controller
|
162
164
|
ActiveSupport.run_load_hooks(:action_view_test_case, self)
|
163
|
-
end
|
164
165
|
|
165
|
-
|
166
|
-
# Need to experiment if this priority is the best one: rendered => output_buffer
|
167
|
-
def document_root_element
|
168
|
-
Nokogiri::HTML::Document.parse(@rendered.blank? ? @output_buffer : @rendered).root
|
169
|
-
end
|
170
|
-
|
171
|
-
def say_no_to_protect_against_forgery!
|
172
|
-
_helpers.module_eval do
|
173
|
-
silence_redefinition_of_method :protect_against_forgery?
|
166
|
+
helper do
|
174
167
|
def protect_against_forgery?
|
175
168
|
false
|
176
169
|
end
|
177
|
-
end
|
178
|
-
end
|
179
170
|
|
180
|
-
|
181
|
-
|
182
|
-
_helpers.module_eval do
|
183
|
-
unless private_method_defined?(:_test_case)
|
184
|
-
define_method(:_test_case) { test_case_instance }
|
185
|
-
private :_test_case
|
171
|
+
def _test_case
|
172
|
+
controller._test_case
|
186
173
|
end
|
187
174
|
end
|
188
175
|
end
|
189
176
|
|
177
|
+
private
|
178
|
+
# Need to experiment if this priority is the best one: rendered => output_buffer
|
179
|
+
def document_root_element
|
180
|
+
Nokogiri::HTML::Document.parse(@rendered.blank? ? @output_buffer : @rendered).root
|
181
|
+
end
|
182
|
+
|
190
183
|
module Locals
|
191
184
|
attr_accessor :rendered_views
|
192
185
|
|
@@ -283,7 +276,7 @@ module ActionView
|
|
283
276
|
|
284
277
|
def respond_to_missing?(name, include_private = false)
|
285
278
|
begin
|
286
|
-
routes = @controller.respond_to?(:_routes) && @controller._routes
|
279
|
+
routes = defined?(@controller) && @controller.respond_to?(:_routes) && @controller._routes
|
287
280
|
rescue
|
288
281
|
# Don't call routes, if there is an error on _routes call
|
289
282
|
end
|
@@ -8,12 +8,8 @@ module ActionView #:nodoc:
|
|
8
8
|
# useful for testing extensions that have no way of knowing what the file
|
9
9
|
# system will look like at runtime.
|
10
10
|
class FixtureResolver < OptimizedFileSystemResolver
|
11
|
-
def initialize(hash = {}
|
11
|
+
def initialize(hash = {})
|
12
12
|
super("")
|
13
|
-
if pattern
|
14
|
-
ActiveSupport::Deprecation.warn "Specifying a custom path for #{self.class} is deprecated. Implement a custom Resolver subclass instead."
|
15
|
-
@pattern = pattern
|
16
|
-
end
|
17
13
|
@hash = hash
|
18
14
|
@path = ""
|
19
15
|
end
|
@@ -27,34 +23,17 @@ module ActionView #:nodoc:
|
|
27
23
|
end
|
28
24
|
|
29
25
|
private
|
30
|
-
def
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
end.map do |_path, source|
|
36
|
-
handler, format, variant = extract_handler_and_format_and_variant(_path)
|
37
|
-
|
38
|
-
Template.new(source, _path, handler,
|
39
|
-
virtual_path: path.virtual,
|
40
|
-
format: format,
|
41
|
-
variant: variant,
|
42
|
-
locals: locals
|
43
|
-
)
|
44
|
-
end.sort_by do |t|
|
45
|
-
match = ("/" + t.identifier).match(regex)
|
46
|
-
EXTENSIONS.keys.reverse.map do |ext|
|
47
|
-
if ext == :variants && exts[ext] == :any
|
48
|
-
match[ext].nil? ? 0 : 1
|
49
|
-
elsif match[ext].nil?
|
50
|
-
exts[ext].length
|
51
|
-
else
|
52
|
-
found = match[ext].to_sym
|
53
|
-
exts[ext].index(found)
|
54
|
-
end
|
55
|
-
end
|
26
|
+
def find_candidate_template_paths(path)
|
27
|
+
@hash.keys.select do |fixture|
|
28
|
+
fixture.start_with?(path.virtual)
|
29
|
+
end.map do |fixture|
|
30
|
+
"/#{fixture}"
|
56
31
|
end
|
57
32
|
end
|
33
|
+
|
34
|
+
def source_for_template(template)
|
35
|
+
@hash[template[1..template.size]]
|
36
|
+
end
|
58
37
|
end
|
59
38
|
|
60
39
|
class NullResolver < PathResolver
|
@@ -4,9 +4,9 @@ require "concurrent/map"
|
|
4
4
|
|
5
5
|
module ActionView
|
6
6
|
class UnboundTemplate
|
7
|
-
def initialize(source,
|
7
|
+
def initialize(source, identifier, handler, options)
|
8
8
|
@source = source
|
9
|
-
@
|
9
|
+
@identifier = identifier
|
10
10
|
@handler = handler
|
11
11
|
@options = options
|
12
12
|
|
@@ -22,7 +22,7 @@ module ActionView
|
|
22
22
|
options = @options.merge(locals: locals)
|
23
23
|
Template.new(
|
24
24
|
@source,
|
25
|
-
@
|
25
|
+
@identifier,
|
26
26
|
@handler,
|
27
27
|
**options
|
28
28
|
)
|
@@ -28,6 +28,40 @@ module ActionView
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
+
# Append a path to the list of view paths for this controller.
|
32
|
+
#
|
33
|
+
# ==== Parameters
|
34
|
+
# * <tt>path</tt> - If a String is provided, it gets converted into
|
35
|
+
# the default view path. You may also provide a custom view path
|
36
|
+
# (see ActionView::PathSet for more information)
|
37
|
+
def append_view_path(path)
|
38
|
+
self._view_paths = view_paths + Array(path)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Prepend a path to the list of view paths for this controller.
|
42
|
+
#
|
43
|
+
# ==== Parameters
|
44
|
+
# * <tt>path</tt> - If a String is provided, it gets converted into
|
45
|
+
# the default view path. You may also provide a custom view path
|
46
|
+
# (see ActionView::PathSet for more information)
|
47
|
+
def prepend_view_path(path)
|
48
|
+
self._view_paths = ActionView::PathSet.new(Array(path) + view_paths)
|
49
|
+
end
|
50
|
+
|
51
|
+
# A list of all of the default view paths for this controller.
|
52
|
+
def view_paths
|
53
|
+
_view_paths
|
54
|
+
end
|
55
|
+
|
56
|
+
# Set the view paths.
|
57
|
+
#
|
58
|
+
# ==== Parameters
|
59
|
+
# * <tt>paths</tt> - If a PathSet is provided, use that;
|
60
|
+
# otherwise, process the parameter into a PathSet.
|
61
|
+
def view_paths=(paths)
|
62
|
+
self._view_paths = ActionView::PathSet.new(Array(paths))
|
63
|
+
end
|
64
|
+
|
31
65
|
private
|
32
66
|
# Override this method in your controller if you want to change paths prefixes for finding views.
|
33
67
|
# Prefixes defined here will still be added to parents' <tt>._prefixes</tt>.
|
@@ -88,41 +122,5 @@ module ActionView
|
|
88
122
|
def prepend_view_path(path)
|
89
123
|
lookup_context.view_paths.unshift(*path)
|
90
124
|
end
|
91
|
-
|
92
|
-
module ClassMethods
|
93
|
-
# Append a path to the list of view paths for this controller.
|
94
|
-
#
|
95
|
-
# ==== Parameters
|
96
|
-
# * <tt>path</tt> - If a String is provided, it gets converted into
|
97
|
-
# the default view path. You may also provide a custom view path
|
98
|
-
# (see ActionView::PathSet for more information)
|
99
|
-
def append_view_path(path)
|
100
|
-
self._view_paths = view_paths + Array(path)
|
101
|
-
end
|
102
|
-
|
103
|
-
# Prepend a path to the list of view paths for this controller.
|
104
|
-
#
|
105
|
-
# ==== Parameters
|
106
|
-
# * <tt>path</tt> - If a String is provided, it gets converted into
|
107
|
-
# the default view path. You may also provide a custom view path
|
108
|
-
# (see ActionView::PathSet for more information)
|
109
|
-
def prepend_view_path(path)
|
110
|
-
self._view_paths = ActionView::PathSet.new(Array(path) + view_paths)
|
111
|
-
end
|
112
|
-
|
113
|
-
# A list of all of the default view paths for this controller.
|
114
|
-
def view_paths
|
115
|
-
_view_paths
|
116
|
-
end
|
117
|
-
|
118
|
-
# Set the view paths.
|
119
|
-
#
|
120
|
-
# ==== Parameters
|
121
|
-
# * <tt>paths</tt> - If a PathSet is provided, use that;
|
122
|
-
# otherwise, process the parameter into a PathSet.
|
123
|
-
def view_paths=(paths)
|
124
|
-
self._view_paths = ActionView::PathSet.new(Array(paths))
|
125
|
-
end
|
126
|
-
end
|
127
125
|
end
|
128
126
|
end
|
data/lib/action_view.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
#--
|
4
|
-
# Copyright (c) 2004-
|
4
|
+
# Copyright (c) 2004-2020 David Heinemeier Hansson
|
5
5
|
#
|
6
6
|
# Permission is hereby granted, free of charge, to any person obtaining
|
7
7
|
# a copy of this software and associated documentation files (the
|
@@ -51,6 +51,8 @@ module ActionView
|
|
51
51
|
autoload :Renderer
|
52
52
|
autoload :AbstractRenderer
|
53
53
|
autoload :PartialRenderer
|
54
|
+
autoload :CollectionRenderer
|
55
|
+
autoload :ObjectRenderer
|
54
56
|
autoload :TemplateRenderer
|
55
57
|
autoload :StreamingTemplateRenderer
|
56
58
|
end
|
@@ -58,6 +60,7 @@ module ActionView
|
|
58
60
|
autoload_at "action_view/template/resolver" do
|
59
61
|
autoload :Resolver
|
60
62
|
autoload :PathResolver
|
63
|
+
autoload :FileSystemResolver
|
61
64
|
autoload :OptimizedFileSystemResolver
|
62
65
|
autoload :FallbackFileSystemResolver
|
63
66
|
end
|