class ActionView::Template
Шаблон Action View
Константы
- NONE
- STRICT_LOCALS_REGEX
Атрибуты
Публичные методы класса
# File actionview/lib/action_view/template.rb, line 184
def mime_types_implementation=(implementation)
# This method isn't thread-safe, but it's not supposed
# to be called after initialization
if self::Types != implementation
remove_const(:Types)
const_set(:Types, implementation)
end
end # File actionview/lib/action_view/template.rb, line 199
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 Публичные методы экземпляра
# File actionview/lib/action_view/template.rb, line 321
def encode!
source = self.source
return source unless source.encoding == Encoding::BINARY
# Look for # encoding: *. If we find one, we'll encode the
# String in that encoding, otherwise, we'll use the
# default external encoding.
if source.sub!(LEADING_ENCODING_REGEXP, "")
encoding = magic_encoding = $1
else
encoding = Encoding.default_external
end
# 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)
end
end Этот метод отвечает за правильную установку кодировки исходного текста. До этого момента мы считаем, что исходный текст представляет собой двоичные данные. Если дополнительные сведения не указаны, мы предполагаем, что кодировка совпадает с Encoding.default_external.
Пользователь также может указать кодировку с помощью комментария в первой строке шаблона (# encoding: NAME-OF-ENCODING). Это работает с любым движком шаблонов: перед передачей исходного текста движку мы удаляем комментарий с указанием кодировки, оставляя вместо него пустую строку.
# File actionview/lib/action_view/template.rb, line 300
def inspect
"#<#{self.class.name} #{short_identifier} locals=#{locals.inspect}>"
end # File actionview/lib/action_view/template.rb, line 165 eager_autoload do autoload :Error autoload :RawFile autoload :Renderable autoload :Handlers autoload :HTML autoload :Inline autoload :Types autoload :Sources autoload :Text autoload :Types end
Возвращает хеш с определёнными локальными переменными.
Для следующего рендеринга подшаблона:
<%= render "application/header", { headline: "Welcome", person: person } %> В подшаблонах можно использовать local_assigns, чтобы получить доступ к локальным переменным:
local_assigns[:headline] # => "Welcome"
Каждый ключ в local_assigns доступен как локальная переменная партиала:
local_assigns[:headline] # => "Welcome" headline # => "Welcome"
Поскольку local_assigns — это Hash, он совместим с оператором сопоставления с образцом при присваивании, появившимся в Ruby 3.1:
local_assigns => { headline:, **options }
headline # => "Welcome"
options # => {}
Сопоставление с образцом при присваивании также поддерживает переименование переменных:
local_assigns => { headline: title }
title # => "Welcome"
Если шаблон обращается к переменной, которая не была передана в представление в составе locals: { ... } Hash, шаблон вызовет исключение ActionView::Template::Error:
<%# => raises ActionView::Template::Error %> <% alerts.each do |alert| %> <p><%= alert %></p> <% end %>
Поскольку local_assigns возвращает экземпляр Hash, можно условно прочитать переменную, а затем использовать значение по умолчанию, если ключ не входит в параметры locals: { ... }:
<% local_assigns.fetch(:alerts, []).each do |alert| %> <p><%= alert %></p> <% end %>
Сочетание сопоставления с образцом при присваивании из Ruby 3.1 и вызовов +Hash#with_defaults+ позволяет компактно присваивать локальные переменные партиала:
<% local_assigns.with_defaults(alerts: []) => { headline:, alerts: } %>
<h1><%= headline %></h1>
<% alerts.each do |alert| %>
<p><%= alert %></p>
<% end %> По умолчанию шаблоны принимают любые locals в качестве именованных аргументов и предоставляют их через local_assigns. Чтобы ограничить набор значений, которые local_assigns принимает шаблон, добавьте магический комментарий locals::
<%# locals: (headline:, alerts: []) %> <h1><%= headline %></h1> <% alerts.each do |alert| %> <p><%= alert %></p> <% end %>
Подробнее о строгих локальных переменных см. в руководстве Обзор Action View.
# File actionview/lib/action_view/template.rb, line 223
def locals
if strict_locals?
nil
else
@locals
end
end Локальные переменные, для которых этот шаблон был или будет скомпилирован, либо nil, если это шаблон со строгими локальными переменными.
# File actionview/lib/action_view/template.rb, line 271
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 Рендерит шаблон. Если шаблон ещё не скомпилирован, компиляция выполняется непосредственно перед рендерингом.
Для этого метода включена инструментация «!render_template.action_view». Обратите внимание: в названии инструментации используется восклицательный знак, потому что в рабочей среде её не следует использовать. Она замедляет работу только в том случае, если на неё подписан слушатель.
# File actionview/lib/action_view/template.rb, line 296
def short_identifier
@short_identifier ||= defined?(Rails.root) ? identifier.delete_prefix("#{Rails.root}/") : identifier
end # File actionview/lib/action_view/template.rb, line 304 def source @source.to_s end
# File actionview/lib/action_view/template.rb, line 366
def strict_locals!
if @strict_locals == NONE
self.source.sub!(STRICT_LOCALS_REGEX, "")
@strict_locals = $1&.rstrip
return if @strict_locals.nil? # Magic comment not found
@strict_locals = "**nil" if @strict_locals.blank?
end
@strict_locals
end Этот метод помечает шаблон как использующий строгие локальные переменные. Это означает, что шаблон может принимать только локальные переменные, определённые в магическом комментарии. Например, если шаблон принимает локальные переменные title и comment_count, добавьте в файл шаблона следующее:
<%# locals: (title: "Default title", comment_count: 0) %>
Строгие локальные переменные полезны для проверки аргументов шаблона и задания значений по умолчанию.
# File actionview/lib/action_view/template.rb, line 380 def strict_locals? strict_locals! end
Возвращает, использует ли шаблон строгие локальные переменные.
# File actionview/lib/action_view/template.rb, line 261 def supports_streaming? handler.respond_to?(:supports_streaming?) && handler.supports_streaming? end
Возвращает, поддерживает ли базовый обработчик потоковую передачу. Если да, при начале рендеринга может быть передан буфер потоковой передачи.
# File actionview/lib/action_view/template.rb, line 251
def translate_location(backtrace_location, spot)
if handler.respond_to?(:translate_location)
handler.translate_location(spot, backtrace_location, encode!) || spot
else
spot
end
end Преобразует местоположение ошибки, возвращённое ErrorHighlight, в соответствующее местоположение в исходном коде шаблона.
# File actionview/lib/action_view/template.rb, line 292 def type @type ||= Types[format] end
Приватные методы экземпляра
# File actionview/lib/action_view/template.rb, line 578
def instrument(action, &block) # :doc:
ActiveSupport::Notifications.instrument("#{action}.action_view", instrument_payload, &block)
end
© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.