Ответ 1
Вы смешиваете две различные функции Rails: частичные (используя render
) и макеты (используя yield
).
Вы можете добавить рельсоподобную версию (или обоих) из них только в программу Haml.
Partials
В представлении рельсов вы можете использовать render :partial_name
, чтобы заставить файл _partial_name.html.haml
отображаться в этой точке содержащего представления (на самом деле Rails позволяет использовать любой поддерживающий язык шаблонов, и он найдет исправление расширения имени файла использовать, но я буду придерживаться только Хамла здесь). Вне Rails render
недоступен, но его можно добавить довольно легко.
Простой метод render
будет просто найти соответствующий файл haml, отобразить его и вернуть строку html для включения в родительский объект:
def render(partial)
# assuming we want to keep the rails practice of prefixing file names
# of partials with "_"
Haml::Engine.new(File.read("_#{partial}.html.haml")).render
end
Первый аргумент Haml::Engine.render
- это объект области видимости, который мы можем использовать для добавления методов, доступных внутри шаблона haml. По умолчанию используется значение Object.new
. Однако в простом случае, как это, мы можем определить метод render
на верхнем уровне, и он будет доступен в рамках шаблона Haml. Мы просто помещаем наш метод render
в script перед вызовом Haml::Engine.new(...).render
и вызываем его вот так в нашем шаблоне:
!!!
%html
%head
%title Hello
%body
=render :the_partial
Теперь файл _the_partial.html.haml
будет отображаться в соответствующей точке вывода.
Локальные переменные
Мы можем сделать это еще дальше. Rails позволяет передавать в хэш локальные переменные в частичное. Haml также примет хэш переменных, которые будут переданы как локальные переменные, как второй аргумент метода Haml render
. Поэтому, если мы расширим наш метод визуализации, чтобы выглядеть так:
def render(partial, locals = {})
Haml::Engine.new(File.read("_#{partial}.html.haml")).render(Object.new, locals)
end
мы можем использовать частичное, что выглядит примерно так:
%p You passed in #{foo}
и назовите его из нашего шаблона с помощью:
%body
=render :partial, :foo => "bar"
который отобразит
<body>
<p>You passed in bar</p>
</body>
Макеты
В Rails вы можете указать макет для своих просмотров, чтобы все ваши страницы могли совместно использовать один и тот же
заголовок, область меню и т.д. Это делается путем указания файла макета, в котором вы вызываете yield
для отображения фактического представления. Макеты немного сложнее добавить к haml, но все равно можно сделать.
Метод Hamls render
также принимает блок, поэтому простым решением было бы сделать файл макета и передать блок, который отображает файл вида:
Haml::Engine.new(File.read("layout.html.haml")).render do
Haml::Engine.new(File.read("view.html.haml")).render
end
Это предоставит содержимое layout.html.haml
, отображаемое с содержимым view.html.haml
, которое будет отображаться в файле макета, содержащем =yield
.
content_for
Rails немного более гибкая, чем это. Он позволяет вам называть yield
несколько раз в вашем файле макета, называя конкретный регион в каждом случае и указывая содержимое, которое нужно добавить в каждом регионе, используя метод content_for
в ваших представлениях. Итак, в вашем файле макета:
!!!
%html
%head
= yield :title
%body
=yield
и на ваш взгляд:
-content_for :title do
%title Hello
%p
Here a paragraph.
На самом деле Rails работает, прежде всего, для рендеринга части представления, сохранения всех разных разделов, а затем визуализации макета, передачи блока, который предоставляет соответствующий фрагмент, когда yield
вызывается в макете. Мы можем реплицировать это с помощью небольшого вспомогательного класса, чтобы предоставить метод content_for
и отслеживать отображаемые фрагменты для каждого региона:
class Regions
def initialize
@regions_hash={}
end
def content_for(region, &blk)
@regions_hash[region] = capture_haml(&blk)
end
def [](region)
@regions_hash[region]
end
end
Здесь мы используем метод capture_haml
, чтобы получить обработанный haml без его прямого выхода на выход. Обратите внимание, что это не отражает безымянную часть представления.
Теперь мы можем использовать наш вспомогательный класс для вывода окончательного вывода.
regions = Regions.new
unnamed = Haml::Engine.new(File.read("view_named.html.haml")).render(regions)
output = Haml::Engine.new(File.read("layout_named.html.haml")).render do |region|
region ? regions[region] : unnamed
end
Теперь переменная output
содержит окончательный вывод рендеринга.
Обратите внимание, что код здесь не обеспечивает всю гибкость, которая включена в рельсы, но, надеюсь, достаточно, чтобы показать вам, с чего начать настройку Haml для удовлетворения ваших потребностей.