Подтвердить что ты не робот

Использование макетов в файлах HAML независимо от Rails

Моя конечная цель - создать несколько статических HTML файлов для передачи другим людям.

Но для моего рабочего процесса я хотел бы иметь HAML в качестве основных исходных файлов. При этом я надеюсь, что СУХОЙ процесс, по крайней мере, на моей стороне.

Теперь у меня много страниц, которые, в конечном счете, будут разделять общий макет, и мне интересно, как включить макеты.

Вот мой текущий код:

./compile.rb

#!/usr/bin/env ruby

require 'rubygems'
require 'rake'
require 'haml'

FileList.new('./src/*.html.haml').each do |filename|
  if filename =~ /([^\/]+)\.haml$/
    File.open($1, 'w') do |f|
      f.write Haml::Engine.new(File.read(filename)).render
    end
  end
end

./ЦСИ/layout.html.haml

!!!
%html
  %head
    %title Yay
  %body
    = yield

./ЦСИ/home.html.haml

= render :layout => 'header' do
  %p This is awesome

Теперь это явно не работает, потому что метод рендеринга undefined выходит из контекста Rails, но я надеюсь, что он найдет смысл в том, что я пытаюсь сделать.

Любые предложения?

4b9b3361

Ответ 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 для удовлетворения ваших потребностей.

Ответ 2

content = Haml::Engine.new(content_haml).render(
  Object.new, 
  :local_var_1 => ..., 
  :local_var_2 => ...
)


Haml::Engine.new(layout_haml).render(Object.new, :content => content)

layout.haml

!!!
%html
  %head
    %title
  %body
    = content

Вы также можете использовать переменные экземпляра Object.new (заменить значимым объектом) в haml, я полагаю.