Использование макетов в файлах HAML независимо от Rails - PullRequest
36 голосов
/ 25 мая 2011

Моя конечная цель - создать несколько статических файлов 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

. / src / layout.html.haml

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

. / src / home.html.haml

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

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

Есть предложения?

Ответы [ 2 ]

75 голосов
/ 26 мая 2011

Вы смешиваете две разные функции Rails: частичные (используя render) и макеты (используя yield) .

Вы можете добавитьпохожая на рельсы версия любой из них (или обеих) для программы только на Haml.

Partials

В представлении rails вы можете использовать render :partial_name, чтобы вызвать файл _partial_name.html.hamlвизуализироваться в этой точке в содержащем представлении (фактически Rails позволяет вам использовать любой поддерживаемый язык шаблонов, и он найдет правильное расширение имени файла, но я остановлюсь только на Haml).Вне Rails render недоступен, но его можно добавить довольно легко.

Простой метод render просто найдет соответствующий файл haml, отобразит его и вернет html-строку для включения вparent:

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 в сценарий перед вызовом 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's 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 метод , чтобы получить обработанный хамл, не отправляя его прямо на выход.Обратите внимание, что это не захватывает безымянную часть представления.

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

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 содержитокончательный результат рендеринга.

Обратите внимание, что код здесь не обеспечивает всю гибкость, которая включена в rails, но, надеюсь, этого достаточно, чтобы показать вам, с чего начать настройку Haml в соответствии с вашими потребностями.

5 голосов
/ 25 мая 2011
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, я считаю.

...