System of a Down
-
09 октября 2008 11:30
-
Комментарии (0)

Сегодня ночью, пока я спокойно спал, mongrel ушел в даун :( Похоже причиной тому стала работа с RMagic в капче. Если такое ещё раз повториться, то похоже придётся поменять её на что-то более надёжное.
На примете уже есть плагин для работы с reCAPTCHA, но как-то боязно его применять т.к. он взаимодействует с удалённым сервисом и если что случиться с ним, то, насколько я понимаю, сделать с этим ничего будет нельзя. Хотя с другой стороны я уже видел много сайтов которые его используют. В общем буду смотреть по обстоятельствам :)
Использование Maruku (часть №4)
-
09 октября 2008 00:10
-
Комментарии (0)

Приближается к концу мой “эпос” посвящённый Maruku :)
В этой части, как и обещал, я расскажу о том как добавить свои собственные блочные элементы. Напомню, что про добавление span-элементов я рассказал в прошлом посте.
Начну я как и прежде с шаблона, который вы можете использовать при разработке своих блочных элементов:
StartTag = /^<регулярное выражение для начального тега>/
EndTag = /^<регулярное выражение для конечного тега>/
MaRuKu::In::Markdown::register_block_extension(
:regexp => StartTag,
:handler => lambda { |doc, src, context|
# Пропускаем первую строку с начальным тегом
src.shift_line
# Считываем строки которые находятся внутри блока
lines = []
while src.cur_line && !(src.cur_line =~ EndTag)
lines.push src.shift_line
end
# Пропускаем строку с конечным тегом
src.shift_line
# Здесь находиться ваш код который обрабатывает строки внутри блока
# и возвращает результат в переменной result
context.push result
true
}
)
Если вы читали мою предыдущую статью, то заметили что этот шаблон сильно похож на шаблон для span-элементов. Поэтому я не буду заново рассказывать обо всех аргументах, а лишь упомяну об отличиях.
Мы завели две переменные в которых хранятся регулярные выражения для начального и конечного тега. Как вы понимаете это связано с тем что блок имеет следующий формат:
<начальный тег>
...
<содержимое блока>
...
<конечный тег>
И с помощью этих регулярных выражений мы находим эти теги, а затем “выкусываем” содержимое которое находится между ними и обрабатываем его.
Хорошим тоном думаю будет строить такие регулярные выражения которые будут искать теги начиная с начала строки (я специально указал в шаблоне символ чайки ^) связано это с тем что обработчик не принимает аргумент :chars как было в обработчике для span-тегов, а вместо этого применяет ко всем строкам вашего документа регулярное выражение StartTag чтобы понять содержит ли строка открывающий тег. Думаю понятно что из-за этого могут возникнуть проблемы с производительностью, а символ ^ всего лишь небольшая страховка от этих проблем.
Следующий момент на который надо обратить внимание состоит в том что мы используем метод register_block_extension для регистрации обработчика. Плюс, как я упомянул выше, этот метод содержит на один аргумент меньше. В теле обработчика я привел небольшой фрагмент кода который собирает находящиеся внутри блока строки.
Теоретическая часть закончена, переходим к практике :) Создадим блочный элемент в который можно помещать код на Ruby, а на выходе получать результат выполнения этого кода :)
Вот что у меня получилось:
StartTag = /^!ruby/
EndTag = /^!/
MaRuKu::In::Markdown::register_block_extension(
:regexp => StartTag,
:handler => lambda { |doc, src, context|
# Пропускаем первую строку с начальным тегом
src.shift_line
# Считываем строки которые находятся внутри блока
lines = []
while src.cur_line && !(src.cur_line =~ EndTag)
lines.push src.shift_line
end
# Пропускаем строку с конечным тегом
src.shift_line
code = lines.join("\n")
result = get_result(code)
context.push doc.md_html("<pre><code>#{result}</code></pre>")
true
})
class StdOutCapturer
attr_reader :output
def initialize
@output = ""
end
def write(s)
@output += s
end
end
def get_result(code)
origin_stdout = $stdout
$stdout = StdOutCapturer.new
eval(code)
result = $stdout.output
$stdout = origin_stdout
result
end
И такой вот блок
!ruby
5.times { |i| puts "Hello World #{i}!!!" }
!
конвертируется в следующую разметку
<pre><code>Hello World 0!!!
Hello World 1!!!
Hello World 2!!!
Hello World 3!!!
Hello World 4!!!
</code></pre>
Что ж, я рассказал про все доступные способы расширения Markdown в Maruku. Код правда получился несколько громоздким, если видите способы исправить это - оставляйте комментарии :)
Следующий пост завершит цикл статей о Maruku, в нём я попробую выяснить насколько быстро работает Maruku.
Использование Maruku (часть №3)
-
08 октября 2008 11:29
-
Комментарии (0)

Как я и обещал, сейчас я расскажу вам о возможностях расширения Markdown. Так как есть два способа расширить функциональность, то в этом посте я расскажу про первый, а в следующем про второй.
Первый способ позволяет создавать свои span-подобные теги т.е. теги состоящие из одной строки. Например можно преобразовывать конструкцию вида
( ximg: ruby.jpg : Логотип Ruby : center )
в изображение с подписью. Или например вставлять на место смайликов их изображения, чем мы сейчас и займёмся.
В качестве заготовки для span-расширений можно использовать код приведённый ниже:
RegExp = /<регулярное выражение>/
MaRuKu::In::Markdown::register_span_extension(
:chars => [<символы с которых могут начинаться ваши span-теги>],
:regexp => RegExp,
:handler => lambda { |doc, src, context|
# Здесь находиться ваш код который преобразует span-тег в HTML разметку
# Код возвращает true если тег успешно обработан, иначе возвращает false
}
)
Этот код используя метод register_span_extension регистрирует обработчик span-тегов.
В аргументе :chars указывается символ или массив символов при встрече которых срабатывает обработчик. Причём символы не должны попадать в диапазон [a-zA-Z].
В аргументе :regexp указывается регулярное выражение которое будет выполнятся при встрече символа указанного в :chars и проверять является ли последовательность символов (начиная с текущего) вашим span-тегом. Не забудьте добавить символы из :chars в начало своего регулярного выражения, я потратил довольно много времени пытаясь понять почему обработчик не срабатывает.
В аргументе :handler в виде лямбда выражения находиться ваш обработчик. Который собственно говоря и занимается преобразованием вашего span-тега в нужную вам разметку. У этого обработчика тоже есть аргументы:
Аргумент doc это экземпляр класса Maruku который вы создали. В него подмешены методы из модуля MaRuKu::Helpers которые позволяют конструировать элементы на основе которых генерируется конечная разметка (понятно что формат мета-информации о том является ли текст курсивом в XHTML, PDF и LaTeX различаются, поэтому эти методы создают промежуточные объекты в которых храниться эта мета-информация, а уже из этих объектов по вашему требованию строится или XHTML или PDF или LaTeX)
Аргумент src предоставляет объект который содержит обрабатываемый текст и методы для его обработки.
Аргумент context предоставляет объект в который ваше расширение складывает результат своей работы (т.е. элемент или элементы полученные с помощью вспомогательных методов аргумента doc и заполненные мета-информацией необходимой для генерации разметки)
Остаётся добавить что если вы успешно обработали свой span-тег, то лямбда выражение должно вернуть true, тогда обработчики идущие за ним не будут вызваны и по окончанию преобразований ваш span-тег будет замещён генерированной в обработчике разметкой. А если вернуть false, то представление вашего span-тега без изменений будет помещено в выходную разметку.
Теперь мы готовы к написанию обработчика span-тегов. Как я уже сказал выше мы будем преобразовывать текстовые смайлики в HTML разметку содержащую изображение смайлика. Так как я суровый программист, то смайликов у меня будет всего лишь два (улыбающийся смайлик - :) или :-) и расстроенный смайлик - :( или :-( )
RegSmiles = /:-?(\(|\))/
MaRuKu::In::Markdown::register_span_extension(
:chars => [?:],
:regexp => RegSmiles,
:handler => lambda { |doc, src, context|
attrs = src.read_regexp(RegSmiles).captures
bracket = attrs[0]
case bracket
when ")"
image = doc.md_im_image([], "/images/smile1.gif", ":-)", {:style => "padding:0;margin:0", :alt => ":-)"})
when "("
image = doc.md_im_image([], "/images/smile0.gif", ":-(", {:style => "padding:0;margin:0", :alt => ":-("})
end
context.push_element image
true
}
)
Вот такой вот код у меня получился. Так как мои смайлики начинаются с :, то аргумент :chars содержит этот символ. Регулярное выражение RegSmiles проверяет наличие смайлика при встречи символа двоеточия, а так же захватывает один символ (символ скобки) который после проверяется в case-е и на его основе формируется элемент на основе которого будет сформировано изображение. Затем этот элемент с помощью метода push_element помещается в контейнер context и лямбда выражение сигнализирует об успешной обработке возвращая true.
Это вот пример строк которые я использовал для тестирования:
Test :)
Тест :(
К сожалению этот код не заработал… не заработал с первого раза. Только для первой строки где содержались латинские символы появился смайлик, в строке же с русскими символами текст остался без изменений. Потратив больше часа на поиски проблемы я нашел решение и даже готовый патч (но ещё не включенный в основную версию). Порадовал меня и тот факт что я нашел то же место, но не стал писать заплатку, а решил отправить баг автору :)
А вот получившаяся разметка:
<p>Test <img src='/images/smile1.gif' alt='' style='padding:0;margin:0' /></p>
<p>Тест <img src='/images/smile0.gif' alt='' style='padding:0;margin:0' /></p>
На всякий случай приведу патч:
*** lib/maruku/input/charsource.rb.bak 2008-03-20 20:06:04.000000000 +0200
--- lib/maruku/input/charsource.rb 2008-03-20 20:28:34.000000000 +0200
***************
*** 88,95 ****
end
def next_matches(r)
! r2 = /^.{#{@buffer_index}}#{r}/m
! md = r2.match @buffer
return !!md
end
--- 88,94 ----
end
def next_matches(r)
! md = /#{r}/um.match @buffer[@buffer_index, @buffer.size-@buffer_index]
return !!md
end
Думаю он потребуется нам и в следующей части. А пока всё.
Скорая помощь
-
08 октября 2008 03:40
-
Комментарии (1)
В этом посте я расскажу какие справочные системы по Ruby и Rails (и не только) доступны разработчикам в Интернете.
Использование Maruku (часть №2)
-
07 октября 2008 14:23
-
Комментарии (0)

В прошлой части я рассказал про то, что же из-себя представляет Maruku и что интересного в нём есть. Поэтому сейчас я расскажу как его устанавливать (думаю кто-то уже справился без меня т.к. процесс довольно стандартный)
Всё самое вкусное Rails разработчики обычно получают устанавливая gem-ы, не является исключением и Maruku. На сегодняшний день доступна версия 0.5.9, которую я и поставлю:
sudo gem install maruku
Собственно на этом установка Maruku закончена.
Пример использования:
require 'rubygems'
require 'maruku'
m = Maruku.new("**Привет**")
puts m.to_html
После выполнения этот код вернёт вам строку:
<p><strong>Привет</strong></p>
Помимо метода to_html можно ещё вызывать to_html_document, который выдаёт готовый XHTML документ, а не его часть. Но сейчас этот документ создаётся с довольно специфическим DOCTYPE-ом (хотя судя по коду в следующих версиях возможно это будет как-то настраиваться)
Из интересных вещей ещё осталось отметить то что, Maruku имеет список глобальных настроек доступных в хеше MaRuKu::Globals, например с его помощью можно немного облегчить создание разметки. Например, установив:
MaRuKu::Globals[:html_use_syntax] = true
вы можете использовать более короткую версию IAL для описания языка используемого в блоке кода:
require 'maruku'
{:lang=ruby}
заместо
require 'maruku'
{:lang=ruby html_use_syntax=true}
Кстати возможность подсветки блоков кода Maruku реализует за счёт того что задействует gem под названием Syntax, правда количество поддерживаемых языков в нём пока маловато (есть ruby, xml и yaml)
На этом пока всё, в следующей части я расскажу о том как можно расширить язык разметки Markdown вашими собственными тегами(коммандами)
Горестные раздумья блоговода
-
07 октября 2008 03:56
-
Комментарии (0)

Подумывал тут о том чтобы залочить блог для ословодов т.к. этот “браузер” уже давно отравляет мне жизнь своим странным поведением. Седьмой осёл например давит скролбарами блоки с кодом, что с этим делать я пока не придумал. А про шестой вообще вспоминать даже не хочется.
Использование 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
Результат:
привет
привет
ПРИВЕТ

