2017-07-01 16:09:13 -04:00
|
|
|
# frozen_string_literal: true
|
2017-07-10 09:48:09 -04:00
|
|
|
|
2016-08-06 12:48:35 -04:00
|
|
|
require "active_support/core_ext/object/try"
|
|
|
|
require "active_support/core_ext/kernel/singleton_class"
|
2019-01-31 18:34:09 -05:00
|
|
|
require "active_support/deprecation"
|
2016-08-06 12:48:35 -04:00
|
|
|
require "thread"
|
2019-01-31 18:34:09 -05:00
|
|
|
require "delegate"
|
2009-04-14 20:22:51 -04:00
|
|
|
|
2009-04-23 18:58:38 -04:00
|
|
|
module ActionView
|
2010-06-16 14:27:50 -04:00
|
|
|
# = Action View Template
|
2008-07-12 15:33:46 -04:00
|
|
|
class Template
|
2009-12-02 23:01:01 -05:00
|
|
|
extend ActiveSupport::Autoload
|
2009-12-22 18:27:37 -05:00
|
|
|
|
2018-04-03 09:28:12 -04:00
|
|
|
mattr_accessor :finalize_compiled_template_methods, default: true
|
Add `action_view.finalize_compiled_template_methods` config option
ActionView::Template instances compile their source to methods on the
ActionView::CompiledTemplates module. To prevent leaks in development
mode, where templates can frequently change, a finalizer is added that
undefines these methods[1] when the templates are garbage-collected.
This is undesirable in the test environment, however, as templates don't
change during the life of the test. Moreover, the cost of undefining a
method is proportional to the number of descendants a class or module
has, since the method cache must be cleared for all descendant classes.
As ActionView::CompiledTemplates is mixed into every
ActionView::TestCase (or in RSpec suites, every view spec example
group), it can end up with a very large number of descendants, and
undefining its methods can become very expensive.
In large test suites, this results in a long delay at the end of the
test suite as all template finalizers are run, only for the process to
then exit.
To avoid this unnecessary cost, this change adds a config option,
`action_view.finalize_compiled_template_methods`, defaulting to true,
and sets it to false in the test environment only.
[1] https://github.com/rails/rails/blob/09b2348f7fc8d4e7191e70e06608c5909067e2aa/actionview/lib/action_view/template.rb#L118-L126
2018-03-30 17:45:57 -04:00
|
|
|
|
2010-05-17 11:41:54 -04:00
|
|
|
# === Encodings in ActionView::Template
|
|
|
|
#
|
|
|
|
# ActionView::Template is one of a few sources of potential
|
|
|
|
# encoding issues in Rails. This is because the source for
|
|
|
|
# templates are usually read from disk, and Ruby (like most
|
|
|
|
# encoding-aware programming languages) assumes that the
|
|
|
|
# String retrieved through File IO is encoded in the
|
|
|
|
# <tt>default_external</tt> encoding. In Rails, the default
|
|
|
|
# <tt>default_external</tt> encoding is UTF-8.
|
|
|
|
#
|
|
|
|
# As a result, if a user saves their template as ISO-8859-1
|
|
|
|
# (for instance, using a non-Unicode-aware text editor),
|
|
|
|
# and uses characters outside of the ASCII range, their
|
|
|
|
# users will see diamonds with question marks in them in
|
|
|
|
# the browser.
|
|
|
|
#
|
2010-05-30 05:07:34 -04:00
|
|
|
# For the rest of this documentation, when we say "UTF-8",
|
|
|
|
# we mean "UTF-8 or whatever the default_internal encoding
|
|
|
|
# is set to". By default, it will be UTF-8.
|
|
|
|
#
|
2010-05-17 11:41:54 -04:00
|
|
|
# To mitigate this problem, we use a few strategies:
|
|
|
|
# 1. If the source is not valid UTF-8, we raise an exception
|
|
|
|
# when the template is compiled to alert the user
|
|
|
|
# to the problem.
|
|
|
|
# 2. The user can specify the encoding using Ruby-style
|
|
|
|
# encoding comments in any template engine. If such
|
|
|
|
# a comment is supplied, Rails will apply that encoding
|
|
|
|
# to the resulting compiled source returned by the
|
|
|
|
# template handler.
|
|
|
|
# 3. In all cases, we transcode the resulting String to
|
2010-05-30 05:07:34 -04:00
|
|
|
# the UTF-8.
|
2010-05-17 11:41:54 -04:00
|
|
|
#
|
|
|
|
# This means that other parts of Rails can always assume
|
|
|
|
# that templates are encoded in UTF-8, even if the original
|
|
|
|
# source of the template was not UTF-8.
|
|
|
|
#
|
|
|
|
# From a user's perspective, the easiest thing to do is
|
|
|
|
# to save your templates as UTF-8. If you do this, you
|
|
|
|
# do not need to do anything else for things to "just work".
|
|
|
|
#
|
|
|
|
# === Instructions for template handlers
|
|
|
|
#
|
|
|
|
# The easiest thing for you to do is to simply ignore
|
|
|
|
# encodings. Rails will hand you the template source
|
|
|
|
# as the default_internal (generally UTF-8), raising
|
|
|
|
# an exception for the user before sending the template
|
|
|
|
# to you if it could not determine the original encoding.
|
|
|
|
#
|
|
|
|
# For the greatest simplicity, you can support only
|
|
|
|
# UTF-8 as the <tt>default_internal</tt>. This means
|
|
|
|
# that from the perspective of your handler, the
|
|
|
|
# entire pipeline is just UTF-8.
|
|
|
|
#
|
|
|
|
# === Advanced: Handlers with alternate metadata sources
|
|
|
|
#
|
|
|
|
# If you want to provide an alternate mechanism for
|
|
|
|
# specifying encodings (like ERB does via <%# encoding: ... %>),
|
2010-05-30 05:07:34 -04:00
|
|
|
# you may indicate that you will handle encodings yourself
|
2016-08-07 19:05:28 -04:00
|
|
|
# by implementing <tt>handles_encoding?</tt> on your handler.
|
2010-05-17 11:41:54 -04:00
|
|
|
#
|
2010-05-30 05:07:34 -04:00
|
|
|
# If you do, Rails will not try to encode the String
|
|
|
|
# into the default_internal, passing you the unaltered
|
|
|
|
# bytes tagged with the assumed encoding (from
|
|
|
|
# default_external).
|
2010-05-17 11:41:54 -04:00
|
|
|
#
|
|
|
|
# In this case, make sure you return a String from
|
|
|
|
# your handler encoded in the default_internal. Since
|
|
|
|
# you are handling out-of-band metadata, you are
|
|
|
|
# also responsible for alerting the user to any
|
|
|
|
# problems with converting the user's data to
|
2011-05-10 18:28:37 -04:00
|
|
|
# the <tt>default_internal</tt>.
|
2010-05-17 11:41:54 -04:00
|
|
|
#
|
2013-01-26 11:36:38 -05:00
|
|
|
# To do so, simply raise +WrongEncodingError+ as follows:
|
2010-05-17 11:41:54 -04:00
|
|
|
#
|
|
|
|
# raise WrongEncodingError.new(
|
|
|
|
# problematic_string,
|
|
|
|
# expected_encoding
|
|
|
|
# )
|
|
|
|
|
2015-02-18 14:40:58 -05:00
|
|
|
##
|
|
|
|
# :method: local_assigns
|
|
|
|
#
|
|
|
|
# Returns a hash with the defined local variables.
|
|
|
|
#
|
|
|
|
# Given this sub template rendering:
|
|
|
|
#
|
|
|
|
# <%= render "shared/header", { headline: "Welcome", person: person } %>
|
|
|
|
#
|
|
|
|
# You can use +local_assigns+ in the sub templates to access the local variables:
|
|
|
|
#
|
|
|
|
# local_assigns[:headline] # => "Welcome"
|
|
|
|
|
2009-12-22 18:27:37 -05:00
|
|
|
eager_autoload do
|
|
|
|
autoload :Error
|
|
|
|
autoload :Handlers
|
2014-02-14 09:57:47 -05:00
|
|
|
autoload :HTML
|
2009-12-22 18:27:37 -05:00
|
|
|
autoload :Text
|
2012-07-05 16:02:11 -04:00
|
|
|
autoload :Types
|
2009-12-22 18:27:37 -05:00
|
|
|
end
|
|
|
|
|
2009-12-02 23:01:01 -05:00
|
|
|
extend Template::Handlers
|
2010-03-09 07:12:11 -05:00
|
|
|
|
2014-03-12 10:42:21 -04:00
|
|
|
attr_accessor :locals, :formats, :variants, :virtual_path
|
2010-10-07 09:50:20 -04:00
|
|
|
|
2010-10-10 03:24:17 -04:00
|
|
|
attr_reader :source, :identifier, :handler, :original_encoding, :updated_at
|
2009-09-24 13:30:13 -04:00
|
|
|
|
2010-09-30 05:40:51 -04:00
|
|
|
# This finalizer is needed (and exactly with a proc inside another proc)
|
|
|
|
# otherwise templates leak in development.
|
2015-02-18 14:44:57 -05:00
|
|
|
Finalizer = proc do |method_name, mod| # :nodoc:
|
2010-09-30 05:40:51 -04:00
|
|
|
proc do
|
|
|
|
mod.module_eval do
|
|
|
|
remove_possible_method method_name
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2009-04-23 18:58:38 -04:00
|
|
|
def initialize(source, identifier, handler, details)
|
2010-10-10 03:24:17 -04:00
|
|
|
format = details[:format] || (handler.default_format if handler.respond_to?(:default_format))
|
|
|
|
|
|
|
|
@source = source
|
|
|
|
@identifier = identifier
|
|
|
|
@handler = handler
|
|
|
|
@compiled = false
|
|
|
|
@original_encoding = nil
|
|
|
|
@locals = details[:locals] || []
|
|
|
|
@virtual_path = details[:virtual_path]
|
|
|
|
@updated_at = details[:updated_at] || Time.now
|
2012-07-05 16:02:11 -04:00
|
|
|
@formats = Array(format).map { |f| f.respond_to?(:ref) ? f.ref : f }
|
2014-03-12 10:42:21 -04:00
|
|
|
@variants = [details[:variant]]
|
2012-05-20 17:01:52 -04:00
|
|
|
@compile_mutex = Mutex.new
|
2009-04-14 20:22:51 -04:00
|
|
|
end
|
2009-09-24 13:30:13 -04:00
|
|
|
|
2015-09-02 22:22:18 -04:00
|
|
|
# Returns whether the underlying handler supports streaming. If so,
|
2016-12-28 04:57:53 -05:00
|
|
|
# a streaming buffer *may* be passed when it starts rendering.
|
2011-04-16 04:28:47 -04:00
|
|
|
def supports_streaming?
|
|
|
|
handler.respond_to?(:supports_streaming?) && handler.supports_streaming?
|
|
|
|
end
|
|
|
|
|
2010-10-09 17:56:08 -04:00
|
|
|
# Render a template. If the template was not compiled yet, it is done
|
|
|
|
# exactly before rendering.
|
|
|
|
#
|
|
|
|
# This method is instrumented as "!render_template.action_view". Notice that
|
|
|
|
# we use a bang in this instrumentation because you don't want to
|
|
|
|
# consume this in production. This is only slow if it's being listened to.
|
2019-01-16 18:36:55 -05:00
|
|
|
def render(view, locals, buffer = ActionView::OutputBuffer.new, &block)
|
2016-08-24 19:01:55 -04:00
|
|
|
instrument_render_template do
|
2010-10-07 09:50:20 -04:00
|
|
|
compile!(view)
|
2019-01-16 20:28:03 -05:00
|
|
|
view.run(method_name, locals, buffer, &block)
|
2010-03-17 17:19:42 -04:00
|
|
|
end
|
2013-10-24 19:09:58 -04:00
|
|
|
rescue => e
|
2010-10-09 17:56:08 -04:00
|
|
|
handle_render_error(view, e)
|
2009-04-23 18:58:38 -04:00
|
|
|
end
|
2009-09-24 13:30:13 -04:00
|
|
|
|
2012-06-15 11:17:21 -04:00
|
|
|
def type
|
2012-07-05 16:02:11 -04:00
|
|
|
@type ||= Types[@formats.first] if @formats.first
|
2010-03-09 07:12:11 -05:00
|
|
|
end
|
|
|
|
|
2010-10-09 17:56:08 -04:00
|
|
|
# Receives a view object and return a template similar to self by using @virtual_path.
|
|
|
|
#
|
|
|
|
# This method is useful if you have a template object but it does not contain its source
|
|
|
|
# anymore since it was already compiled. In such cases, all you need to do is to call
|
|
|
|
# refresh passing in the view object.
|
|
|
|
#
|
|
|
|
# Notice this method raises an error if the template to be refreshed does not have a
|
|
|
|
# virtual path set (true just for inline templates).
|
|
|
|
def refresh(view)
|
2010-10-10 07:43:32 -04:00
|
|
|
raise "A template needs to have a virtual path in order to be refreshed" unless @virtual_path
|
2012-02-21 20:55:56 -05:00
|
|
|
lookup = view.lookup_context
|
|
|
|
pieces = @virtual_path.split("/")
|
|
|
|
name = pieces.pop
|
|
|
|
partial = !!name.sub!(/^_/, "")
|
|
|
|
lookup.disable_cache do
|
2016-08-06 12:48:35 -04:00
|
|
|
lookup.find_template(name, [ pieces.join("/") ], partial, @locals)
|
2010-10-10 07:43:32 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2009-09-24 13:30:13 -04:00
|
|
|
def inspect
|
2018-02-27 23:33:37 -05:00
|
|
|
@inspect ||= defined?(Rails.root) ? identifier.sub("#{Rails.root}/", "") : identifier
|
2009-09-24 13:30:13 -04:00
|
|
|
end
|
2008-02-05 23:26:40 -05:00
|
|
|
|
2011-12-20 06:39:28 -05:00
|
|
|
# This method is responsible for properly setting the encoding of the
|
2011-12-20 05:06:37 -05:00
|
|
|
# source. Until this point, we assume that the source is BINARY data.
|
|
|
|
# If no additional information is supplied, we assume the encoding is
|
|
|
|
# the same as <tt>Encoding.default_external</tt>.
|
|
|
|
#
|
|
|
|
# The user can also specify the encoding via a comment on the first
|
|
|
|
# line of the template (# encoding: NAME-OF-ENCODING). This will work
|
|
|
|
# with any template engine, as we process out the encoding comment
|
|
|
|
# before passing the source on to the template engine, leaving a
|
|
|
|
# blank line in its stead.
|
|
|
|
def encode!
|
2019-01-31 17:06:21 -05:00
|
|
|
source = self.source
|
|
|
|
|
|
|
|
return source unless source.encoding == Encoding::BINARY
|
2011-12-20 06:39:28 -05:00
|
|
|
|
|
|
|
# Look for # encoding: *. If we find one, we'll encode the
|
|
|
|
# String in that encoding, otherwise, we'll use the
|
|
|
|
# default external encoding.
|
2016-08-06 12:48:35 -04:00
|
|
|
if source.sub!(/\A#{ENCODING_FLAG}/, "")
|
2011-12-20 06:39:28 -05:00
|
|
|
encoding = magic_encoding = $1
|
|
|
|
else
|
|
|
|
encoding = Encoding.default_external
|
|
|
|
end
|
2011-12-20 05:06:37 -05:00
|
|
|
|
2011-12-20 06:39:28 -05:00
|
|
|
# Tag the source with the default external encoding
|
|
|
|
# or the encoding specified in the file
|
|
|
|
source.force_encoding(encoding)
|
|
|
|
|
|
|
|
# If the user didn't specify an encoding, and the handler
|
|
|
|
# handles encodings, we simply pass the String as is to
|
|
|
|
# the handler (with the default_external tag)
|
|
|
|
if !magic_encoding && @handler.respond_to?(:handles_encoding?) && @handler.handles_encoding?
|
|
|
|
source
|
|
|
|
# Otherwise, if the String is valid in the encoding,
|
|
|
|
# encode immediately to default_internal. This means
|
|
|
|
# that if a handler doesn't handle encodings, it will
|
|
|
|
# always get Strings in the default_internal
|
|
|
|
elsif source.valid_encoding?
|
|
|
|
source.encode!
|
|
|
|
# Otherwise, since the String is invalid in the encoding
|
|
|
|
# specified, raise an exception
|
|
|
|
else
|
|
|
|
raise WrongEncodingError.new(source, encoding)
|
2011-12-20 05:06:37 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-10-03 16:31:40 -04:00
|
|
|
|
2018-10-02 04:09:40 -04:00
|
|
|
# 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.
|
2018-09-30 19:55:16 -04:00
|
|
|
def marshal_dump # :nodoc:
|
2018-09-30 19:50:57 -04:00
|
|
|
[ @source, @identifier, @handler, @compiled, @original_encoding, @locals, @virtual_path, @updated_at, @formats, @variants ]
|
|
|
|
end
|
|
|
|
|
2018-09-30 19:55:16 -04:00
|
|
|
def marshal_load(array) # :nodoc:
|
2018-09-30 19:50:57 -04:00
|
|
|
@source, @identifier, @handler, @compiled, @original_encoding, @locals, @virtual_path, @updated_at, @formats, @variants = *array
|
|
|
|
@compile_mutex = Mutex.new
|
|
|
|
end
|
|
|
|
|
2016-12-19 05:30:36 -05:00
|
|
|
private
|
2010-10-07 09:50:20 -04:00
|
|
|
|
2010-10-09 17:56:08 -04:00
|
|
|
# Compile a template. This method ensures a template is compiled
|
|
|
|
# just once and removes the source after it is compiled.
|
2016-12-19 05:30:36 -05:00
|
|
|
def compile!(view)
|
2010-10-09 17:56:08 -04:00
|
|
|
return if @compiled
|
2010-10-07 09:50:20 -04:00
|
|
|
|
2012-05-20 17:01:52 -04:00
|
|
|
# Templates can be used concurrently in threaded environments
|
|
|
|
# so compilation and any instance variable modification must
|
|
|
|
# be synchronized
|
|
|
|
@compile_mutex.synchronize do
|
|
|
|
# Any thread holding this lock will be compiling the template needed
|
|
|
|
# by the threads waiting. So re-check the @compiled flag to avoid
|
|
|
|
# re-compilation
|
|
|
|
return if @compiled
|
|
|
|
|
2019-01-18 18:54:37 -05:00
|
|
|
mod = view.compiled_method_container
|
2012-05-20 17:01:52 -04:00
|
|
|
|
2013-05-03 08:28:16 -04:00
|
|
|
instrument("!compile_template") do
|
2014-08-27 20:59:34 -04:00
|
|
|
compile(mod)
|
2013-05-03 08:28:16 -04:00
|
|
|
end
|
2012-05-20 17:01:52 -04:00
|
|
|
|
|
|
|
# Just discard the source if we have a virtual path. This
|
|
|
|
# means we can get the template back.
|
|
|
|
@source = nil if @virtual_path
|
|
|
|
@compiled = true
|
2010-10-09 17:56:08 -04:00
|
|
|
end
|
|
|
|
end
|
2010-10-07 09:50:20 -04:00
|
|
|
|
2019-01-31 18:34:09 -05:00
|
|
|
class LegacyTemplate < DelegateClass(Template) # :nodoc:
|
|
|
|
attr_reader :source
|
|
|
|
|
|
|
|
def initialize(template, source)
|
|
|
|
super(template)
|
|
|
|
@source = source
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2010-05-17 11:41:54 -04:00
|
|
|
# Among other things, this method is responsible for properly setting
|
2011-12-20 05:06:37 -05:00
|
|
|
# the encoding of the compiled template.
|
2010-05-17 11:41:54 -04:00
|
|
|
#
|
2010-05-30 05:07:34 -04:00
|
|
|
# If the template engine handles encodings, we send the encoded
|
|
|
|
# String to the engine without further processing. This allows
|
|
|
|
# the template engine to support additional mechanisms for
|
|
|
|
# specifying the encoding. For instance, ERB supports <%# encoding: %>
|
|
|
|
#
|
|
|
|
# Otherwise, after we figure out the correct encoding, we then
|
2011-05-10 18:28:37 -04:00
|
|
|
# encode the source into <tt>Encoding.default_internal</tt>.
|
|
|
|
# In general, this means that templates will be UTF-8 inside of Rails,
|
2010-05-17 11:41:54 -04:00
|
|
|
# regardless of the original source encoding.
|
2016-12-19 05:30:36 -05:00
|
|
|
def compile(mod)
|
2019-01-31 17:06:21 -05:00
|
|
|
source = encode!
|
2019-01-31 18:34:09 -05:00
|
|
|
code = @handler.call(LegacyTemplate.new(self, source))
|
2010-05-17 11:41:54 -04:00
|
|
|
|
2013-06-07 16:43:06 -04:00
|
|
|
# Make sure that the resulting String to be eval'd is in the
|
2010-05-30 05:07:34 -04:00
|
|
|
# encoding of the code
|
2018-05-17 04:32:27 -04:00
|
|
|
source = +<<-end_src
|
2011-04-15 20:10:36 -04:00
|
|
|
def #{method_name}(local_assigns, output_buffer)
|
2019-01-16 20:39:42 -05:00
|
|
|
@virtual_path = #{@virtual_path.inspect};#{locals_code};#{code}
|
2009-09-24 13:30:13 -04:00
|
|
|
end
|
|
|
|
end_src
|
|
|
|
|
2011-12-24 07:57:54 -05:00
|
|
|
# Make sure the source is in the encoding of the returned code
|
|
|
|
source.force_encoding(code.encoding)
|
2010-05-17 11:41:54 -04:00
|
|
|
|
2011-12-24 07:57:54 -05:00
|
|
|
# In case we get back a String from a handler that is not in
|
|
|
|
# BINARY or the default_internal, encode it to the default_internal
|
|
|
|
source.encode!
|
2010-05-17 11:41:54 -04:00
|
|
|
|
2011-12-24 07:57:54 -05:00
|
|
|
# Now, validate that the source we got back from the template
|
|
|
|
# handler is valid in the default_internal. This is for handlers
|
|
|
|
# that handle encoding but screw up
|
|
|
|
unless source.valid_encoding?
|
2019-01-31 17:06:21 -05:00
|
|
|
raise WrongEncodingError.new(source, Encoding.default_internal)
|
2009-04-23 18:58:38 -04:00
|
|
|
end
|
2008-07-12 15:33:46 -04:00
|
|
|
|
2014-08-27 20:58:59 -04:00
|
|
|
mod.module_eval(source, identifier, 0)
|
Add `action_view.finalize_compiled_template_methods` config option
ActionView::Template instances compile their source to methods on the
ActionView::CompiledTemplates module. To prevent leaks in development
mode, where templates can frequently change, a finalizer is added that
undefines these methods[1] when the templates are garbage-collected.
This is undesirable in the test environment, however, as templates don't
change during the life of the test. Moreover, the cost of undefining a
method is proportional to the number of descendants a class or module
has, since the method cache must be cleared for all descendant classes.
As ActionView::CompiledTemplates is mixed into every
ActionView::TestCase (or in RSpec suites, every view spec example
group), it can end up with a very large number of descendants, and
undefining its methods can become very expensive.
In large test suites, this results in a long delay at the end of the
test suite as all template finalizers are run, only for the process to
then exit.
To avoid this unnecessary cost, this change adds a config option,
`action_view.finalize_compiled_template_methods`, defaulting to true,
and sets it to false in the test environment only.
[1] https://github.com/rails/rails/blob/09b2348f7fc8d4e7191e70e06608c5909067e2aa/actionview/lib/action_view/template.rb#L118-L126
2018-03-30 17:45:57 -04:00
|
|
|
if finalize_compiled_template_methods
|
|
|
|
ObjectSpace.define_finalizer(self, Finalizer[method_name, mod])
|
|
|
|
end
|
2009-04-23 18:58:38 -04:00
|
|
|
end
|
2009-08-14 15:00:52 -04:00
|
|
|
|
2016-12-19 05:30:36 -05:00
|
|
|
def handle_render_error(view, e)
|
2010-10-09 17:56:08 -04:00
|
|
|
if e.is_a?(Template::Error)
|
|
|
|
e.sub_template_of(self)
|
|
|
|
raise e
|
|
|
|
else
|
2011-12-20 05:06:37 -05:00
|
|
|
template = self
|
|
|
|
unless template.source
|
|
|
|
template = refresh(view)
|
|
|
|
template.encode!
|
|
|
|
end
|
2015-11-03 09:54:34 -05:00
|
|
|
raise Template::Error.new(template)
|
2010-10-07 15:30:19 -04:00
|
|
|
end
|
2010-10-07 09:50:20 -04:00
|
|
|
end
|
|
|
|
|
2016-12-19 05:30:36 -05:00
|
|
|
def locals_code
|
2016-09-30 13:55:38 -04:00
|
|
|
# Only locals with valid variable names get set directly. Others will
|
|
|
|
# still be available in local_assigns.
|
2016-12-08 14:55:21 -05:00
|
|
|
locals = @locals - Module::RUBY_RESERVED_KEYWORDS
|
2017-01-15 08:41:39 -05:00
|
|
|
locals = locals.grep(/\A@?(?![A-Z0-9])(?:[[:alnum:]_]|[^\0-\177])+\z/)
|
2016-09-30 13:55:38 -04:00
|
|
|
|
2017-09-02 01:49:12 -04:00
|
|
|
# Assign for the same variable is to suppress unused variable warning
|
2018-05-17 04:32:27 -04:00
|
|
|
locals.each_with_object(+"") { |key, code| code << "#{key} = local_assigns[:#{key}]; #{key} = #{key};" }
|
2010-10-09 17:56:08 -04:00
|
|
|
end
|
|
|
|
|
2016-12-23 06:39:54 -05:00
|
|
|
def method_name
|
2014-10-07 06:59:58 -04:00
|
|
|
@method_name ||= begin
|
2018-05-17 04:32:27 -04:00
|
|
|
m = +"_#{identifier_method_name}__#{@identifier.hash}_#{__id__}"
|
2018-02-27 23:33:37 -05:00
|
|
|
m.tr!("-", "_")
|
2014-10-07 06:59:58 -04:00
|
|
|
m
|
|
|
|
end
|
2010-06-29 12:21:24 -04:00
|
|
|
end
|
|
|
|
|
2016-12-19 05:30:36 -05:00
|
|
|
def identifier_method_name
|
2018-02-27 23:33:37 -05:00
|
|
|
inspect.tr("^a-z_", "_")
|
2009-09-24 13:30:13 -04:00
|
|
|
end
|
2013-05-03 08:28:16 -04:00
|
|
|
|
2016-12-19 05:30:36 -05:00
|
|
|
def instrument(action, &block) # :doc:
|
2017-02-19 09:58:35 -05:00
|
|
|
ActiveSupport::Notifications.instrument("#{action}.action_view", instrument_payload, &block)
|
2016-08-24 19:01:55 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def instrument_render_template(&block)
|
2018-02-27 23:33:37 -05:00
|
|
|
ActiveSupport::Notifications.instrument("!render_template.action_view", instrument_payload, &block)
|
2016-08-24 19:01:55 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def instrument_payload
|
|
|
|
{ virtual_path: @virtual_path, identifier: @identifier }
|
2013-05-03 08:28:16 -04:00
|
|
|
end
|
2009-04-23 18:58:38 -04:00
|
|
|
end
|
2009-05-28 18:12:28 -04:00
|
|
|
end
|