ActionView::Template (original) (raw)
Action View Template
Namespace
- MODULE ActionView::Template::Handlers
- MODULE ActionView::Template::Sources
Methods
E
I
L
M
N
R
S
T
Constants
NONE | = | Object.new |
---|---|---|
STRICT_LOCALS_REGEX | = | /\#\s+locals:\s+\((.*)\)/ |
Attributes
[R] | format |
---|---|
[RW] | frozen_string_literal |
[R] | handler |
[R] | identifier |
[R] | variable |
[R] | variant |
[R] | virtual_path |
Class Public methods
mime_types_implementation=(implementation)Link
def mime_types_implementation=(implementation)
if self::Types != implementation remove_const(:Types) const_set(:Types, implementation) end end
new(source, identifier, handler, locals:, format: nil, variant: nil, virtual_path: nil)Link
def initialize(source, identifier, handler, locals:, format: nil, variant: nil, virtual_path: nil) @source = source.dup @identifier = identifier @handler = handler @compiled = false @locals = locals @virtual_path = virtual_path
@variable = if @virtual_path base = @virtual_path.end_with?("/") ? "" : ::File.basename(@virtual_path) base =~ /\A_?(.*?)(?:.\w+)*\z/ $1.to_sym end
@format = format @variant = variant @compile_mutex = Mutex.new @strict_locals = NONE @strict_local_keys = nil @type = nil end
Instance Public methods
encode!()Link
This method is responsible for properly setting the encoding of the 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 Encoding.default_external
.
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! source = self.source
return source unless source.encoding == Encoding::BINARY
if source.sub!(LEADING_ENCODING_REGEXP, "") encoding = magic_encoding = $1 else encoding = Encoding.default_external end
source.force_encoding(encoding)
if !magic_encoding && @handler.respond_to?(:handles_encoding?) && @handler.handles_encoding? source
elsif source.valid_encoding? source.encode!
else raise WrongEncodingError.new(source, encoding) end end
inspect()Link
def inspect "#<#{self.class.name} #{short_identifier} locals=#{locals.inspect}>" end
local_assigns Link
Returns a hash with the defined local variables.
Given this sub template rendering:
<%= render "application/header", { headline: "Welcome", person: person } %>
You can use local_assigns in the sub templates to access the local variables:
local_assigns[:headline] # => "Welcome"
Each key in local_assigns is available as a partial-local variable:
local_assigns[:headline] # => "Welcome"
headline # => "Welcome"
Since local_assigns is a Hash, it’s compatible with Ruby 3.1’s pattern matching assignment operator:
local_assigns => { headline:, **options }
headline # => "Welcome"
options # => {}
Pattern matching assignment also supports variable renaming:
local_assigns => { headline: title }
title # => "Welcome"
If a template refers to a variable that isn’t passed into the view as part of the locals: { ... }
Hash, the template will raise an ActionView::Template::Error
:
<%# => raises ActionView::Template::Error %>
<% alerts.each do |alert| %>
<p><%= alert %></p>
<% end %>
Since local_assigns returns a Hash instance, you can conditionally read a variable, then fall back to a default value when the key isn’t part of the locals: { ... }
options:
<% local_assigns.fetch(:alerts, []).each do |alert| %>
<p><%= alert %></p>
<% end %>
Combining Ruby 3.1’s pattern matching assignment with calls to +Hash#with_defaults+ enables compact partial-local variable assignments:
<% local_assigns.with_defaults(alerts: []) => { headline:, alerts: } %>
<h1><%= headline %></h1>
<% alerts.each do |alert| %>
<p><%= alert %></p>
<% end %>
By default, templates will accept any locals
as keyword arguments and make them available to local_assigns. To restrict what local_assigns a template will accept, add a locals:
magic comment:
<%# locals: (headline:, alerts: []) %>
<h1><%= headline %></h1>
<% alerts.each do |alert| %>
<p><%= alert %></p>
<% end %>
Read more about strict locals in Action View Overview in the guides.
eager_autoload do autoload :Error autoload :RawFile autoload :Renderable autoload :Handlers autoload :HTML autoload :Inline autoload :Types autoload :Sources autoload :Text autoload :Types end
locals()Link
The locals this template has been or will be compiled for, or nil if this is a strict locals template.
def locals if strict_locals? nil else @locals end end
render(view, locals, buffer = nil, implicit_locals: [], add_to_stack: true, &block)Link
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.
def render(view, locals, buffer = nil, implicit_locals: [], add_to_stack: true, &block) instrument_render_template do compile!(view)
if strict_locals? && @strict_local_keys && !implicit_locals.empty?
locals_to_ignore = implicit_locals - @strict_local_keys
locals.except!(*locals_to_ignore)
end
if buffer
view._run(method_name, self, locals, buffer, add_to_stack: add_to_stack, has_strict_locals: strict_locals?, &block)
nil
else
result = view._run(method_name, self, locals, OutputBuffer.new, add_to_stack: add_to_stack, has_strict_locals: strict_locals?, &block)
result.is_a?(OutputBuffer) ? result.to_s : result
end
end rescue => e handle_render_error(view, e) end
short_identifier()Link
def short_identifier @short_identifier ||= defined?(Rails.root) ? identifier.delete_prefix("#{Rails.root}/") : identifier end
strict_locals!()Link
This method is responsible for marking a template as having strict locals which means the template can only accept the locals defined in a magic comment. For example, if your template accepts the locals title
and comment_count
, add the following to your template file:
<%# locals: (title: "Default title", comment_count: 0) %>
Strict locals are useful for validating template arguments and for specifying defaults.
def strict_locals! if @strict_locals == NONE self.source.sub!(STRICT_LOCALS_REGEX, "") @strict_locals = $1
return if @strict_locals.nil?
@strict_locals = "**nil" if @strict_locals.blank?
end
@strict_locals end
strict_locals?()Link
Returns whether a template is using strict locals.
supports_streaming?()Link
Returns whether the underlying handler supports streaming. If so, a streaming buffer may be passed when it starts rendering.
def supports_streaming? handler.respond_to?(:supports_streaming?) && handler.supports_streaming? end
translate_location(backtrace_location, spot)Link
Translate an error location returned by ErrorHighlight to the correct source location inside the template.
def translate_location(backtrace_location, spot) if handler.respond_to?(:translate_location) handler.translate_location(spot, backtrace_location, encode!) || spot else spot end end
Instance Private methods
instrument(action, &block)Link
def instrument(action, &block) ActiveSupport::Notifications.instrument("#{action}.action_view", instrument_payload, &block) end