actionview 6.0.4.7 → 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.

Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +152 -293
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +1 -1
  5. data/lib/action_view/base.rb +21 -52
  6. data/lib/action_view/cache_expiry.rb +1 -2
  7. data/lib/action_view/context.rb +0 -1
  8. data/lib/action_view/dependency_tracker.rb +10 -4
  9. data/lib/action_view/digestor.rb +3 -2
  10. data/lib/action_view/gem_version.rb +3 -3
  11. data/lib/action_view/helpers/asset_tag_helper.rb +40 -15
  12. data/lib/action_view/helpers/asset_url_helper.rb +6 -4
  13. data/lib/action_view/helpers/atom_feed_helper.rb +2 -1
  14. data/lib/action_view/helpers/cache_helper.rb +10 -16
  15. data/lib/action_view/helpers/date_helper.rb +4 -4
  16. data/lib/action_view/helpers/form_helper.rb +59 -17
  17. data/lib/action_view/helpers/form_options_helper.rb +7 -16
  18. data/lib/action_view/helpers/form_tag_helper.rb +8 -6
  19. data/lib/action_view/helpers/javascript_helper.rb +3 -3
  20. data/lib/action_view/helpers/number_helper.rb +6 -6
  21. data/lib/action_view/helpers/rendering_helper.rb +11 -3
  22. data/lib/action_view/helpers/sanitize_helper.rb +2 -2
  23. data/lib/action_view/helpers/tag_helper.rb +92 -17
  24. data/lib/action_view/helpers/tags/base.rb +9 -5
  25. data/lib/action_view/helpers/tags/date_field.rb +1 -1
  26. data/lib/action_view/helpers/tags/date_select.rb +2 -2
  27. data/lib/action_view/helpers/tags/datetime_local_field.rb +1 -1
  28. data/lib/action_view/helpers/tags/label.rb +4 -0
  29. data/lib/action_view/helpers/tags/month_field.rb +1 -1
  30. data/lib/action_view/helpers/tags/select.rb +1 -1
  31. data/lib/action_view/helpers/tags/time_field.rb +1 -1
  32. data/lib/action_view/helpers/tags/week_field.rb +1 -1
  33. data/lib/action_view/helpers/text_helper.rb +1 -1
  34. data/lib/action_view/helpers/translation_helper.rb +88 -53
  35. data/lib/action_view/helpers/url_helper.rb +107 -13
  36. data/lib/action_view/layouts.rb +3 -2
  37. data/lib/action_view/log_subscriber.rb +26 -10
  38. data/lib/action_view/lookup_context.rb +3 -18
  39. data/lib/action_view/path_set.rb +0 -3
  40. data/lib/action_view/railtie.rb +35 -46
  41. data/lib/action_view/renderer/abstract_renderer.rb +93 -14
  42. data/lib/action_view/renderer/collection_renderer.rb +192 -0
  43. data/lib/action_view/renderer/object_renderer.rb +34 -0
  44. data/lib/action_view/renderer/partial_renderer/collection_caching.rb +25 -26
  45. data/lib/action_view/renderer/partial_renderer.rb +20 -282
  46. data/lib/action_view/renderer/renderer.rb +44 -1
  47. data/lib/action_view/renderer/streaming_template_renderer.rb +5 -1
  48. data/lib/action_view/renderer/template_renderer.rb +15 -12
  49. data/lib/action_view/rendering.rb +3 -1
  50. data/lib/action_view/routing_url_for.rb +1 -1
  51. data/lib/action_view/template/handlers/erb/erubi.rb +9 -7
  52. data/lib/action_view/template/handlers/erb.rb +10 -14
  53. data/lib/action_view/template/handlers.rb +0 -26
  54. data/lib/action_view/template/html.rb +1 -11
  55. data/lib/action_view/template/raw_file.rb +0 -3
  56. data/lib/action_view/template/renderable.rb +24 -0
  57. data/lib/action_view/template/resolver.rb +82 -40
  58. data/lib/action_view/template/text.rb +0 -3
  59. data/lib/action_view/template.rb +9 -49
  60. data/lib/action_view/test_case.rb +18 -25
  61. data/lib/action_view/testing/resolvers.rb +10 -31
  62. data/lib/action_view/unbound_template.rb +3 -3
  63. data/lib/action_view/view_paths.rb +34 -36
  64. data/lib/action_view.rb +4 -1
  65. data/lib/assets/compiled/rails-ujs.js +1 -1
  66. 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
- # preallocate all the default blocks for performance/memory consumption reasons
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
- # usually a majority of template look ups return nothing, use this canonical preallocated array to save memory
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
- "#<#{self.class.name}:0x#{(object_id << 1).to_s(16)} keys=#{@data.size} queries=#{@query_cache.size}>"
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. Do not call this
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(pattern = nil)
168
- if pattern
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
- super()
202
+ @path_parser = PathParser.new
203
+ super
176
204
  end
177
205
 
178
206
  def clear_cache
179
207
  @unbound_templates.clear
180
- super()
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 = Template::Sources::File.new(template)
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!(/:action/, partial)
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
- pieces = File.basename(path).split(".")
274
- pieces.shift
275
-
276
- extension = pieces.pop
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, pattern = nil)
325
+ def initialize(path)
300
326
  raise ArgumentError, "path already is a Resolver class" if path.is_a?(Resolver)
301
- super(pattern)
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 find_template_paths_from_details(path, details)
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
- Dir[query].uniq.reject do |filename|
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.reverse.map do |ext|
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.uniq.map { |e| Regexp.escape(e) }.join("|")
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}))?"
@@ -27,9 +27,6 @@ module ActionView #:nodoc:
27
27
  def format
28
28
  :text
29
29
  end
30
-
31
- def formats; Array(format); end
32
- deprecate :formats
33
30
  end
34
31
  end
35
32
  end
@@ -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, :original_encoding, :updated_at
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, locals: nil, virtual_path: nil, updated_at: 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[-1] == "/" ? "" : ::File.basename(@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.sub("#{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, @updated_at, @format, @variant ]
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, @updated_at, @format, @variant = *array
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
- attr_writer :controller_path
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 = (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
- _helpers.module_eval <<-end_eval, __FILE__, __LINE__ + 1
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
- @controller = ActionView::TestCase::TestController.new
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
- make_test_case_available_to_view!
113
- say_no_to_protect_against_forgery!
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
- private
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
- def make_test_case_available_to_view!
181
- test_case_instance = self
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 = {}, pattern = nil)
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 query(path, exts, _, locals, cache:)
31
- regex = build_regex(path, exts)
32
-
33
- @hash.select do |_path, _|
34
- ("/" + _path).match?(regex)
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, identifer, handler, options)
7
+ def initialize(source, identifier, handler, options)
8
8
  @source = source
9
- @identifer = identifer
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
- @identifer,
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-2019 David Heinemeier Hansson
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