Некоторое время назад нами был начат проект по разработке веб-приложения для специфических нужд нашего заказчика. Первая версия готова к сдаче в эксплуатацию. Проект был сделан на Ruby on Rails силами одного человека (меня) в течение месяца. Хочу поделиться первыми впечатлениями от реального использования фреймворка.

Что такое Ruby on Rails

Ruby on Rails — это современный высокоуровневый фреймворк веб-разработки. Создатели утверждают, что Ruby on Rails позволит в разы повысить продуктивность веб-разработчиков по сравнению с предыдущими популярными технологиями, такими как PHP. Версия 1.0 вышла в прошлом году и с тех пор Ruby on Rails быстрыми темпами набирает популярность.

В целом, при работе с Rails возникает ощущение, что попал в светлое завтра веб-разработки. На вещи, которые делаешь в первый раз, времени уходит столько же, сколько на реализацию того же самого в десятый раз на том, с чем я работал раньше. Начиная со второго раза – в два-три раза меньше. Сравниваю, в первую очередь с PHP, ASP и ASP.NET, с которыми я более-менее серьезно работал в прошлом, и с Django, знакомым по паре микроскопических проектов, сделанных для собственного удовольствия.

Сам по себе Ruby тоже очень хорош. Пока не могу понять, нравится ли он мне больше, чем Python… Но то, что больше всего остального — совершенно точно.

5 самых приятных моментов Ruby on Rails

  1. Schema Migration. Как правило, одной из основных проблем разработки программных продуктов является сложность внесения изменений в структуры базы данных. В результате возникает желание спроектировать всю структуру заранее, что плохо согласуется с итеративной разработкой. Разработанная заранее структура часто не полностью соответствует логике приложения. Кроме того, не всегда понятно в каком виде хранить структуру данных. В единственном экземпляре на тестовом сервере? Класть дамп БД в систему управления версиями?

    Rails помогает решить все эти проблемы с помощью входящих в него функций эволюционного преобразования структуры БД (Schema Migration). Вы описываете исходную структуру БД, а затем описываете каждое изменение в виде так называемой «миграции», описывающей операции по обновлению структуры БД до следующей версии. В миграциях легко описываются как стандартные, так и весьма нетривиальные на некоторых платформах преобразования (переименование таблиц и полей). Rails хранит в базе версию ее структуры, что позволяет надежным и предсказуемым образом обновить любую БД до последней версии. Гораздо проще использовать миграции, чем пользоваться дампом тестовой БД и потом мучительно пытаться обновить устаревшую БД заказчика, не потеряв по дороге данные. Кроме того, миграции позволяют вернуть структуру БД к предыдущей версии, что очень полезно, когда в установленной у заказчика новой версии обнаружилась критическая ошибка. Имея возможность откатить структуру БД к более старой версии, вы можете спокойно вернуть все приложение к последней стабильной версии и без суеты начать исправлять ошибку. Куда безопаснее, чем пытаться героическими темпами исправить проблему прямо на сервере заказчика.

  2. Rake. Также в состав Rails входит Rake (инструмент сборки, аналогичный Make) и комплект стандартных задач к нему. В результате вы, как минимум, сэкономите за время написания и тестирования приложения немало времени на выполнении стандартных операций — очистке логов и временных файлов, обновлении структуры БД, запуске тестов и т.д. Если же вы знаете, как пользоваться подобными инструментами сборки, то вы получаете мощную базу для дальнейшей кастомизации, экономя при этом кучу времени на написание того же самого с нуля. В дополнение к Rake существует Capistrano — утилита, предназначенная для выполнения задач на нескольких серверах, позволяющая существенно упростить развертывание вашего приложения.

  3. Convention over Configuration. Этот принцип архитектуры Rails можно перевести как «соглашения вместо настроек», а его использование призвано свести к минимуму количество стандартного кода, которое вы пишете. Фактически, речь идет об очень продуманной системе значений по умолчанию. Речь идет не только о значениях по умолчанию в методах стандартной библиотеки. Например, стандартно названные «куски» вашего приложения будут автоматически связываться друг с другом без вашего участия — класс данных Work будет по умолчанию считать себя представляющим данные таблицы works и т.д. Можете попрощаться с шаблонным кодом инициализации и списком импортов на треть страницы.

  4. Поддержка автоматизированного тестирования. Ruby on Rails делает все возможное для того, чтобы писать автоматизированные тесты для вашего приложения было как можно проще. Режим тестирования позаботится о том, чтобы отправленные в тестах письма никуда не ушли, чтобы тестовые данные никак не соприкасались с рабочими, а изменения в БД, сделанные одним тестом, не влияли на следующий. Rails включает библиотеки для поддержки блочного, функционального, интеграционного и нагрузочного тестирования

  5. Красивые URL’ы. Rails четко отделяет URL’ы от имен файлов, названий методов и прочих сугубо внутренних деталей вашего приложения. При этом вместо sites/view.php?id=245 вы получаете /sites/245 и для этого не приходится копаться в .htaccess-файлах на каждой машине, где оно будет стоять. Синтаксис схемы URL’ов гораздо понятнее, чем синтаксис настроек mod_rewrite и к тому же избавляет вас от предположения, что в качестве веб-сервера обязательно будет использоваться Apache. Дополнительный бонус — функция формирования ссылок использует для формирования URL’ов имена ваших классов и методов. В результате вы можете перенастроить схему URL’ов не меняя при этом ни строки кода в вашем приложении – и все будет работать.

Здравствуй, грабли!

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

  1. ERb, движок шаблонов, используемый в Ruby on Rails, ведет к появлению безумной мешанины кода и HTML, так характерной для PHP-программ сомнительного качества. Вот кусок одного из моих шаблонов:

    <td class='site_description'><%= truncate(site.human_description, 60) %></td>
    <td class='site_edit'><%= link_to 'Edit', edit_site_url(:id => site.id) %></td>
    <td>
      <% if site.works.empty? and site.estimates.empty? %>
        <%= link_to 'Add&nbsp;estimate', :controller => 'estimates',
              :action => 'new', :site_id => site %>
      <% else %>
        <%= link_to 'Add&nbsp;work', :controller => 'works',
              :action => 'new', :site_id => site %>
      <% end %>
    </td>
    

    Не очень эстетично, правда? А ведь это стандарт… Есть как минимум одна неплохая альтернативная реализация, но версия 1.0 вышла только месяц назад, и, кто знает, сколько еще пройдет времени до того, как она получит более-менее заметное распространение.

  2. Валидация данных как будто гвоздями прибита к моделям. Так хорошо интегрирована, что захочешь — не отдерешь. Отличное решение, если вам надо работать с данными, хранимыми в БД. Так что пока идет реализация функций редактирования данных — все танцуют. Легко и изящно решены и такие относительно распространенные вещи как проверка согласия с user agreement’ом. Потом настает очередь настраиваемых отчетов и продвинутого поиска. И, сюрприз! — вы в жопе… Стандартная валидация не работает. То есть совсем. Потому что модели данных, на которую можно завязать поля вашей формы продвинутого поиска не существует в природе. Не сомневаюсь, что есть грязный трюк, с помощью которого можно обойти эту проблему, но найти его за разумное время мне не удалось. Два балла.

  3. Совершенно ужасны стандартные Date и Time control’ы. Date control выглядит вот так:

    Date control in Ruby on Rails

    Time control ничем не лучше. Кроме того, у этих control’ов бывают проблемы с валидацией. А если использовать их без привязки к ActiveRecord, то придется вручную собирать дату или время из отдельных «кусочков», полученных в виде параметров. Стыд и позор! Сравните с тем, как это выглядит в Django:

    Django Date and Time controls.

    Без комментариев.

  4. Урезанная поддержка БД по умолчанию. Настоящим ковбоям не нужны удаленные ключи! Мало того, что удаленные ключи отключены по умолчанию, библиотека миграций еще и не включает в себя функций по их созданию. Придется писать свои. Так же по никто и не подумает автоматически создать для вас индекс по полю удаленного ключа. Так что тем из нас, кто использует для production что-то посерьезнее SQLite, придется совершить несколько больше ручных манипуляций, чем предполагает дух Ruby on Rails.

    В принципе, если вы редактируете данные только через ваше приложение, написанное на Ruby on Rails, то это не особенно серьезная проблема — Rails и сам неплохо справляется с поддержанием целостности данных. Но если с базой взаимодействуют другие приложения или вы часто меняете данные непосредственно через SQL-консоль, то отсутствие удаленных ключей может оказаться весьма неприятным сюрпризом.

  5. Я столкнулся с мистическими багами ruby 1.8.5 на FreeBSD 5.4. В ряде случаев Ruby падает, выдавая Core Dump. В частности, не работает Rake, проваливаются несколько тестов в плагине acts_as_authenticated и где-то раз в сутки (update: уже каждые пять минут) падает mongrel. Неприятно. Проблема, скорее всего в железе или операционке, “но неприятных осадок остался”. Как решится — напишу.

На этом список неприятностей заканчивается. Для меня ничего из перечисленного даже близко не стоит с ViewState и необходимостью использовать IIS (ASP.NET) или отсутствием namespace’ов в языке (PHP).

Хочу подчеркнуть что «проблемы» Rails, как правило, заключаются в том, что фреймворк устанавливает у разработчика высокие ожидания относительно уровня абстракции. Когда из-за закона дырявых абстракций некоторые вещи приходится реализовывать на более низком уровне, сравнимом с тем, который предлагает, например, PHP — разработчик ощущает разочарование. Так что перечисленные проблемы вовсе не являются основанием не использовать Rails, это скорее список возможностей, упущенных создателями. Учитывая, что текущей версией является все лишь 1.2, возможностей улучшить ситуацию будет предостаточно. И даже с учетом всех этих проблем скорость и удобство создания нового веб-приложения на Ruby on Rails в разы превосходит таковые на старых платформах.

Выводы

Настоятельно рекомендую хотя бы попробовать Ruby on Rails. Даже если в ближайшее время вы не сможете использовать Rails в своей непосредственной работе, то его все равно стоит изучить. Почувствовав стиль и принципы Ruby on Rails, вы поймете к чему надо стремиться, а это поможет вам при разработке веб-приложений на любом языке и любой платформе.

Материалы по теме

  • RubyOnRails.com. Домашняя страница проекта.

  • RubyOnRails.ru. Она же на русском.

  • Ruby on Rails Tutorial, Revisited (part 1). Хороший Tutorial, с лихвой окупающий пару часов, которые надо потратить на его вдумчивое освоение. Состоит из двух частей, ссылка на вторую часть есть где-то в конце первой, поэтому не буду ее здесь приводить.

  • Отличная шпаргалка по Ruby on Rails. Кратко описывает все самые важные вещи на одной (пусть и большой) странице. Открыта у меня постоянно и используется не реже чем Rails API.

  • Русскоязычная дискуссионная группа о Ruby on Rails. Основное место живого общения о Ruby on Rails на русском языке. 20% тем хороши, информативны и полезны для разработчиков самого разного профессионального уровня. Ну а 80% тем, как и в любом другом месте — полный мусор.