Ruby on Rails
18 September 2011

Шаблонизатор Slim — альтернатива Haml'y

Давно хотел попробовать Haml, но всё не было времени. Но вот недавно обнаружил новый шаблонизатор, который мне сразу понравился. По словам создателей, он взял лучшее от Jade и Haml. Основная задача — сократить объем кода, при этом не делая его страшным и непонятным.

Вот так выглядит шаблон с использованием Slim:
doctype html
html
  head
    title Slim Examples
    meta name="keywords" content="template language"

  body
    h1 Markup examples
    #content.example1
      p Nest by indentation

    = yield

    - unless items.empty?
      table
        - for item in items do
          tr
            td = item.name
            td = item.price
    - else
      p No items found

    #footer
      | Copyright © 2010 Andrew Stone

    = render 'tracking_code'

    script
      | $(content).do_something();


Как и в Haml, форматирование вывода идёт по отступам. Вместо конструкции <%= %> используется знак =. Для вычислений без вывода в html (например, для if и for), ставится знак -.

В отличие от Haml'a, тут нет знака %, которым выделяются теги. Их можно сразу писать как есть. По сути, это просто HTML без <> скобок, в котором используются отступы для обозначения вложенных элементов. К слову, количество отступов — на ваш выбор, но не менее одного.

Список всех операторов:

| Вертикальная черта сообщает шаблонизатору, что нужно просто откопировать линию. При этом все "опасные" символы фильтруется.
' Одиночная скобка работает как и предыдущий оператор, но добавляет в конце пробел.
- Дефис работает как и в Haml, используется для циклов, условий и прочего, в чем вы раньше использовали <% ... %>
= Знак равенства работает как <%= ... %>, выводя содержимое в html
=' Работает как и предыдущий оператор, при этом добавляя в конец пробел.
== Работает как и знак равенства, но выводит текст "как есть", без обработки методом escape_html
==' Тоже самое, что и выше, но добавляет в конце пробел.
/ Знак комментария. Код не будет выполнен и не попадет в html вообще.
/! Знак для html комментариев (<!-- -->), которые попадут в вывод.


Атрибуты и комментарии

Обозначать id и class можно вот так:
blockquote id="quote-#{@quote.id}" class="quote"
  p class="title" = @quote.title
  p style="padding:1em;" = @quote.body


Для сравнения с Haml:
%blockquote{:id => "quote-#{@quote.id}", :class => "quote"}
  %p{:class="title"}= @quote.title
  %p{:style => "padding:1em;"}= @quote.body


Кроме того, Slim допускает несколько вариантов синтаксиса::
/ Эти две линии идентичны. Первый вариант синтаксиса, наверно, знаком вам по Haml'у 
#nav.top
div id="nav" class="top"

/ Допускается писать любой из этих вариантов
h1 class=page_header_class = page_header
h1{class=page_header_class} = page_header
h1[class=page_header_class] = page_header
h1(class=page_header_class) = page_header


Еще одна приятная штука — если в атрибуте не указаны кавычки, будет использована переменная. Из примера парой строчек выше можно увидеть, что используется переменная page_header_class.
# Можно писать и так, и так.
a href="#{url_for @user}" = @user.name
# Во втором случае не надо писать конструкцию "#{...}"
a href=url_for(@user) = @user.name


Если функция возвращает false, атрибут вообще не будет выведен в html (как и в Haml):
option value="Slim" selected=option_selected?("Slim") # -> <option value="Slim"></option>


Можно использовать интерполяцию как в строках Ruby:
body
  h1 Приветствуем, #{current_user.name}
  | С помощью двойных скобок #{{content}} выводится как есть, без фильтрации методом escape_html.



Мне очень нравится, как работают комментарии. Если у вас имеется блок кода, который надо закомментить, достаточно добавить всего одну строку, которая повлияет на весь блок.
# весь этот блок ниже закомментирован и не будет выведен
/.comments
  - @comments.each do |comment|
    == render comment


Стоит учесть, что метод render по-умолчанию фильтрует вывод, поэтому перед ним надо ставить двойной знак равенства, чтобы escape_html не сработал дважды.

Режим Logic-less

Slim::Engine.set_default_options :sections => true

И вот что можно с ним делать:
/ Автоматическая проверка переменной на false и empty?, если прошла то h1 будет выведен
- article
  h1 = title


/ Обратная проверка, если article удовлетворяет условиям false или empty? то блок будет выведен
-! article
  p Статья не найдена


Возможно, прочитав первый пример, у вас возник вопрос — откуда берется переменная 'title'? Slim сам пытается её найти несколькими способами.
/ If article.respond_to?(:title)
- article
  / Исполняется article.send(:title)
  h1 = title

/ If article.respond_to?(:has_key?) and article.has_key?(:title)
- article
  / Выводится переменная article[:title]
  h1 = title

/ If article.instance_variable_defined?(@title)
- article
  / Будет выведена классовая переменная с помощью article.instance_variable_get @title
  h1 = title

Лично мне такой режим не понравился, но может именно вам он придется по вкусу.

Что насчет производительности

Шаблоны в рельсах кешируются, поэтому по скорости они будут отставать от стандартного Erb лишь при первом обращении к ним. Вот сравнительная таблица, которая показывает, что Slim уж точно не будет узким местом в вашем приложении:
# Linux + Ruby 1.9.2, 1000 iterations
                      user     system      total        real
(1) erb           0.680000   0.000000   0.680000 (  0.810375)
(1) erubis        0.510000   0.000000   0.510000 (  0.547548)
(1) fast erubis   0.530000   0.000000   0.530000 (  0.583134)
(1) slim          4.330000   0.020000   4.350000 (  4.495633)
(1) haml          4.680000   0.020000   4.700000 (  4.747019)
(1) haml ugly     4.530000   0.020000   4.550000 (  4.592425)

(2) erb           0.240000   0.000000   0.240000 (  0.235896)
(2) erubis        0.180000   0.000000   0.180000 (  0.185349)
(2) fast erubis   0.150000   0.000000   0.150000 (  0.154970)
(2) slim          0.050000   0.000000   0.050000 (  0.046685)
(2) haml          0.490000   0.000000   0.490000 (  0.497864)
(2) haml ugly     0.420000   0.000000   0.420000 (  0.428596)

(3) erb           0.030000   0.000000   0.030000 (  0.033979)
(3) erubis        0.030000   0.000000   0.030000 (  0.030705)
(3) fast erubis   0.040000   0.000000   0.040000 (  0.035229)
(3) slim          0.040000   0.000000   0.040000 (  0.036249)
(3) haml          0.160000   0.000000   0.160000 (  0.165024)
(3) haml ugly     0.150000   0.000000   0.150000 (  0.146130)

(4) erb           0.060000   0.000000   0.060000 (  0.059847)
(4) erubis        0.040000   0.000000   0.040000 (  0.040770)
(4) slim          0.040000   0.000000   0.040000 (  0.047389)
(4) haml          0.190000   0.000000   0.190000 (  0.188837)
(4) haml ugly     0.170000   0.000000   0.170000 (  0.175378)

1. Рендер некешированной страницы при первом обращении.
   Его можно активировать, используя параметр slow=1.

2. Кешированный тест. Шаблон предварительно парсится.
   Код Ruby не компилируется и может быть выполнен в любое время.
   Этот бенчмарк испольует стандартное API шаблонов.

3. Компилированный тест. Шаблон также предварительно парсится,
   но кроме того, код Ruby компилируется в отдельный метод.
   Это самый быстрый тест, потому что в нем тестируется лишь
   скорость выполнения самого кода.

4. Компилированный Tilt-бенчмарк. Шаблон компилируется с помощью Tilt,
   что даёт более точные результаты производительности в режиме Продакшена
   в таких фреймворках как Sinatra, Ramaze and Camping.

Как установить

Есть 2 варианта. Первый — без добавления генераторов шаблонов (для создания, например, Scaffold’ов). Второй — с генераторами.
# Если вам просто нужен Slim
gem 'slim'

# Если вам нужен Slim и генераторы Scaffold'ов
gem 'slim-rails'
Затем нужно прописать в консоли bundle install для установки выбранных гемов.

Не стоит забывать, что для использования Slim ваши файлы должны иметь расширение .slim. То есть, файл index.html.erb будет выполнен шаблонизатором Erb, а index.html.slim — соответственно, Slim.

Полезные ссылки

slim-lang.com— официальная страница
github.com/stonean/slim — страница на Github
github.com/fredwu/haml2slim — конвертатор Haml в Slim
github.com/fredwu/ruby-slim-tmbundle — бандл для TextMate
github.com/bbommarito/vim-slim — файлы для Vim

+55
64.1k 164
Comments 68
Top of the day