Записи с меткой ‘helpers’
Кэширование фрагментов HTML кода в шаблонах ActionMailer
Задача: реализовать кэширование фрагментов HTML кода в шаблоне письма для рассылки.
Первое решение которое приходит в голову – это использовать хелпер cache, например так:
<h1>Result has been executed for long time</h1>
<% cache cache_key do %>
<div>
<%= doing_something_long_time_and_show_result %>
</div>
<% end %>
...
Но этот способ не работает, так как ActiveMailer не содержит методы для кэширования. И в результате у нас ошибка:
/Users/undr/.rvm/gems/ruby-1.9.2-p180/gems/actionpack-3.0.7/lib/action_view/helpers/cache_helper.rb:37:in `cache'
...
Второй вариант, это использовать Rails.cache.fetch:
<h1>Result has been executed for long time</h1>
<%= Rails.cache.fetch cache_key do %>
<div>
<%= doing_something_long_time_and_show_result %>
</div>
<% end %>
...
Ошибки уже нет, но результат не верный. В кэш попадает все содержимое шаблона, а не часть в блоке, и, как следствие, в результате письмо содержит дублированные куски HTML кода. То есть сначала выводится заголовок, потом опять заголовок и содержимое блока.
Чтобы убрать дублирование HTML кода в результате, нужно написать примерно такой хелпер:
Rails.cache.fetch(key) do
with_output_buffer(&block)
end
end
И в шаблоне вызывать его.
<h1>Result has been executed for long time</h1>
<%= mailer_cache cache_key do %>
<div>
<%= doing_something_long_time_and_show_result %>
</div>
<% end %>
...
Как тестировать помощники для rails с помощью rspec, использующие методы render(), concat() и capture()?
Когда я писал небольшой плагин для rails, добавляющий в приложение возможность быстрого создания javascript вкладок, у меня возникли трудности с тестированием. Методы плагина, которые использовали методы render(), concat() и capture(), невозможно было нормально протестировать, все время возникали ошибки в самих тестах.
Правильные окончания для единственного и множественного чисел
Эта небольшая функция поможет отобразить правильные окончания у существительных в единственном и множественном числе
{
if($number > 20) { $strval = strval($number); $number = $strval[strlen($strval) - 1]; }
if ($number == 0) { return $two; }
if ($number == 1) { return $one; }
if ($number > 1 && $number <= 4) { return $two; }
if ($number > 4 && $number < 21) { return $three; }
}
Используем:
<?= pluralize(1, "медведь", "медведя", "медведей"); ?>
// 2 медведя
<?= pluralize(2, "медведь", "медведя", "медведей"); ?>
// 6 медведей
<?= pluralize(6, "медведь", "медведя", "медведей"); ?>
//21 медведь
<?= pluralize(21, "медведь", "медведя", "медведей"); ?>
Избавляемся от операторов if и foreach в шаблонах
Часто в шаблонах приходится использовать вывод по условию. В результате шаблон обрастает трудно читаемыми конструкциями, типа:
< ? foreach($comments as $comment): ?>
< ?= include_view("comment", array("comment" => $comment)) ?>
< ? endforeach ?>
< ? endif ?>
< ? if($reader->canWriteComments()): ?>
< ?= include_view("comment_form") ?>
< ? endif ?>
или
Можно написать помощника, который будет выводить текст по условию.
Исчезающие flash сообщения
Для передачи сообщений от запроса к запросу используют flash сообщения. Чтобы организовать работу по отображению flash сообщений можно написать помощник, который будет скрывать сообщение по прошествии какого-то времени, чтобы оно не мешало.
Помощники с блоком аля content_for для Rails в cakePHP
По ходу разработки одного проекта на cakePHP возникла необходимость создания помошника, использующего блок, как в ruby. Использовали jQuery, и конструкцию $(document).ready(function(){…}) добавляли в разных шаблонах и подшаблонах.
В результате эти блоки оказывались разбросанными по всему HTML документу. Это не очень удобно при отладке. Приходится перемещаться по всему документу в поисках нужного блока. Чтобы исправить ситуацию, создали помошник, который собирает все куски $(document).ready(function(){…}) в разных подшаблонах и размещает их в одном месте, например, в секции head страницы.
Помошник действует по принципу рельсовой вспомогательной функции content_for, которой в блоке передается кусок шаблона для отображения в другом месте.
Были созданы три функции: jQueryReadyStart(), jQueryReadyEnd(), jQueryReadyShow(). Тело $(document).ready(function(){…}) помещалось между двумя вызовами функций jQueryReadyStart() и jQueryReadyEnd().

