Использование Maruku (часть №1)
-
06 октября 2008 12:55
-
Комментарии (1)

В этом посте я собираюсь начать цикл статей, рассказывающих о Maruku.
Maruku это движок, который позволяет конвертировать текст в XHTML представление этого текста на основе специализированного “легковесного” языка разметки под названием Markdown.
Пару замечаний по абзацу выше:
-
Maruku использует в своей работе Markdown, но не просто использует, а ещё и расширяет его возможности. Как он это делает, я расскажу ниже.
-
Помимо преобразования в XHTML существует ещё возможность преобразования в LaTeX и PDF (предварительно преобразовав его в LaTeX). В планах у разработчиков добавление возможности конвертирования в сам Markdown (без специфических особенностей присутствующих в расширении этого языка от Maruku) и Textile2. Ценность последних конверторов, на мой взгляд, довольно сомнительная.
О самом Markdown я не вижу сейчас смысла рассказывать т.к. в интернете полно документации. Вот лишь несколько ссылок:
- Markdown в Wikipedia(ru) и Wikipedia(en)
- Описание синтаксиса Markdown от Daring Fireball
- Загляните в каталог <путь к каталогу с gem-ами>/gems/maruku-0.5.9/docs, а затем в файл markdown_syntax.html
Поэтому расскажу как Maruku расширяет Markdown. Начну я с того, что расскажу о двух основных категориях элементов разметки:
-
span-элемент - это такой элемент разметки, который состоит из одной строки текста (т.е. в нем нет переходов на новую строку). Как правило, эти элементы конвертируются в строковые (или как их ещё называют встроенные) элементы HTML. Например, _такой текст на Markdown_ будет преобразован в <em>такой текст на Markdown</em>
-
блочный элемент - такой элемент может состоять из нескольких строк. Примером такого элемента в Markdown может являться таблица или параграф
А теперь поговорим о расширениях. Их существует два вида:
Inline Attribute Lists (IAL)
В данном случае рядом с элементом разметки появляется конструкция вида:
{: <список атрибутов> }
Для span-элемента она должна идти сразу же за ним (без о всяких пробелов, за исключением заголовков где допускаются отступы), а для блочных элементов располагаться на новой строке под ним (без о всяких пустых строк между ними, но допускается отступ от начала строки до 3-х символов)
Это пример расширения _span-элемента_{: style="color:red" }
А это пример
расширения блочного
элемента
{: style="background-color:silver" }
А вот результат:
Это пример расширения span-элемента
А это пример расширения блочного элемента
Как вы заметили, в качестве списка атрибутов применяются атрибуты допустимые для HTML элементов. Но допустимы и следующие сокращения:
.<имя CSS класса> - будет преобразовано в class=”<имя CSS класса>”. Соответственно если такие конструкции встречаются несколько раз то все они будут помешены внутрь одного элемента class, как того требует спецификация CSS
#<id элемента> - будет преобразовано в id=”<id элемента>”.
key=value - будет преобразовано в атрибут key=value. Если value содержит пробелы, то его надо заключить в двойные кавычки.
ref_id - т.е. просто идентификатор без префиксов (# или .) говорит о том, что к элементу будет применяться стиль, описанный в ALD расширении. Без этой возможности Maruku не особо бы отличался от RedCloth. Но об этом ниже.
Attribute Lists Definitions (ALD)
А вот здесь начинаются чудеса :)
Вы можете объявить в любом месте вашей разметки конструкцию вида:
{:<ref_id>: <список атрибутов> }
а затем ссылаться на это объявление в любом IAL используя указанный вами ref_id
Пример:
Текст
{: red }
{:red: style="background-color: silver" }
Текст
{: red }
А вот результат:
Текст
Текст
На этом пока всё. В следующий раз я расскажу вам как подключить и использовать Maruku в своём приложении.
RedCloth в топку! Да здравствует Maruku!
-
05 октября 2008 19:56
-
Комментарии (2)

Сегодня утром RedCloth меня окончательно добил :( и я решил совершить подвиг и перевести блог на другой движок разметки. Причём поменял не просто сам движок, но ещё и язык разметки. Теперь всё топики у меня работают на Maruku (Респект Andrea Censi!), а языком разметки стал Markdown. Сейчас уже нет сил что либо делать, а вот завтра я постараюсь рассказать про Maruku более подробно.
Жонглируем файлами в Capistrano
-
05 октября 2008 01:47
-
Комментарии (0)

Жонглировать файлами в Capistrano просто :), потому как в одной из последних версии Capistrano появились два замечательных метода upload и download которые позволяют закачивать файлы на сервер и скачивать их с него соответственно.
download <путь к файлу на сервере>,
<путь на локальной машине куда будет скопирован файл>, <опции>
upload <путь на локальной машине откуда будет скопирован файл>,
<путь к файлу на сервере>, <опции>
С первыми двумя аргументами думаю всё понятно. Третий аргумент принимает хеш, одним из значений которого может быть ключ :via указывающий какой клиент будет использован для передачи файлов (SCP или SFTP который используется по умолчанию)
Метод upload в качестве опции так же принимает ключ :mode и в случае его наличия вызывает поле окончания процесса загрузки команду chmod передав её значение указанное в ключе (например :mode => 755)
Пример:
task :get_production_log, :role => [:app] do
download "#{current_path}/log/production.log", 'tmp/production.log', :via => :scp
end
Особенности работы с русскими строками в Ruby
-
04 октября 2008 20:55
-
Комментарии (2)

До этого как-то не приходилось с этим сталкиваться…
Оказывается чтобы операции со строками содержащими русские символы заработали так как нужно вам, сначала надо преобразовать строку в символы. Делается это с помощью метода chars который входит в состав Active Support (и который по умолчанию используется в Rails):
# Говорим Ruby что будем работать
# с UTF-8 (в Rails применяется по умолчанию)
$KCODE = "UTF8"
# Подгружаем Active Support (в Rails подключается по умолчанию)
require "rubygems"
require "active_support"
s = "привет"
puts s
puts s.upcase
puts s.chars.upcase
Результат:
привет
привет
ПРИВЕТ
Книги по Ruby и Rails на русском языке
-
04 октября 2008 16:56
-
Комментарии (0)

Тема с русскими книгами по Ruby и Rails довольно избитая и озвучена во многих блогах, но я не могу не добавить свои “пять копеек” :)
Особенность работы метода run в Capistrano
-
03 октября 2008 22:46
-
Комментарии (0)
Потратил сегодня полтора часа пытаясь заставить работать следующий код:
task :tmp_list, :roles => [:app] do
run <<-CMD
if [ -d /tmp/ ];
then
ls /tmp/
fi
CMD
end
и получал одну и ту же ошибку
* executing `tmp_list'
* executing "if [ -d /tmp/ ];\\\nthen\\\n ls /tmp/\\\nfi"
servers: ["111.111.111.111"]
[111.111.111.111] executing command
*** [err :: 111.111.111.111] Syntax error: end of file unexpected (expecting "fi")
command finished
failed: "sh -c \"if [ -d /tmp/ ];\\\\\nthen\\\\\n ls /tmp/\\\\\nfi\"" on 111.111.111.111
Проблема заключалась в том что sh передаётся команда содержащая символы переноса строки. В man-е освящене этого момента я не нашел.
Обойти эту проблему можно как минимум двумя способами:
1) Избавится от переносов строк. Тогда код будет выглядеть примерно так:
task :tmp_list, :roles => [:app] do
run "if [ -d /tmp/ ]; then ls /tmp/ ; fi"
end
2) Либо использовать условные операторы
task :tmp_list, :roles => [:app] do
run "([ -d /tmp/ ] && ls /tmp/) || true"
end
Трюк с true нужен для того чтобы в случае неудачи (если директория не будет найдена) выполнение набора комманд завершилось с кодом ошибки равным нулю (что означает что проблем при выполнении не возникло)
Таблицы цветов
-
02 октября 2008 17:51
-
Комментарии (1)
При разработке Web приложений мне часто требуется подобрать элементу тот или иной цвет, причём довольно часто непонятно даже что за цвет это должен быть :)
В таких случаях помогает взгляд на таблицу цветов в которой перечислены основные применяемые в Web разработке цвета. До недавнего времени я пользовался таблицей цветов из Wikipedia, но у неё был не большой недостаток существенный для меня. Заключался он в отсутствии оттенков серого цвета. Решил я эту проблему просто :) Я нашел другую таблицу на сайте www.cloford.com
Чуть не забыл :)
-
01 октября 2008 16:25
-
Комментарии (0)
С сегодняшнего дня я безработный!!!! Йес! :)
Отдохну недельку… подшлифую блог и займусь фрилансом :)
Создание Sitemap.xml в Rails
-
01 октября 2008 13:08
-
Комментарии (1)
Создание Sitemap в Rails довольно простая задача. Всё что вам нужно сделать это:
1) Создать контроллер или использовать уже готовый. Я пошел вторым путём. В этот контроллер нужно добавить действие которое будет отвечать за создание Sitemap.xml страницы.
def sitemap
headers['Content-Type'] = "application/xml"
@messages = Message.find :all, :limit => 50000, :order => "published_at DESC"
end
Первая строка устанавливает заголовок Content-Type в “application/xml” это означает для браузера (или поискового сервера) что контент файла находится в формате XML. Sitemap который мы создаём соответствует спецификации под номером 0.9 в которой сказано что контент должен быть именно в этом формате.
Вторая строка извлекает все сообщения в блоге и сортирует их в обратном порядке (чтобы более новые сообщения были вначале Sitemap файла). Ограничение в 50000 записей опять же установлено на основе спецификации (хотя есть ещё ограничение в 10Мб, но мы его не учитываем).
Ещё один немаловажный момент связанны с этим методом: нужно отключить текущий layout если он у вас установлен.
layout 'main', :except => [:sitemap]
Если этого не сделать, то весть XML код который мы сгенерируем на следующем шаге будет помешен в этот layout, а это в свою очередь будет означать что sitemap файл станет не корректным.
Кстати, как вариант, заместо этой строчки можно добавить в метод (в конец метода) следующую строчку такого вида:
render :layout => false
2) Следующим шагом будет создание представления которое называется так же как и наше действие и лежит в каталоге представления ассоциированном с контроллером. Называется он у меня так: sitemap.rxml. Обратите внимание на расширение rxml это означает что в этом файле мы собираемся работать с XML а вспомогательные методы Rails помогут нам в этом.
xml.instruct! :xml, :version=>"1.0"
xml.urlset(:xmlns => "http://www.sitemaps.org/schemas/sitemap/0.9") {
xml.url {
xml.loc(url_for :controller => 'blog', :only_path => false)
lastmod = @messages[0].published_at.strftime("%Y-%m-%d") if !@messages.nil?
lastmod = lastmod || Time.now.strftime("%Y-%m-%d")
xml.lastmod(lastmod)
xml.changefreq("daily")
xml.priority(1)
}
for message in @messages
xml.url {
xml.loc(url_for :controller => 'blog', :action => 'message', :id => message.id, :only_path => false)
xml.lastmod(message.published_at.strftime("%Y-%m-%d"))
xml.changefreq("weekly")
xml.priority(0.8)
}
end
}
В первой строке мы задаём сигнатуру XML файла. А затем, во второй строке, создаём корневой XML тэг под названием urlset с атрибутом xmlns который указывает на то какую версию Sitemap спецификации мы используем при генерации файла.
Затем обратите внимание на два места в коде где встречается строка xml.url в первом случае этот тег будет описывать главную страницу блога, а во втором каждое конкретное сообщение блога (т.к. этот тег находится внутри цикла который перебирает сообщения). Подобным же способом можно добавить ссылки на другие страницы вашего сайта (например на страницу с описанием сайта и т.п.)
Тэг xml.loc содержит полный URL путь в странице (чтобы получить полный путь, а не относительный, у метода urlfor_ устанавливаем опцию onlypath_ равной false)
Тэг xml.lastmod содержит дату (время указывать необязательно) последнего изменения страницы. Для главной страницы блога я вычисляю его на основании первой последней записи в созданной блоге.
Тэг xml.changefreq указывает с какой частотон надо проводить сканирование каждой конкретной страницы (учтите что вы всего лишь предлагаете поисковому боту сканировать с такой частотой, а он сам затем решает следовать вашим указаниям или нет). В данном случае я хочу чтобы главная страница сканировалась ежедневно (daily), а страницы с сообщениями раз в неделю (weekly)
Тэг xml.priority указывает в каком порядке бот должен сканировать страницы (допустимы знчения от 0.0 до 1.0) После этих 2-х шагов по адресу http://localhost:3000/<контроллер содержащий действие sitemap>/sitemap вы должны получить контент sitemap файла.
3) Последний завершающий штрих состоит в том что мы заставим Rails отдавать sitemap файл по более короткому URL. Для этого в файл config/routes.rb добавим следующую строку:
map.sitemap "/sitemap.xml", :controller => "<ваш контроллер>", :action => "sitemap"
Теперь обратившись по адресу http://localhost:3000/sitemap.xml вы получите sitemap.xml файл.
На этом создание sitemap.xml файла закончено.
P.S. Есть ещё более правильный способ создания sitemap файла, это использование специальных плагинов, но этот способ я постараюсь рассмотреть позже.
Особенности настройки кеширования на production сервере
-
30 сентября 2008 17:26
-
Комментарии (0)
Решил я на днях заняться кешированием блога и напоролся на небольшую проблему…
Требовалось обработать JavaScript и CSS файлы (которых меня много, да и весят они немало) и получить на выходе всего лишь два файла. Для этого я использовал способ предоставляемый хелперными методами javascript_include_tag и stylesheet_link_tag, а именно: собрал все .js и .css файлы в два хелперных метода и установил у них опции :cache. Получился примерно следующий код:
<%= javascript_include_tag 'shCore.js', 'shBrushCSharp.js', 'shBrushXml.js', 'shBrushRuby.js', 'shBrushBash.js', 'shBrushPlain.js', :cache => 'sh' %>
<%= stylesheet_link_tag 'application', 'pagination', 'textilize', 'awesomebox', 'SyntaxHighlighter.css', cache => 'general_all' %>
Для того чтобы кеширование заработало в конфиге для production сервера (_config/environments/production.rb_) поле config.action_controller.perform_caching должно быть выставлено в true (на самом деле это значение по умолчанию для этого конфига)
Грабли же заключаются в том, что в этом случае в каталогах public/javascripts и public/stylesheets при первом обращении к серверу создаются файлы объединяющие все указанные вами скрипты и CSS и если у mongrel нет прав на запись в эти каталоги, по возникает исключение:
ActionView::TemplateError (Permission denied - /u/apps/blog4m/releases/20080928165941/public/javascripts/sh.js) on line #10 of layouts/main.html.erb:
10: <%= javascript_include_tag 'shCore.js', 'shBrushCSharp.js', 'shBrushXml.js', 'shBrushRuby.js', 'shBrushBash.js', 'shBrushPlain.js', :cache => 'sh' %>
11: <%= stylesheet_link_tag 'application', 'pagination', 'textilize', 'SyntaxHighlighter.css', :cache => 'main_all' %>
А прав у mongrel-а небыло потому что он запускался под специально созданной учётной записью (не под той под которой деплоились на сервер файлы)
Покапавшись в интернете я нашел следующий workaround: надо в deploy.rb добавить следующие задачи которые будут выполняться после создания Сapistrano проекта на сервере и после заливки новой версии на сервер:
task :after_cold, :roles => [:app, :web, :db] do
sudo "chown -R mongrel:mongrel #{current_path}/"
end
task :after_update, :roles => [:app, :web, :db] do
sudo "chown -R mongrel:mongrel #{current_path}/"
end
Задачи просто меняют владельца у находящихся на сервере файлов после выполнения задачь deploy:cold и deploy:update

