класс ActionView::Base
Базовый класс Action View
Шаблоны Action View можно записывать несколькими способами. Если файл шаблона имеет расширение .erb, используется система шаблонов erubi, позволяющая встраивать Ruby в HTML-документ. Если файл шаблона имеет расширение .builder, используется библиотека Jim Weirich Builder::XmlMarkup.
Вы запускаете ERB, используя встраивания, например <% %>, <% -%> и <%= %>. Набор тегов <%= %> используется, когда нужно вывести содержимое. Рассмотрим следующий цикл для имен:
<b>Names of all the people</b> <% @people.each do |person| %> Name: <%= person.name %><br/> <% end %>
Цикл задается с помощью обычных тегов встраивания <% %>, а имя выводится с помощью тега встраивания для вывода <%= %>. Обратите внимание: это не просто рекомендация по использованию. Обычные функции вывода, такие как print или puts, не будут работать с шаблонами ERB. Поэтому следующий вариант будет неправильным:
<%# WRONG %> Hi, Mr. <% puts "Frodo" %>
Если вам непременно нужно выполнять запись из функции, используйте concat.
Если строка содержит только пробелы, кроме тега, <% %> удаляет начальные и конечные пробелы, включая символ новой строки в конце. <% %> и <%- -%> работают одинаково. Однако обратите внимание, что <%= %> и <%= -%> различаются: только последний вариант удаляет конечные пробелы.
Использование вложенных шаблонов
Использование вложенных шаблонов позволяет избежать утомительного копирования и вынести общие структуры отображения в общие шаблоны. Классический пример — использование заголовка и подвала (хотя в Action Pack для этого следует использовать Layouts):
<%= render "application/header" %> Something really specific and terrific <%= render "application/footer" %>
Как видите, для методов render используются встраивания с выводом. Сам вызов render просто возвращает строку с результатом рендеринга. Встраивание с выводом записывает ее в текущий шаблон.
Но вам не обязательно ограничиваться статическими включениями. Шаблоны могут совместно использовать переменные, определенные как переменные экземпляра с помощью обычных тегов встраивания. Например:
<% @page_title = "A Wonderful Hello" %> <%= render "application/header" %>
Теперь заголовок может получить переменную @page_title и использовать ее для вывода тега заголовка:
<title><%= @page_title %></title>
Передача локальных переменных во вложенные шаблоны
Вы можете передавать локальные переменные во вложенные шаблоны с помощью хеша, в котором имена переменных используются в качестве ключей, а объекты — в качестве значений:
<%= render "application/header", { headline: "Welcome", person: person } %> Теперь к ним можно обратиться в application/header следующим образом:
Headline: <%= headline %> First name: <%= person.first_name %>
К локальным переменным, переданным во вложенные шаблоны, можно обратиться как к хешу с помощью хеша local_assigns. Это позволяет обращаться к переменным следующим образом:
Headline: <%= local_assigns[:headline] %>
Это удобно, если вы не уверены, была ли локальная переменная присвоена. Также можно использовать defined? headline, чтобы сначала проверить, была ли переменная присвоена, и только после этого использовать ее.
По умолчанию шаблоны принимают любые locals в качестве именованных аргументов. Чтобы ограничить набор locals, принимаемых шаблоном, добавьте специальный комментарий locals::
<%# locals: (headline:) %> Headline: <%= headline %>
Если локальные переменные являются необязательными, объявите именованный аргумент со значением по умолчанию:
<%# locals: (headline: nil) %> <% unless headline.nil? %> Headline: <%= headline %> <% end %>
Подробнее о строгих локальных переменных читайте в руководстве Обзор Action View.
Кэширование Template
По умолчанию Rails компилирует каждый шаблон в метод для его рендеринга. При изменении шаблона Rails проверяет время изменения файла и перекомпилирует его в режиме разработки.
Builder
Шаблоны Builder — более программная альтернатива ERB. Они особенно полезны для создания содержимого XML. Объект XmlMarkup с именем xml автоматически становится доступен шаблонам с расширением .builder.
Вот несколько простых примеров:
xml.em("emphasized") # => <em>emphasized</em>
xml.em { xml.b("emph & bold") } # => <em><b>emph & bold</b></em>
xml.a("A Link", "href" => "http://onestepback.org") # => <a href="http://onestepback.org">A Link</a>
xml.target("name" => "compile", "option" => "fast") # => <target option="fast" name="compile"\>
# NOTE: order of attributes is not specified.
Любой метод с блоком будет обработан как тег разметки XML с вложенной разметкой в блоке. Например, следующий код:
xml.div do xml.h1(@person.name) xml.p(@person.bio) end
создаст примерно такой результат:
<div> <h1>David Heinemeier Hansson</h1> <p>A product of Danish Design during the Winter of '79...</p> </div>
Вот полноценный пример RSS, используемый на Basecamp:
xml.rss("version" => "2.0", "xmlns:dc" => "http://purl.org/dc/elements/1.1/") do
xml.channel do
xml.title(@feed_title)
xml.link(@url)
xml.description "Basecamp: Recent items"
xml.language "en-us"
xml.ttl "40"
@recent_items.each do |item|
xml.item do
xml.title(item_title(item))
xml.description(item_description(item)) if item_description(item)
xml.pubDate(item_pubDate(item))
xml.guid(@person.firm.account.url + @recent_items.url(item))
xml.link(@person.firm.account.url + @recent_items.url(item))
xml.tag!("dc:creator", item.author_name) if item_has_creator?(item)
end
end
end
end
Дополнительную информацию о Builder см. в исходном коде.
Атрибуты
Открытые методы класса
# File actionview/lib/action_view/base.rb, line 192 def cache_template_loading ActionView::Resolver.caching? end
# File actionview/lib/action_view/base.rb, line 196 def cache_template_loading=(value) ActionView::Resolver.caching = value end
# File actionview/lib/action_view/base.rb, line 212
def inspect
"#<ActionView::Base:#{'%#016x' % (object_id << 1)}>"
end Открытые методы экземпляра
# File actionview/lib/action_view/base.rb, line 264
def _run(method, template, locals, buffer, add_to_stack: true, has_strict_locals: false, &block)
_old_output_buffer, _old_virtual_path, _old_template = @output_buffer, @virtual_path, @current_template
@current_template = template if add_to_stack
@output_buffer = buffer
if has_strict_locals
begin
public_send(method, locals, buffer, **locals, &block)
rescue ArgumentError => argument_error
public_send_line = __LINE__ - 2
frame = argument_error.backtrace_locations[1]
if frame.path == __FILE__ && frame.lineno == public_send_line
raise StrictLocalsError.new(argument_error, @current_template)
end
raise
end
else
public_send(method, locals, buffer, &block)
end
ensure
@output_buffer, @virtual_path, @current_template = _old_output_buffer, _old_virtual_path, _old_template
end # File actionview/lib/action_view/base.rb, line 287
def compiled_method_container
raise NotImplementedError, <<~msg.squish
Subclasses of ActionView::Base must implement `compiled_method_container`
or use the class method `with_empty_template_cache` for constructing
an ActionView::Base subclass that has an empty cache.
msg
end # File actionview/lib/action_view/base.rb, line 295
def in_rendering_context(options)
old_view_renderer = @view_renderer
old_lookup_context = @lookup_context
if !lookup_context.html_fallback_for_js && options[:formats]
formats = Array(options[:formats])
if formats == [:js]
formats << :html
end
@lookup_context = lookup_context.with_prepended_formats(formats)
@view_renderer = ActionView::Renderer.new @lookup_context
end
yield @view_renderer
ensure
@view_renderer = old_view_renderer
@lookup_context = old_lookup_context
end
© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.