Monday, October 4, 2010

Rails pg gem

Ошибка вида:
/usr/bin/ruby1.8 extconf.rb
checking for pg_config... no
checking for libpq-fe.h... no
Can't find the 'libpq-fe.h header
Решается с помощью установки следующих пакетов.

В ubuntu:
apt-get install postgresql-server-dev-8.4

В Gentoo:
emerge postgresql-server

Sunday, November 29, 2009

Catalyst mod_perl Deployment

Недавно пришлось мне разворачивать catalyst-овское приложение под Apache. Посмотрел я документацию Catalyst::Manual::Cookbook В частности есть там пример конфигурации апача, а именно:

PerlSwitches -I/var/www/MyApp/lib
PerlModule MyApp

<Location />
  SetHandler modperl
  PerlResponseHandler MyApp
</Location>

Сей конфиг работать у меня отказался. Пошел читать про modperl, в результате нашел слудующий пример тут:
<VirtualHost ...>
  ServerName dev1
  PerlOptions +Parent
  PerlSwitches -I/home/dev1/lib/perl
</VirtualHost>
В конечном счете добавление опции

PerlOptions +Parent

решает проблему

Странно как-то... в мануалах писать нерабочие конфиги, посмотрел баг репорт по этому мануалу. Оказывает что есть #31164: Catalyst::Manual::Cookbook mod_perl configuration incorrect? (обратите внимание что баг за Mon Dec 03 07:20:12 2007) Тут человек пишет о такой же проблеме, но предлагает другое решение. Но мануал по сей день не исправлен.

Monday, November 16, 2009

Закругление углов с помощью таблицы (проверено в IE7 и Firefox 3.0.15)

По моему мнение самый универсальный способ закругления углов в IE это через таблицу. Сразу покажу что мы получим в результате:


Для этого нам понадобятся четыре угла, которые нужно нарисовать, я использовал GIMP:






уголки маленкие, 6х6 пикселей, в моем случае нужны были именно такие. И четыре картинки для бордеров (картинки есть, они просто очень мелкие, бордер всего 1px):







Вот по поводу использования бордеров в этом случае терзают сомнения, я думаю должен быть какой-нибудь способ более простой, если кто-то знает и поделится - буду очень благодарен.

Сам HTML код:

<table style="background-color: white;" width="15%" cellpadding="0" cellspacing="0" border="0">
 <tr>
  <td><img src="corner_top_left.gif" width="6" height="6"/></td>
  <td height="6px" style="background-image: url('border_top.gif'); background-repeat: repeat-x; height: 6px;"></td>
  <td><img src="corner_top_right.gif" width="6" height="6"/></td>
 </tr>
 <tr>
  <td height="6px" style="background-image: url('border_left.gif'); height: 6px;"></td>
  <td width="100%">
   Содержимое округлого блока тут
  </td>
  <td height="6px" style="background-image: url('border_right.gif'); height: 6px;"></td>
 </tr>
 <tr>
  <td><img src="corner_bottom_left.gif" width="6" height="6"/></td>
  <td height="6px" style="background-image: url('border_bottom.gif'); background-repeat: repeat-x; height: 6px;"></td>
  <td><img src="corner_bottom_right.gif" width="6" height="6"/></td>
 </tr>
</table>


Внимание! Для IE7 имеет разница форматирование HTML. Что это означает? Означает следующее, что записи:

<tr>
<td>Bla bla bla bla</td>
</tr>

и

<tr><td>Bla bla bla bla</td></tr>

IE трактует по разному, и соответственно результат который вы будете видеть в браузере тоже будет разным. В первом случае как я понял он пытается вставить пустую линию и получается что попало, так что обратите на это внимание.

PS: Ненавижу IE !

Saturday, November 14, 2009

Изменение cpan-овских зеркал

Ставлю модуль с cpan и судя по всему сейчас с http на perl.org какие-то проблемы, по ftp все скачивается нормально. Не очень хочется сидеть и ждать пока пройдет тайм аут и модуль таки скачается, особенно если надо много чего поставить. Наблюдается вот такая вот картина:

Fetching with LWP:
http://www.perl.org/CPAN/authors/id/F/FL/FLORA/namespace-clean-0.11.tar.gz

<дилетельное ожидание>

LWP failed with code[500] message[read timeout]
Fetching with LWP:
ftp://ftp.perl.org/pub/CPAN/authors/id/F/FL/FLORA/namespace-clean-0.11.tar.gz
Checksum for /root/.cpan/sources/authors/id/F/FL/FLORA/namespace-clean-0.11.tar.gz ok


Для решения проблемы идем на http://www.cpan.org/SITES.html и выбираем там себе подходящий сайт, мой выбор пал на http://cpan.makeperl.org/. Далее запускаем cpan-овскую консоль (не забываем про sudo кому надо):

perl -MCPAN -e shell


и пишем там

cpan[37]> o conf urllist http://cpan.makeperl.org/
Please use 'o conf commit' to make the config permanent!


Как и указано если хотите чтобы изменения остались на постоянной основе нужно выполнить

o conf commit

Для добавление урлов в список:

o conf urllist push http://cpan.makeperl.org/
o conf urllist unshift http://cpan.makeperl.org/


для удаления:

o conf urllist shift
o conf urllist pop


Список зеркал можно посмотреть следующим образом:

o conf urllist

Friday, November 7, 2008

Переименовать большое количество файлов сразу

Появилась у меня потребность переименовать кучу файлов, после непродолжительного ресерча наткнулся на на замечательную консольную утилиту Лари Уолла под названием rename с поддержкой, как не трудно догадаться, perlexpr. Несколько примеров использования.

Удалить расширение у файла:
rename 's/\.bak$//' *.bak

Перевести символы в малый регистр:
rename 'y/A-Z/a-z/' *

и т д

Более подробную информацию можно найти в man rename

Monday, June 30, 2008

XML::Twig

Приветствую.

Решил заделиться имеющимися знаниями и навыками работы с перловым модулем для работы с XML документами под названием XML::Twig. В этом документе я постараюсь осветить самые основные моменты использования данного модуля. Заранее хочу сказать что я не претендую на "последнюю инстанцию" и для полной точности нужно обращаться к официальной документации

Начнемс. Для примера возьмем xml файл следующего содержания:


<document pubdate="2008-06-06">
<chapter>
<section userlevel="1"><title>Атрибуты подпрограммы:</title>
<list>
<item>locked</item>
<item>method</item>
<item>lvalue</item>
</list>
</section>
<section userlevel="2">
<para>Разыменовывающие префиксы:</para>
<list type="bullet">
<item><bold>Скаляр</bold> $ </item>
<item><bold>Массив</bold> @ </item>
<item><bold>Хеш</bold> % </item>
</list>
</section>
<para>"Выполнять линейный просмотр в ассоциативном массиве —
все равно что пытаться забить кого-нибудь до смерти заряженным Узи" Ларри Уолл</para>
</chapter>
</document>

назовем его example.xml.

Хочу сразу напомнить что в начало скрипта нужно поместить директиву: use XML::Twig, дабы подключить сам модуль. Создадим обьект XML::Twig и откроем вышеуказаный файл:

my $twig = XML::Twig->new();

$twig->parsefile("example.xml");

возьмем корневой элемент:

my $root = $twig->root;

для радующего глаз вывода воспользуемся методом set_pretty_print со стилем indented:

$root->set_pretty_print('indented');

в данном случае элемент $root сейчас содержит весь контент содержимого файла example.xml. Чтобы посмотреть содержимое переменной $root и вообще любого обьекта XML::Twig нужно воспользоваться методом print(), т. е. $root->print. Вызывать print можно только после парсинга, т е в нашем случае после $twig->parsefile("example.xml"), ибо как не трудно догадаться выводить ему будет просто нечего.

Замена тега

Чтобы изменить тег <chapter> на <part> нужно:

my $chapter = $root->first_child('chapter');

$chapter->set_tag('part');

Метод first_child возвращает первого "ребенка" элемента $root с названием part. После используем метод set_tag чтобы задать тегу part новое название — chapter. После этих манипуляций документ примет вид:


<document pubdate="2008-06-06">
<part>
....................................................
</part>
</document>

Обработка потомков

К примеру есть задача найти все теги <section> в теге <part> и удалить их, оставив при этом их содержание. Воспользуемся методом children:

foreach my $section ( $part->children('section') ) {

$section->erase;

}

метод children возвращает список детей элемнта, в данном случае детей под названием section. Если в скобках ничего не указывать, т е $part->children(), то метод вернет список всех детей, т е (section, section, para). Метод erase более подробно описывается ниже.

после этого документ примет вид:


<document pubdate="2008-06-06">
<chapter>
<title>Атрибуты подпрограммы:</title>
<list>
<item>locked</item>
<item>method</item>
<item>lvalue</item>
</list>
<para>Разыменовывающие префиксы:</para>
<list type="bullet">
<item><bold>Скаляр</bold> $ </item>
<item><bold>Массив</bold> @ </item>
<item><bold>Хеш</bold> % </item>
</list>
<para>"Выполнять линейный просмотр в ассоциативном массиве — все равно что пытаться забить кого-нибудь до смерти заряженным Узи" Ларри Уолл</para>
</chapter>
</document>

Работа с атрибутами

Удаление атрибутов

Предположим что нужно удалить атрибуты у root'ового документа, для этого воспользуемся методом del_atts, т е $root->del_atts, после чего тег <document pubdate="2008-06-06"> станет просто <document>.

Добавление атрибутов

Добавим к тегу атрибут attention с значением 1:

my $para = $chapter->first_child('para');

$para->set_att('attention' => '1');

Результат:


<document pubdate="2008-06-06">
<chapter>
................................
<para attention="1">"Выполнять линейный просмотр в ассоциативном массиве — все равно что пытаться забить кого-нибудь до смерти заряженным Узи" Ларри Уолл</para>
</chapter>
</document>

Извлечение содержимого тега

Для извлечения содержимого тега <title> нужно воспользоваться методом text:

my $title = $section->first_child('title');

$title_content = $title->text;

print $title_content,"\n";

Результатом будет строка: "Атрибуты подпрограммы:"

Метод text возвращает содержимое тега исключая любые другие теги. Т е если к примеру document_title будет:


<document_title>
<title1>Title 1</title1>
<title2>Title 2</title2>
</document_title>

и выполнить $document_title->text вывод будет: Title 1Title 2

Удаление тега

Для удаления тегов есть два метода, erase и delete. Erase удаляет сам тег, оставляя все содержимое. Delete также удаляет сам тег, но в отличие от erase также удаляет все его содержимое. К примеру:

my $section = $para->first_child('section');

$section->erase;

Результат будет:


<document pubdate="2008-06-06">
<document_title>Some title</document_title>
<part>
<title>Атрибуты подпрограммы:</title>
<list>
<item>locked</item>
<item>method</item>
<item>lvalue</item>
</list>
<section userlevel="2">
..............................................................

Если использовать delete, т е:

$section->delete;

Результат будет:


<document pubdate="2008-06-06">
<document_title>Some title</document_title>
<part>
<section userlevel="2">
<para>Разыменовывающие префиксы:</para>
<list type="bullet">
<item><bold>Скаляр</bold> $ </item>
<item><bold>Массив</bold> @ </item>
<item><bold>Хеш</bold> % </item>
</list>
</section>
<para>"Выполнять линейный просмотр в ассоциативном массиве — все равно что пытаться забить кого-нибудь до смерти заряженным Узи" Ларри Уолл</para>
</part>
</document>

Как видно от первой секции ничего не осталось.

Сохранение в файл

Для сохранения в файл в XML::Twig есть метод с незамысловатым названием print_to_file. Пример использования:

my $twig = XML::Twig->new();

$twig->parsefile("example.xml");


my $root = $twig->root;

$root->set_pretty_print('indented');


my $part = $root->first_child('part');

my $section = $part->first_child('section');

$section->delete;


$twig->print_to_file("result.xml");


Измененный контент example.xml будет сохранен в файл result.xml.

Метод get_xpath

К примеру есть необходимость заменить все теги <item> на <listitem>. Для этой цели можно использоваться методом get_xpath. Сей замечательный метод возвращает список всех тегов которые удовлетворяют значению в скобках, '//' используется для того чтобы получить всех потомков.

my @item_collector = $root->get_xpath("//item");

foreach (@item_collector) {

        $_->set_tag('listitem');

}

После последней манипуляции документ будет выглядить так:


<document pubdate="2008-06-06">
<document_title>Some title</document_title>
<part>
<section userlevel="1">
<title>Атрибуты подпрограммы:</title>
<list>
<listitem>locked</listitem>
<listitem>method</listitem>
<listitem>lvalue</listitem>
</list>
</section>
<section userlevel="2">
<para>Разыменовывающие префиксы:</para>
<list type="bullet">
<listitem><bold>Скаляр</bold> $ </listitem>
<listitem><bold>Массив</bold> @ </listitem>
<listitem><bold>Хеш</bold> % </listitem>
</list>
</section>
<para>"Выполнять линейный просмотр в ассоциативном массиве —
все равно что пытаться забить кого-нибудь до смерти заряженным Узи" Ларри Уолл</para>
</part>
</document>

Все теги <item> содержащиеся в элементе $root были изменены на <listitem>.

Дополнительные примеры:

1) Нужно поменять все теги list в зависимости от атрибута, если list без атрибутов, то изменить его на orderlist, а если с атрибутом type и последний равен bullet, то изменить его на bulletlist при этом удалив атрибуты. Воспользуемся вышеупомятым методом get_xpath:

my @list_collector = ($root->get_xpath("//list"));

foreach my $list (@list_collector) {

if ($list->has_no_atts) {

$list->set_tag('orderlist');

}

if ($list->has_atts && $list->att('type') eq 'bullet') {

$list->set_tag('bulletlist');

$list->del_atts;

}

}

Результат:


<document pubdate="2008-06-06">
<chapter>
<section userlevel="1">
<title>Атрибуты подпрограммы:</title>
<orderlist>
<item>locked</item>
<item>method</item>
<item>lvalue</item>
</orderlist>
</section>
<section userlevel="2">
<para>Разыменовывающие префиксы:</para>
<bulletlist>
<item><bold>Скаляр</bold> $ </item>
<item><bold>Массив</bold> @ </item>
<item><bold>Хеш</bold> % </item>
</bulletlist>
</section>
<para>"Выполнять линейный просмотр в ассоциативном массиве —
все равно что пытаться забить кого-нибудь до смерти заряженным Узи" Ларри Уолл</para>
</chapter>
</document>

2)Скопировать все теги section с содержимым в отдельный файл, предварительно заключив в тег document. В этом примере воспользуемся модулем FileHandle, как результат в начале нужно прописать use FileHandle. Если сей модуль не установлен, в Linux' е его можно поставить командой: cpan install FileHandle

my @section_collector = $root->get_xpath("//section");

my $counter = 0;

foreach my $section (@section_collector) {

#Создаем новый пустой тег document

my $document = XML::Twig::Elt->new( document => '' );

$document->set_att( 'docref', "document$counter" );

#вставляем элемент $section с содержимым в тег document

$section->move( first_child => $document );

#сохраняем элемент document в файл

my $fh = FileHandle->new();

$fh->open(">result$counter.xml");

$document->print($fh,"indented");

$fh->close;

$counter++;

}

в результате в текущем каталоге появятся два файла: result0.xml и result1.xml

PS: Если вы нашли ошибки/неточности, сообщите пожалуйста. Обоснованная критика принимается :)