Всем хорошо известно, что родным способом генерации всевозможных HTML страничек в рельсах является использование Ruby Templating, ERb. Честно признаюсь, до недавнего времени считал его единственным и вполне приемлемым. Но все изменилось, когда я познакомился с Haml. В данной статье я собираюсь рассказать об этом знакомстве.
Идея ERb достаточно проста – вы пишите HTML-код, попутно включая в него Ruby-вставки, которые в последствии будут заменены на результат вычисления выражения во вставке. Рассмотрим небольшой пример. Пусть у нас есть модель статей (Article). Код для вывода списка статей традиционно содержится в файле index.html.erb. Файл может выглядеть следующим образом:
Идея ERb достаточно проста – вы пишите HTML-код, попутно включая в него Ruby-вставки, которые в последствии будут заменены на результат вычисления выражения во вставке. Рассмотрим небольшой пример. Пусть у нас есть модель статей (Article). Код для вывода списка статей традиционно содержится в файле index.html.erb. Файл может выглядеть следующим образом:
Copy Source | Copy HTML
- <%- @articles.each do |article| -%>
- <div class="article">
- <div class="date"><%= l article.created_at.to_date -%></div>
- <h2><%= link_to h(article.title), article_path(article) -%></h2>
- <div class="summary"><%= h article.summary -%></div>
- </div>
- <%- end -%>
Если у вас какой-нибудь более-менее продвинутый дизайн, например, если вы задумали выводить красивую рамочку с закругленными краями при наведении на статью, то код может раздуться еще сильнее – могут появиться пустые DIV'ы для вывода каждой стороны этой самой рамочки (естественно, что к этому всему еще должен подключаться соответствующий CSS). В итоге код будет захламлен бесконечными открывающимися и закрывающимися HTML-тегами. Да и чем больше текста, тем сложнее его обрабатывать различным процессорам, вроде того же ERb.
Еще один момент, который мне не очень нравится, – это то, что без ужаса на код конечной HTML-страницы смотреть невозможно. Когда какой-нибудь шаблонн содержит другие, например, перебирает какую-нибудь коллекцию объектов и отображает соответствующий partial для каждого ее элемента (render :partial => 'article', :collection => @articles), а потом это все еще и в лэйаут заворачивается, то в итоге код странички превращается в полную кашу – пустые строки, разные уровни выравнивания, скачущие теги, лишние пробелы. Некоторых проблем можно избежать, но для этого разработчику нужно тщательно следить за расстановкой минусов в Ruby-вставках (<%- @articles.each do | article| -%>, <%= h article.summary -%>), что тоже не доставляет большого удовольствия.
Ладно, хватит о грустном, пора переходить в более лаконичному и красивому способу построения шаблонов – Haml. Постоянно натыкался на это поначалу непонятное слово в сети, много чего слышал о нем хорошего, но как-то все не доходило до дела. И вот совсем недавно в связи с наличием свободного времени все же решил с ним познакомиться поближе. Все, что необходимо сделать, чтобы втянуться в этот замечательный язык построения шаблонов, – это пройти пятиминутный обучающий курс на сайте.
Давайте попробуем перевести приведенный выше файл index.html.erb в Haml. Для этого переименуем его расширение в haml, получим index.html.haml.
Немножко отвлекусь и скажу для яблочных ребят и любителей TextMate, что для комфортной работой с Haml-файлами необходимо установить соответствующий пакет:
Copy Source | Copy HTML
- cd ~/"Library/Application Support/TextMate/Bundles/"
- svn co "http://macromates.com/svn/Bundles/trunk/Bundles/Ruby Haml.tmbundle"
В VIM'е у меня соответствующий синтаксический файл уже был, так что с ним проблем не было.
Идем дальше, теперь давайте установим gem:
Copy Source | Copy HTML
- $ sudo gem install --no-ri haml
Ну и наконец Haml-ализуем наше рельсовое приложение:
Copy Source | Copy HTML
- $ haml --rails /path/to/our/rails/application
Ничего страшного данная команда не делает, а просто устанавливает маленький плагин в папку vendor/plugins. Итак, дело сделано. Теперь все шаблоны с расширением haml будут обрабатываться процессором Haml. Стоп. Но ведь пока наш единственный Haml-шаблон содержит код для ERb, давайте это исправим:
Copy Source | Copy HTML
- - @articles.each do |article|
- %div{:class => "article"}
- %div{:class => "date"}= l article.created_at.to_date
- %h2= link_to h(article.title), article_path(article)
- %div{:class => "summary"}= h article.summary
Согласитесь, уже сейчас код выглядит намного симпатичнее. Это особо ощутимо на больших шаблонах вроде того же лэйаута. Чуть ниже мы перепишем его в еще более короткой форме, а пока расскажу о том, что же мы сделали (для полного овладения всеми фишками Haml настоятельно советую прочитать небольшую и такую же лаконичную, как и сам Haml, документацию на сайте проекта).
Первая строчка начинается со знака минус. Как вы наверное уже догадались, данная строчка аналогична <% %>, она не генерирует никакого HTML, а служит для выполнения различного рода вспомогательного Ruby-кода, в данном случае для организации цикла.
Хочу заметить, что для Haml очень важны уровни выравнивания кода, именно по ним Haml-процессор определяет, где заканчивается соответствующие выражение или HTML-тег. Благодаря этой замечательной особенности Haml в коде пропадают закрывающиеся конструкции вроде ключевого слова end.
Все последующие строки нашего шаблона начинаются со знака процента, который предназначен для генерации тегов. Имя тега может быть абсолютно любым. После имени в фигурных скобкам может идти определение атрибутов тега в нотации схожей с Ruby-хешами. Ну и завершает все это дело знак равенства, сигнализирующий о начале Ruby-кода. Есть еще множество других вариантов вместо знака равенства, например, если добавить еще один знак равенства, после этого весь оставшийся хвост будет восприниматься как Ruby-строка в двойных кавычках, которые теперь писать уже не надо.
Перейдем к обещанному сокращению кода. Поскольку такие атрибуты тега как class и id используются достаточно часто, Haml позволяет задавать их следующим образом (очень похоже на задание классов и идентификаторов CSS):
Copy Source | Copy HTML
- - @articles.each do |article|
- %div.article
- %div.date= l article.created_at.to_date
- %h2= link_to h(article.title), article_path(article)
- %div.summary= h article.summary
Аналогично будет с атрибутом id, только вместо точки будет решетка. Если необходимо указать несколько классов у одного тега, то их смело можно перечислять через точку, как это мы обычно делаем в CSS.
Но и это еще не все! Не побоюсь заявить, что тег DIV является самым распространенным средством верстки современных сайтов, поэтому он встречается довольно часто. В связи с этим Haml позволяет его опускать. Вот, что из этого может выйти:
Copy Source | Copy HTML
- - @articles.each do |article|
- .article
- .date= l article.created_at.to_date
- %h2= link_to h(article.title), article_path(article)
- .summary= h article.summary
Предлагаю прокрутить страничку выше и сравнить с тем, с чего мы начали. Не знаю как у вас, но у меня после такого знакомства сразу же появилось желание отучить один из небольших проектов нашей компании от ERb и подсадить его на Haml, что я успешно и сделал, при этом получил массу эстетического удовольствия от сокращения кода и приведения его к лаконичному и красивому виду. Планирую все последующие проекты разрабатывать с использованием этого замечательного языка.
Ну и напоследок хочется сказать, что и для построения CSS есть такая штука как Sass, причем она уже у вас установлена, так как идет в комплекте с Haml, синтаксис очень схож. Теперь можно поместить шаблоны с расширением sass в директорию public/stylesheets/sass, после чего соответствующие CSS-файлы будут созданы и положены в папку на уровень выше, где им и место. Честно говоря, с Sass я поиграться не пробовал, так что за примерами сразу отсылаю вас к соответствующей документации.
_________
Текст подготовлен в ХабраРедакторе