Обновление сайта до Ruby on Rails 3 - отчет

April 5, 2011 ActionPack bundler CarGid Ruby Ruby on Rails Ruby on Rails 3 rubygems

За последний месяц я обновил два сайта на Ruby on Rails 3. Первый – RentFeed – обновить было несложно, потому что функционала там немного. На обновление CarGid ушло около 40 человеко-часов; теперь и он работает на Ruby on Rails 3.

До обновления существующего сайта советую ознакомиться с Rails 3 на новом проекте. Нет, не так – считаю, что нельзя обновлять проект, не работав никогда с Rails 3.

Эта статья – не руководство по обновлению, а мои заметки о нем. Полноты раскрытия темы не обещаю.

Мотивация

Зачем тратить 40 часов на то, что не принесет ни новой функциональности, ни новых пользователей, ни существенного прироста производительности? Причины такие:

Мое такое мнение, что обновляться уже пора. После знакомства с третьими рельсами недостатки вторых начинают бросаться в глаза.

Подготовка

Создаем ветку rails3 в репозитории.

Устанавливаем плагин rails_upgrade. Следуя инструкциям плагина, создаем резервные копии ценных файлов, а также создаем новый routes.rb и application.rb, и, если bundler еще не задействован, новый Gemfile. Помимо это, делаем:

rake rails:upgrade:check > upgrade_log.txt

Пригодится.

Коммитим изменения, дабы ничего не потерять.

Подбор гемов

Удаляем плагин rails_upgrade, ибо он больше не пригодится.

В Gemfile нужно принудительно указать gem 'rails', '~> 3.0.0', а кроме этого, если используется MySQL – то и gem 'mysql2'. Остальные гемы оставляем без изменений.

Возносим молитвы.

Производим bundle update. Эта команда попробует подобрать такие версии гемов, которые заработают с Rails 3.

Скорее всего, у нее это не получится. Проблемы с совместимостью решаются гуглением – большая часть гемов уже работает с Rails 3. Заодно пройдись по плагинам – возможно, некоторые из них также уже доступны в виде гемов.

Результатом этого этапа будет успешно собранный Gemfile.lock; коммитимся.

Установка Rails 3

Выполняем в каталоге проекта

rails .

Да, просто так. Эта команда предложит затереть ряд файлов – разрешаем, ведь все под контролем (версий, в смысле).

Коммитимся. Теоретически проект уже работоспособен (но вряд ли).

Зачистка

Убираем все файлы в script, кроме script/rails - они больше не используются.

Меняем mysql на mysql2 в database.yml, если используется MySQL.

Заменяем базовый config/application.rb на тот, который сгенерировали.

Подчищаем роуты

Подставляем тот routes.rb, который сгенерировали из старых роутов. Увы, скорее всего он сломанный и содержит синтаксические ошибки. Устраняем их.

Вот теперь проект точно должен запуститься.

Модели

В моделях надо будет поменять named_scope на scope и переформулировать запросы в Arel. Это пока необязательно.

Контроллеры

В контроллерах ничего особенного не поменялось

Виды

Большая часть времени уйдет именно на обновление видов.

Изменения в Javascript

Разнообразные рельсовые обработчики событий теперь вынесены в отдельный Javascript-файл, что прекрасно. Его нужно подключить. Для jQuery этот файл берется из репозитория rails/jquery-ujs.

Этому файлу нужен authenticity_token, поэтому в заголовок дописываем

<head>
  ...
  <%=csrf_meta_tag %>
</head>

- style block helpers are deprecated. Please use =

Это такая шутка разработчиков, по-видимому. Везде, где используются блочные хелперы, придется дефис поменять на знак равенства:

<!-- было -->
<%-form_for @foo do %>

<!-- надо -->
<%=form_for @foo do %>

Слава богу, делать это не обязательно. Но ошибки в лог будут сыпаться.

Введение обязательного html_safe

В Rails 3 все строки, выводимые в шаблон, неизбежно проходят через эксейпинг. Это прекрасно, поскольку в 98% случаев ты выводишь текст, требующий оного.

<%=@blog_post.title_needs_to_be_escaped%>
&lt;script&gt;alert('U NO ESCAPE JAVASCRIPT');&lt;/script&gt;

Хелперы h можно не убирать, двойного эскейпинга не произойдет:

<%=h @blog_post.title_needs_to_be_escaped%>
&lt;script&gt;alert('U NO ESCAPE JAVASCRIPT');&lt;/script&gt;

Как же выводить текст с тегами? Применять к нему метод String#html_safe:

<%=@blog_post.nice_text_with_markup%>
&lt;FONT COLOR="#FF00FF"&gt;ЛОВИ СИМПАФКУ!&lt;/FONT&;gt

<%=@blog_post.nice_text_with_markup.html_safe%>
<FONT COLOR="#FF00FF">ЛОВИ СИМПАФКУ!</FONT>

Получается, во местах, где ты выводишь строку с тегами, придется дописывать html_safe. Это сложный и кропотливый кусок работы, который нужно сделать в обмен на чистый и безопасный код.

ActionMailer

Синтаксис ActionMailer поменялся. Мейлеры придется переписать, а скорее, переформатировать. Это довольно прозрачный процесс.

Тесты

Разумеется, процесс обновления будет проще, если проект покрыт тестами. Если не покрыт, то, вполне возможно, ты (как и я) решишь заняться тестами перед обновлением. Однако советую начинать сразу после обновления: Rspec 2 работает только с Rails 3.

Обновляем

Скорее всего, ничего кроме исходников обновлять на сервере не придется, поэтому обновление ничем не будет отличаться от обычного деплоя. Возможно, придется сначала обновить на сервере Rubygems и Bundler.

Buy Me a Coffee at ko-fi.com