mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Introduce a file type template, deprecate Template#refresh
Every template that specifies a "virtual path" loses the template source when the template gets compiled:eda0f574f1/actionview/lib/action_view/template.rb (L275)
The "refresh" method seems to think that the source code for a template can be recovered if there is a virtual path:eda0f574f1/actionview/lib/action_view/template.rb (L171-L188)
Every call site that allocates a template object *and* provides a "virtual path" reads the template contents from the filesystem:eda0f574f1/actionview/lib/action_view/template/resolver.rb (L229-L231)
Templates that are inline or literals don't provide a "virtual path":eda0f574f1/actionview/lib/action_view/renderer/template_renderer.rb (L34)
This commit introduces a `FileTemplate` type that subclasses `Template`. The `FileTemplate` keeps a reference to the filename, and reads the source from the filesystem. This effectively makes the template source immutable. Other classes depended on the source to be mutated while being compiled, so this commit also introduces a temporary way to pass the mutated source to the ERB (or whatever) compiler. See `LegacyTemplate`. I think we should consider it an error to provide a virtual path on a non file type template an non-file templates can't recover their source. Here is an example:eda0f574f1/actionview/lib/action_view/testing/resolvers.rb (L53)
This provides a "virtual path" so the source code (a string literal) is thrown away after compilation. Clearly we can't recover that string, so I think this should be an error.
This commit is contained in:
parent
916b74d16a
commit
2169bd3d2a
4 changed files with 47 additions and 3 deletions
|
@ -45,6 +45,7 @@ module ActionView
|
||||||
autoload :Rendering
|
autoload :Rendering
|
||||||
autoload :RoutingUrlFor
|
autoload :RoutingUrlFor
|
||||||
autoload :Template
|
autoload :Template
|
||||||
|
autoload :FileTemplate
|
||||||
autoload :ViewPaths
|
autoload :ViewPaths
|
||||||
|
|
||||||
autoload_under "renderer" do
|
autoload_under "renderer" do
|
||||||
|
|
33
actionview/lib/action_view/file_template.rb
Normal file
33
actionview/lib/action_view/file_template.rb
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "action_view/template"
|
||||||
|
|
||||||
|
module ActionView
|
||||||
|
class FileTemplate < Template
|
||||||
|
def initialize(filename, handler, details)
|
||||||
|
@filename = filename
|
||||||
|
|
||||||
|
super(nil, filename, handler, details)
|
||||||
|
end
|
||||||
|
|
||||||
|
def source
|
||||||
|
File.binread @filename
|
||||||
|
end
|
||||||
|
|
||||||
|
def refresh(_)
|
||||||
|
self
|
||||||
|
end
|
||||||
|
|
||||||
|
# Exceptions are marshalled when using the parallel test runner with DRb, so we need
|
||||||
|
# to ensure that references to the template object can be marshalled as well. This means forgoing
|
||||||
|
# the marshalling of the compiler mutex and instantiating that again on unmarshalling.
|
||||||
|
def marshal_dump # :nodoc:
|
||||||
|
[ @identifier, @handler, @compiled, @original_encoding, @locals, @virtual_path, @updated_at, @formats, @variants ]
|
||||||
|
end
|
||||||
|
|
||||||
|
def marshal_load(array) # :nodoc:
|
||||||
|
@identifier, @handler, @compiled, @original_encoding, @locals, @virtual_path, @updated_at, @formats, @variants = *array
|
||||||
|
@compile_mutex = Mutex.new
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -2,7 +2,9 @@
|
||||||
|
|
||||||
require "active_support/core_ext/object/try"
|
require "active_support/core_ext/object/try"
|
||||||
require "active_support/core_ext/kernel/singleton_class"
|
require "active_support/core_ext/kernel/singleton_class"
|
||||||
|
require "active_support/deprecation"
|
||||||
require "thread"
|
require "thread"
|
||||||
|
require "delegate"
|
||||||
|
|
||||||
module ActionView
|
module ActionView
|
||||||
# = Action View Template
|
# = Action View Template
|
||||||
|
@ -279,6 +281,15 @@ module ActionView
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class LegacyTemplate < DelegateClass(Template) # :nodoc:
|
||||||
|
attr_reader :source
|
||||||
|
|
||||||
|
def initialize(template, source)
|
||||||
|
super(template)
|
||||||
|
@source = source
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Among other things, this method is responsible for properly setting
|
# Among other things, this method is responsible for properly setting
|
||||||
# the encoding of the compiled template.
|
# the encoding of the compiled template.
|
||||||
#
|
#
|
||||||
|
@ -293,7 +304,7 @@ module ActionView
|
||||||
# regardless of the original source encoding.
|
# regardless of the original source encoding.
|
||||||
def compile(mod)
|
def compile(mod)
|
||||||
source = encode!
|
source = encode!
|
||||||
code = @handler.call(self)
|
code = @handler.call(LegacyTemplate.new(self, source))
|
||||||
|
|
||||||
# Make sure that the resulting String to be eval'd is in the
|
# Make sure that the resulting String to be eval'd is in the
|
||||||
# encoding of the code
|
# encoding of the code
|
||||||
|
|
|
@ -226,9 +226,8 @@ module ActionView
|
||||||
|
|
||||||
template_paths.map do |template|
|
template_paths.map do |template|
|
||||||
handler, format, variant = extract_handler_and_format_and_variant(template)
|
handler, format, variant = extract_handler_and_format_and_variant(template)
|
||||||
contents = File.binread(template)
|
|
||||||
|
|
||||||
Template.new(contents, File.expand_path(template), handler,
|
FileTemplate.new(File.expand_path(template), handler,
|
||||||
virtual_path: path.virtual,
|
virtual_path: path.virtual,
|
||||||
format: format,
|
format: format,
|
||||||
variant: variant,
|
variant: variant,
|
||||||
|
|
Loading…
Reference in a new issue