actionview 6.0.0.beta1 → 6.1.0

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 (86) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +206 -119
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +4 -2
  5. data/lib/action_view/base.rb +81 -15
  6. data/lib/action_view/cache_expiry.rb +52 -0
  7. data/lib/action_view/context.rb +0 -6
  8. data/lib/action_view/dependency_tracker.rb +10 -4
  9. data/lib/action_view/digestor.rb +11 -19
  10. data/lib/action_view/flows.rb +0 -1
  11. data/lib/action_view/gem_version.rb +2 -2
  12. data/lib/action_view/helpers/active_model_helper.rb +0 -1
  13. data/lib/action_view/helpers/asset_tag_helper.rb +46 -21
  14. data/lib/action_view/helpers/asset_url_helper.rb +6 -4
  15. data/lib/action_view/helpers/atom_feed_helper.rb +2 -1
  16. data/lib/action_view/helpers/cache_helper.rb +16 -23
  17. data/lib/action_view/helpers/csp_helper.rb +4 -2
  18. data/lib/action_view/helpers/date_helper.rb +5 -6
  19. data/lib/action_view/helpers/form_helper.rb +63 -21
  20. data/lib/action_view/helpers/form_options_helper.rb +10 -18
  21. data/lib/action_view/helpers/form_tag_helper.rb +12 -9
  22. data/lib/action_view/helpers/javascript_helper.rb +7 -5
  23. data/lib/action_view/helpers/number_helper.rb +9 -8
  24. data/lib/action_view/helpers/output_safety_helper.rb +1 -1
  25. data/lib/action_view/helpers/rendering_helper.rb +17 -7
  26. data/lib/action_view/helpers/sanitize_helper.rb +10 -16
  27. data/lib/action_view/helpers/tag_helper.rb +94 -19
  28. data/lib/action_view/helpers/tags/base.rb +10 -7
  29. data/lib/action_view/helpers/tags/check_box.rb +0 -1
  30. data/lib/action_view/helpers/tags/collection_check_boxes.rb +0 -1
  31. data/lib/action_view/helpers/tags/collection_helpers.rb +0 -1
  32. data/lib/action_view/helpers/tags/collection_radio_buttons.rb +0 -1
  33. data/lib/action_view/helpers/tags/color_field.rb +0 -1
  34. data/lib/action_view/helpers/tags/date_field.rb +1 -2
  35. data/lib/action_view/helpers/tags/date_select.rb +2 -3
  36. data/lib/action_view/helpers/tags/datetime_field.rb +0 -1
  37. data/lib/action_view/helpers/tags/datetime_local_field.rb +1 -2
  38. data/lib/action_view/helpers/tags/label.rb +4 -1
  39. data/lib/action_view/helpers/tags/month_field.rb +1 -2
  40. data/lib/action_view/helpers/tags/radio_button.rb +0 -1
  41. data/lib/action_view/helpers/tags/select.rb +1 -2
  42. data/lib/action_view/helpers/tags/text_field.rb +0 -1
  43. data/lib/action_view/helpers/tags/time_field.rb +1 -2
  44. data/lib/action_view/helpers/tags/week_field.rb +1 -2
  45. data/lib/action_view/helpers/text_helper.rb +1 -2
  46. data/lib/action_view/helpers/translation_helper.rb +99 -54
  47. data/lib/action_view/helpers/url_helper.rb +109 -15
  48. data/lib/action_view/layouts.rb +8 -10
  49. data/lib/action_view/log_subscriber.rb +26 -11
  50. data/lib/action_view/lookup_context.rb +59 -31
  51. data/lib/action_view/path_set.rb +3 -12
  52. data/lib/action_view/railtie.rb +36 -42
  53. data/lib/action_view/record_identifier.rb +0 -1
  54. data/lib/action_view/renderer/abstract_renderer.rb +142 -11
  55. data/lib/action_view/renderer/collection_renderer.rb +192 -0
  56. data/lib/action_view/renderer/object_renderer.rb +34 -0
  57. data/lib/action_view/renderer/partial_renderer/collection_caching.rb +35 -29
  58. data/lib/action_view/renderer/partial_renderer.rb +21 -273
  59. data/lib/action_view/renderer/renderer.rb +59 -4
  60. data/lib/action_view/renderer/streaming_template_renderer.rb +9 -7
  61. data/lib/action_view/renderer/template_renderer.rb +35 -27
  62. data/lib/action_view/rendering.rb +49 -29
  63. data/lib/action_view/routing_url_for.rb +1 -1
  64. data/lib/action_view/template/error.rb +30 -15
  65. data/lib/action_view/template/handlers/builder.rb +2 -2
  66. data/lib/action_view/template/handlers/erb/erubi.rb +15 -9
  67. data/lib/action_view/template/handlers/erb.rb +14 -19
  68. data/lib/action_view/template/handlers/html.rb +1 -1
  69. data/lib/action_view/template/handlers/raw.rb +2 -2
  70. data/lib/action_view/template/handlers.rb +1 -1
  71. data/lib/action_view/template/html.rb +5 -6
  72. data/lib/action_view/template/inline.rb +22 -0
  73. data/lib/action_view/template/raw_file.rb +25 -0
  74. data/lib/action_view/template/renderable.rb +24 -0
  75. data/lib/action_view/template/resolver.rb +141 -140
  76. data/lib/action_view/template/sources/file.rb +17 -0
  77. data/lib/action_view/template/sources.rb +13 -0
  78. data/lib/action_view/template/text.rb +2 -3
  79. data/lib/action_view/template.rb +49 -75
  80. data/lib/action_view/test_case.rb +20 -28
  81. data/lib/action_view/testing/resolvers.rb +18 -27
  82. data/lib/action_view/unbound_template.rb +31 -0
  83. data/lib/action_view/view_paths.rb +59 -38
  84. data/lib/action_view.rb +7 -2
  85. data/lib/assets/compiled/rails-ujs.js +22 -13
  86. metadata +30 -18
@@ -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,31 +93,16 @@ 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
65
100
  def cache(key, name, prefix, partial, locals)
66
- if Resolver.caching?
67
- @data[key][name][prefix][partial][locals] ||= canonical_no_templates(yield)
68
- else
69
- fresh_templates = yield
70
- cached_templates = @data[key][name][prefix][partial][locals]
71
-
72
- if templates_have_changed?(cached_templates, fresh_templates)
73
- @data[key][name][prefix][partial][locals] = canonical_no_templates(fresh_templates)
74
- else
75
- cached_templates || NO_TEMPLATES
76
- end
77
- end
101
+ @data[key][name][prefix][partial][locals] ||= canonical_no_templates(yield)
78
102
  end
79
103
 
80
104
  def cache_query(query) # :nodoc:
81
- if Resolver.caching?
82
- @query_cache[query] ||= canonical_no_templates(yield)
83
- else
84
- yield
85
- end
105
+ @query_cache[query] ||= canonical_no_templates(yield)
86
106
  end
87
107
 
88
108
  def clear
@@ -90,7 +110,7 @@ module ActionView
90
110
  @query_cache.clear
91
111
  end
92
112
 
93
- # Get the cache size. Do not call this
113
+ # Get the cache size. Do not call this
94
114
  # method. This method is not guaranteed to be here ever.
95
115
  def size # :nodoc:
96
116
  size = 0
@@ -108,23 +128,9 @@ module ActionView
108
128
  end
109
129
 
110
130
  private
111
-
112
131
  def canonical_no_templates(templates)
113
132
  templates.empty? ? NO_TEMPLATES : templates
114
133
  end
115
-
116
- def templates_have_changed?(cached_templates, fresh_templates)
117
- # if either the old or new template list is empty, we don't need to (and can't)
118
- # compare modification times, and instead just check whether the lists are different
119
- if cached_templates.blank? || fresh_templates.blank?
120
- return fresh_templates.blank? != cached_templates.blank?
121
- end
122
-
123
- cached_templates_max_updated_at = cached_templates.map(&:updated_at).max
124
-
125
- # if a template has changed, it will be now be newer than all the cached templates
126
- fresh_templates.any? { |t| t.updated_at > cached_templates_max_updated_at }
127
- end
128
134
  end
129
135
 
130
136
  cattr_accessor :caching, default: true
@@ -143,14 +149,10 @@ module ActionView
143
149
 
144
150
  # Normalizes the arguments and passes it on to find_templates.
145
151
  def find_all(name, prefix = nil, partial = false, details = {}, key = nil, locals = [])
146
- cached(key, [name, prefix, partial], details, locals) do
147
- find_templates(name, prefix, partial, details)
148
- end
149
- end
152
+ locals = locals.map(&:to_s).sort!.freeze
150
153
 
151
- def find_all_anywhere(name, prefix, partial = false, details = {}, key = nil, locals = [])
152
154
  cached(key, [name, prefix, partial], details, locals) do
153
- find_templates(name, prefix, partial, details, true)
155
+ _find_all(name, prefix, partial, details, key, locals)
154
156
  end
155
157
  end
156
158
 
@@ -159,19 +161,17 @@ module ActionView
159
161
  end
160
162
 
161
163
  private
164
+ def _find_all(name, prefix, partial, details, key, locals)
165
+ find_templates(name, prefix, partial, details, locals)
166
+ end
162
167
 
163
168
  delegate :caching?, to: :class
164
169
 
165
170
  # This is what child classes implement. No defaults are needed
166
171
  # because Resolver guarantees that the arguments are present and
167
172
  # normalized.
168
- def find_templates(name, prefix, partial, details, outside_app_allowed = false)
169
- raise NotImplementedError, "Subclasses must implement a find_templates(name, prefix, partial, details, outside_app_allowed = false) method"
170
- end
171
-
172
- # Helpers that builds a path. Useful for building virtual paths.
173
- def build_path(name, prefix, partial)
174
- Path.build(name, prefix, partial)
173
+ def find_templates(name, prefix, partial, details, locals = [])
174
+ raise NotImplementedError, "Subclasses must implement a find_templates(name, prefix, partial, details, locals = []) method"
175
175
  end
176
176
 
177
177
  # Handles templates caching. If a key is given and caching is on
@@ -180,25 +180,13 @@ module ActionView
180
180
  # resolver is fresher before returning it.
181
181
  def cached(key, path_info, details, locals)
182
182
  name, prefix, partial = path_info
183
- locals = locals.map(&:to_s).sort!
184
183
 
185
184
  if key
186
185
  @cache.cache(key, name, prefix, partial, locals) do
187
- decorate(yield, path_info, details, locals)
186
+ yield
188
187
  end
189
188
  else
190
- decorate(yield, path_info, details, locals)
191
- end
192
- end
193
-
194
- # Ensures all the resolver information is set in the template.
195
- def decorate(templates, path_info, details, locals)
196
- cached = nil
197
- templates.each do |t|
198
- t.locals = locals
199
- t.formats = details[:formats] || [:html] if t.formats.empty?
200
- t.variants = details[:variants] || [] if t.variants.empty?
201
- t.virtual_path ||= (cached ||= build_path(*path_info))
189
+ yield
202
190
  end
203
191
  end
204
192
  end
@@ -208,40 +196,70 @@ module ActionView
208
196
  EXTENSIONS = { locale: ".", formats: ".", variants: "+", handlers: "." }
209
197
  DEFAULT_PATTERN = ":prefix/:action{.:locale,}{.:formats,}{+:variants,}{.:handlers,}"
210
198
 
211
- def initialize(pattern = nil)
212
- @pattern = pattern || DEFAULT_PATTERN
213
- super()
199
+ def initialize
200
+ @pattern = DEFAULT_PATTERN
201
+ @unbound_templates = Concurrent::Map.new
202
+ @path_parser = PathParser.new
203
+ super
214
204
  end
215
205
 
216
- private
206
+ def clear_cache
207
+ @unbound_templates.clear
208
+ @path_parser = PathParser.new
209
+ super
210
+ end
217
211
 
218
- def find_templates(name, prefix, partial, details, outside_app_allowed = false)
212
+ private
213
+ def _find_all(name, prefix, partial, details, key, locals)
219
214
  path = Path.build(name, prefix, partial)
220
- query(path, details, details[:formats], outside_app_allowed)
215
+ query(path, details, details[:formats], locals, cache: !!key)
221
216
  end
222
217
 
223
- def query(path, details, formats, outside_app_allowed)
218
+ def query(path, details, formats, locals, cache:)
224
219
  template_paths = find_template_paths_from_details(path, details)
225
- template_paths = reject_files_external_to_app(template_paths) unless outside_app_allowed
220
+ template_paths = reject_files_external_to_app(template_paths)
226
221
 
227
222
  template_paths.map do |template|
228
- handler, format, variant = extract_handler_and_format_and_variant(template)
229
- contents = File.binread(template)
230
-
231
- Template.new(contents, File.expand_path(template), handler,
232
- virtual_path: path.virtual,
233
- format: format,
234
- variant: variant,
235
- updated_at: mtime(template)
236
- )
223
+ unbound_template =
224
+ if cache
225
+ @unbound_templates.compute_if_absent([template, path.virtual]) do
226
+ build_unbound_template(template, path.virtual)
227
+ end
228
+ else
229
+ build_unbound_template(template, path.virtual)
230
+ end
231
+
232
+ unbound_template.bind_locals(locals)
237
233
  end
238
234
  end
239
235
 
236
+ def source_for_template(template)
237
+ Template::Sources::File.new(template)
238
+ end
239
+
240
+ def build_unbound_template(template, virtual_path)
241
+ handler, format, variant = extract_handler_and_format_and_variant(template)
242
+ source = source_for_template(template)
243
+
244
+ UnboundTemplate.new(
245
+ source,
246
+ template,
247
+ handler,
248
+ virtual_path: virtual_path,
249
+ format: format,
250
+ variant: variant,
251
+ )
252
+ end
253
+
240
254
  def reject_files_external_to_app(files)
241
255
  files.reject { |filename| !inside_path?(@path, filename) }
242
256
  end
243
257
 
244
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
+
245
263
  query = build_query(path, details)
246
264
  find_template_paths(query)
247
265
  end
@@ -268,7 +286,7 @@ module ActionView
268
286
  query.gsub!(/:prefix(\/)?/, prefix)
269
287
 
270
288
  partial = escape_entry(path.partial? ? "_#{path.name}" : path.name)
271
- query.gsub!(/:action/, partial)
289
+ query.gsub!(":action", partial)
272
290
 
273
291
  details.each do |ext, candidates|
274
292
  if ext == :variants && candidates == :any
@@ -285,70 +303,28 @@ module ActionView
285
303
  entry.gsub(/[*?{}\[\]]/, '\\\\\\&')
286
304
  end
287
305
 
288
- # Returns the file mtime from the filesystem.
289
- def mtime(p)
290
- File.mtime(p)
291
- end
292
-
293
306
  # Extract handler, formats and variant from path. If a format cannot be found neither
294
307
  # from the path, or the handler, we should return the array of formats given
295
308
  # to the resolver.
296
309
  def extract_handler_and_format_and_variant(path)
297
- pieces = File.basename(path).split(".")
298
- pieces.shift
299
-
300
- extension = pieces.pop
310
+ details = @path_parser.parse(path)
301
311
 
302
- handler = Template.handler_for_extension(extension)
303
- format, variant = pieces.last.split(EXTENSIONS[:variants], 2) if pieces.last
304
- format &&= Template::Types[format]
312
+ handler = Template.handler_for_extension(details[:handler])
313
+ format = details[:format] || handler.try(:default_format)
314
+ variant = details[:variant]
305
315
 
316
+ # Template::Types[format] and handler.default_format can return nil
306
317
  [handler, format, variant]
307
318
  end
308
319
  end
309
320
 
310
- # A resolver that loads files from the filesystem. It allows setting your own
311
- # resolving pattern. Such pattern can be a glob string supported by some variables.
312
- #
313
- # ==== Examples
314
- #
315
- # Default pattern, loads views the same way as previous versions of rails, eg. when you're
316
- # looking for <tt>users/new</tt> it will produce query glob: <tt>users/new{.{en},}{.{html,js},}{.{erb,haml},}</tt>
317
- #
318
- # FileSystemResolver.new("/path/to/views", ":prefix/:action{.:locale,}{.:formats,}{+:variants,}{.:handlers,}")
319
- #
320
- # This one allows you to keep files with different formats in separate subdirectories,
321
- # eg. <tt>users/new.html</tt> will be loaded from <tt>users/html/new.erb</tt> or <tt>users/new.html.erb</tt>,
322
- # <tt>users/new.js</tt> from <tt>users/js/new.erb</tt> or <tt>users/new.js.erb</tt>, etc.
323
- #
324
- # FileSystemResolver.new("/path/to/views", ":prefix/{:formats/,}:action{.:locale,}{.:formats,}{+:variants,}{.:handlers,}")
325
- #
326
- # If you don't specify a pattern then the default will be used.
327
- #
328
- # In order to use any of the customized resolvers above in a Rails application, you just need
329
- # to configure ActionController::Base.view_paths in an initializer, for example:
330
- #
331
- # ActionController::Base.view_paths = FileSystemResolver.new(
332
- # Rails.root.join("app/views"),
333
- # ":prefix/:action{.:locale,}{.:formats,}{+:variants,}{.:handlers,}",
334
- # )
335
- #
336
- # ==== Pattern format and variables
337
- #
338
- # Pattern has to be a valid glob string, and it allows you to use the
339
- # following variables:
340
- #
341
- # * <tt>:prefix</tt> - usually the controller path
342
- # * <tt>:action</tt> - name of the action
343
- # * <tt>:locale</tt> - possible locale versions
344
- # * <tt>:formats</tt> - possible request formats (for example html, json, xml...)
345
- # * <tt>:variants</tt> - possible request variants (for example phone, tablet...)
346
- # * <tt>:handlers</tt> - possible handlers (for example erb, haml, builder...)
347
- #
321
+ # A resolver that loads files from the filesystem.
348
322
  class FileSystemResolver < PathResolver
349
- def initialize(path, pattern = nil)
323
+ attr_reader :path
324
+
325
+ def initialize(path)
350
326
  raise ArgumentError, "path already is a Resolver class" if path.is_a?(Resolver)
351
- super(pattern)
327
+ super()
352
328
  @path = File.expand_path(path)
353
329
  end
354
330
 
@@ -365,16 +341,32 @@ module ActionView
365
341
 
366
342
  # An Optimized resolver for Rails' most common case.
367
343
  class OptimizedFileSystemResolver < FileSystemResolver #:nodoc:
368
- private
344
+ def initialize(path)
345
+ super(path)
346
+ end
369
347
 
370
- def find_template_paths_from_details(path, details)
348
+ private
349
+ def find_candidate_template_paths(path)
371
350
  # Instead of checking for every possible path, as our other globs would
372
351
  # do, scan the directory for files with the right prefix.
373
352
  query = "#{escape_entry(File.join(@path, path))}*"
374
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
+
375
367
  regex = build_regex(path, details)
376
368
 
377
- Dir[query].uniq.reject do |filename|
369
+ candidates.uniq.reject do |filename|
378
370
  # This regex match does double duty of finding only files which match
379
371
  # details (instead of just matching the prefix) and also filtering for
380
372
  # case-insensitive file systems.
@@ -386,7 +378,7 @@ module ActionView
386
378
  # We can use the matches found by the regex and sort by their index in
387
379
  # details.
388
380
  match = filename.match(regex)
389
- EXTENSIONS.keys.reverse.map do |ext|
381
+ EXTENSIONS.keys.map do |ext|
390
382
  if ext == :variants && details[ext] == :any
391
383
  match[ext].nil? ? 0 : 1
392
384
  elsif match[ext].nil?
@@ -401,13 +393,16 @@ module ActionView
401
393
  end
402
394
 
403
395
  def build_regex(path, details)
404
- query = escape_entry(File.join(@path, path))
396
+ query = Regexp.escape(File.join(@path, path))
405
397
  exts = EXTENSIONS.map do |ext, prefix|
406
398
  match =
407
399
  if ext == :variants && details[ext] == :any
408
400
  ".*?"
409
401
  else
410
- 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("|")
411
406
  end
412
407
  prefix = Regexp.escape(prefix)
413
408
  "(#{prefix}(?<#{ext}>#{match}))?"
@@ -420,12 +415,18 @@ module ActionView
420
415
  # The same as FileSystemResolver but does not allow templates to store
421
416
  # a virtual path since it is invalid for such resolvers.
422
417
  class FallbackFileSystemResolver < FileSystemResolver #:nodoc:
418
+ private_class_method :new
419
+
423
420
  def self.instances
424
421
  [new(""), new("/")]
425
422
  end
426
423
 
427
- def decorate(*)
428
- super.each { |t| t.virtual_path = nil }
424
+ def build_unbound_template(template, _)
425
+ super(template, nil)
426
+ end
427
+
428
+ def reject_files_external_to_app(files)
429
+ files
429
430
  end
430
431
  end
431
432
  end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionView
4
+ class Template
5
+ module Sources
6
+ class File
7
+ def initialize(filename)
8
+ @filename = filename
9
+ end
10
+
11
+ def to_s
12
+ ::File.binread @filename
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionView
4
+ class Template
5
+ module Sources
6
+ extend ActiveSupport::Autoload
7
+
8
+ eager_autoload do
9
+ autoload :File
10
+ end
11
+ end
12
+ end
13
+ end
@@ -8,7 +8,6 @@ module ActionView #:nodoc:
8
8
 
9
9
  def initialize(string)
10
10
  @string = string.to_s
11
- @type = Types[:text]
12
11
  end
13
12
 
14
13
  def identifier
@@ -25,8 +24,8 @@ module ActionView #:nodoc:
25
24
  to_str
26
25
  end
27
26
 
28
- def formats
29
- [@type.ref]
27
+ def format
28
+ :text
30
29
  end
31
30
  end
32
31
  end