Почему стоит переходить на Ruby и Rails. Ruby on Rails. Первые шаги

Привет. Я использую Rails уже значительное время - 5 лет (это, по-моему, значительное). В этой статье я попробую подытожить свой опыт и ответить на вопрос: почему я все еще использую Rails и почему его должны (или не должны) использовать вы.

Для начала ответим на вопрос из заголовка. Действительно ли Rails популярен сейчас, в середине 2015 года?

Вот эта забавная таблица сравнений по критериям популярности репозитория на GitHub и количества вопросов на StackOverflow (https://hotframeworks.com/) говорит что Rails всё ещё в топе:

class Customer < ActiveRecord :: Base has_many :orders end class Order < ActiveRecord :: Base belongs_to :customer end

И это все. Это работает без единой строчки конфигурации. По умолчанию предполагается, что в базе у вас есть таблицы orders и customers . В orders есть внешний ключ с именем customer_id . Первичные ключи называются id . На этом все. Вы соблюдаете соглашения именования и все само работает. Теперь вы можете строить и выполнять SQL-запросы совершенно очевидным и естественным способом:

customer . orders #=> order . customer #=> customer

Окей, идем дальше. Маршрутизация запросов (routes). Это поразительно. Вы можете все, и очень многое из этого “всего” бесплатно. Но это если вы руководствуетесь соглашениями. Пример маршрута из документаци

resources :books

Благодаря магии Rails эта одна скромная строчка способна создать пачку маршрутов для CRUD:

$ bundle exec rake routes | grep book books GET /books(.:format) books#index POST /books(.:format) books#create new_book GET /books/new(.:format) books#new edit_book GET /books/:id/edit(.:format) books#edit book GET /books/:id(.:format) books#show PATCH /books/:id(.:format) books#update PUT /books/:id(.:format) books#update DELETE /books/:id(.:format) books#destroy

Опять-таки, по соглашениям именования у вас должен быть класс BooksController и аналогичные методы index/create в нём, т.е. books#index соответствует BooksController#index . Добавьте к этому ограничения (constraints), пространства имен (namespaces), модули (modules).

HTML-формы. Что тут можно улучшить? Нtml есть html, от него никуда не убежишь, но можно попытаться уменьшить боль. Пример создания формы из документации :

<%= form_for @article, url: {action: "create"}, html: {class: "nifty_form"} do |f| %> <%= f.text_field:title %> <%= f.text_area:body, size: "60x12" %> <%= f.submit "Create" %> <% end %>

Предполагается что @article это ActiveRecord модель, но по факту здесь может быть любой произвольный объект. В том числе, если использовать шаблон FormObject, здесь может быть объект абсолютно отвязанный от слоя ORM.

Миграции базы данных. Здесь все стандартно. Можно, просто и быстро.

Аутентификация пользователя и сопутствующий функционал - регистрация, вход, выход, восстановление пароля. Чтобы это все заработало, вам нужно воспользоваться одной из нескольких доступных библиотек: Devise, Authlogic итд. Вам надо добавить всего несколько стандартных строк для подключения.

Развертывание (deploy) приложения на сервер. Есть стандартное решение - capistrano. Пример стандартного скрипта с комментариями: (ссылка на gist).

# config/deploy.rb # config valid only for current version of Capistrano lock "3.4.0" set :application , "aircat" set :repo_url , "[email protected]:applabsservice/aircat.git" set :deploy_to , "/var/www/apps/aircat" set :git_shallow_clone , 1 set :deploy_via , :copy set :branch , "master" set :host , "127.0.0.1" set :user , "deploy" role :app , %w{[email protected]} role :web , %w{[email protected]} role :db , %w{[email protected]} namespace :db do desc "Make symlinks" task :symlink do on roles (:app ) do execute "ln -nfs #{ shared_path } /config/database.yml #{ release_path } /config/database.yml" end end end after "deploy:updating" , "db:symlink" # дальше идут другие callback"и для перезапуска веб-сервера

Что это дает? При каждом развертывании новая версия приложения копируется в отдельный каталог релиза, рядом с предыдущими. Запускаются миграции, идет компиляция/склейка/минификация статичных css/js файлов, и когда всё готово, веб-сервер переключается на каталог с новым релизом. В случае ошибки на любом из шагов можно просто вернуться на предыдущий релиз. Новый код запускается уже на обновленной базе. Есть нюанс, что во время миграций некоторое время с обновленной базой работает старый код. Но это тоже решается.

class Post < ActiveRecord :: Base has_attached_file :image , styles : { standard : "1280x1280>" }, default_url : "/images/:style/missing.png" validates_attachment_content_type :image , content_type : /\Aimage\/.*\Z/ has_attached_file :video end

И это все. Можно автоматически сгенерировать миграцию, чтобы сохранять метаданные файла в базе и это уже работает:

post . image = File . read ("test.jpeg" ) post . save

Все, файл помещен в правильный каталог на диске. Если это картинка, её можно обрезать, cконвертировать, сжать. Сделать несколько вариантов разрешений парой магических строчек.

Локализация - да, есть как у всех, всё просто и стандартно.

Тестирование. В стандартной библиотеке Ruby есть фреймворк для unit-тестирования. В Rails из коробки есть поддержка функциональных и интеграционных тестов, но намного круче воспользоваться связкой RSpec для модульных тестов и Capybara + webdriver для интеграционных. Представьте - вы можете в интеграционных тестах запускать настоящий браузер, установленный в системе (например через Selenium Webdriver), или headless браузер на базе WebKit. Второй вариант пока что надежнее, стабильнее и быстрее.

Из минусов для разработки можно выделить следующее:

  • Rails даёт вам соглашения. Вы следуете им. Ваш код лаконичен, красив, покрыт тестами, всё сделано по Rails-way. Но есть и обратная сторона. Вы получаете большую связанность компонентов, толстые контролеры или толстые модели. Rails предлагает шаблон MVC, но ничего сверх этого. Нет никакого стандартного слоя абстракции - это решение ложится на ваши плечи. Если вы заметили, что стандартные компоненты (views, models, controllers) уже перенасыщены несвойственной им логикой, вы должны что-то делать. Какие у вас варианты? Можете начать рефакторить, выносить логику в отдельные слои - об этом уже немало написано. Можно использовать Form-объекты, выносить сложный SQL в независимые объекты, отделить бизнес-логику от ORM/контроллеров.
  • Документация для Rails и популярных библиотек отличная, но это всё равно не избавит вас от изучения их исходного кода, чтобы разобраться с упущенными в документации моментами. Иногда код скажет даже больше.
  • Скорость развития инструментов и библиотек имеет очевидную обратную сторону - вам периодически придётся обновляться до последних версий. Это относится и к версиям Rails, и к библиотекам. Переход на другую мажорную версию библиотеки для тестирования может занять не один и не два дня. Возможен вариант, когда появляется какой-то удачный аналог используемой вами библиотеки. Ваша библиотека постепенно перестает развиваться и поддерживаться, и внезапно вы обнаруживаете, что она не работает в очередной версии Rails и придётся переходить на аналоги. Ничто из этого не специфично только для Rails, но в долгоживущем проекте вы с этим столкнетесь с большой вероятностью.

Когда вам нужен Rails?

  • Вы разрабатываете обычное веб-приложение. Вы ожидаете, что проект будет жить долго. Вам нужно, чтобы инструмент продолжал развиваться и жить, нужна поддержка от сообщества или от какой-нибудь компании, возможность нанять специалиста. В таком случае, Rails - прекрасный выбор. Альтернатив хватает, выбирать есть из чего. Но вы все равно выберете Rails, ведь это по-прежнему модно;-)
  • Вы предполагаете постоянное изменение требований и функционала, вектора развития проекта. У вас нет постоянной концепции продукта, она меняется и зависит от обратной связи с пользователями. Rails в этом случае отличный выбор.
  • Вам нужно “быстрое прототипирование”. Rails до сих пор хорош для этого. Альтернативы, конечно же, найдутся, но Rails очень хорош и в этом.

Когда вам не нужен Rails?

  • Вы отчётливо понимаете требования к проекту и функционалу. Вы не ожидаете быстрых изменений функционала. К примеру, у вас уже есть прототип или вы уже делали что-то очень похожее и можете сразу отливать архитектуру в бронзе.
  • Вы ищете то, чего никогда не найдёте в динамически типизированном языке, - высокую (высочайшую) скорость работы и низкое потребление ресурсов сервера.
  • У вас уже есть команда профессионалов которые хотят использовать другой фреймворк.

Ну вот и всё. В заключение я добавлю, что получаю большое удовольствие, используя Rails и Ruby. Это очень удобные инструменты, мягкие и податливые, как пластилин. В умелых руках они помогают создавать волшебные вещи.

Алексей Дмитриев: Здравствуйте. Меня зовут Алексей Дмитриев, и я занимаюсь веб-разработкой последние лет 7. Сначала я писал на PHP и Perl, потом перешел на Ruby, который использую последние 4 года.

Что такое Ruby on Rails? Это фреймворк с открытым исходным кодом. Он существует уже достаточно давно. В штате - 8 активных разработчиков плюс огромное сообщество. В общей сложности в разработке Rails участвует 300-400 человек.

Специалисты создают патчи и пишут плагины. Наработки используются в Rails Core. В конце концов, мировое сообщество испытывает удовольствие от работы с этим фреймворком.

Идеология Rails

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

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

У всех Rails-проектов единая структура. Работая над новым проектом, вы заранее знаете, что и где лежит: модели, шаблоны, библиотеки и плагины. Rails построен на базе схемы MVC ("Модель-представление-контроллер"). Логика проектов разделена на три слоя.

В Rails все должно быть протестировано. Если вы попробуете опубликовать некий плагин, расширение или проект открытого программного обеспечения, то скорее всего, не добьетесь успеха, если не будет проведена всесторонняя тестовая проверка.

Главная сила Ruby on Rails скрыта в языке, на котором он написан. Ruby — это скриптовый язык, который выполняется в момент запроса и не требует компиляции.

Также это объектно-ориентированный язык (как Java или С#). Любая сущность внутри Ruby является объектом, будь то строки, числа, классы или модули.

В Ruby типизация динамическая. Для вызова методов не обязательно задавать типы атрибутов. Все переменные в общем равноправны. Вы сами определяете, с чем вы работаете.

В Ruby существует набор определенных модулей. Это функциональность, абстрагированная от классов, в котором она определяется. Есть специальные классы — модули — внутри которых задается функционал, который можно подключать в любой класс.

Например, в класс «строка» можно добавить новый метод. Аналогично - с классом "книга". Они будут работать одинаково (при прочих равных условиях), поскольку определены одни и те же методы.

Для языка Ruby существует очень большое количество реализаций. Фактически Ruby постепенно адаптируется на всех сколько-нибудь значимых виртуальных машинах. Его сейчас можно поставлять как самостоятельный продукт или диалект в Java-машину. Надеюсь, в скором времени можно будет пользоваться им на платформе DotNet (IronRuby).

Этот язык уже используется по умолчанию в новой версии Mac OS (в виде MacRuby), а также портируется на виртуальную машину Smalltalk и Sub. Надеемся, Rails тоже будет доступным везде и всюду.

Структура Rails — это модель, ее контроллер. Модели представлены фреймворком. Rails — это не единый фреймворк, а их конгломерат. Каждый из них отвечает за определенную часть проекта.

Модель представлена фреймворком ActiveRecord. Его можно использовать и вне Rails (допустим, для работы с базами данных). Это объектно-реляционное отображение (англ. Object-relational mapping, ORM). ActiveRecord поддерживает MySQL, PostgreSQL и SQLite.

ActiveRecord может использоваться высокоранговыми базами данных. Попутно для ActiveRecord были написаны несколько плагинов для поддержки проприетарных баз данных: Oracle, Microsoft SQL Server и DB2.

ActiveRecord предоставляет возможность задавать отношения между различными моделями внутри проекта через определенные связи. Один - ко многим, многие - ко многим и полиморфные связи (когда объекты, связанные друг с другом, "не знают", какого класса у них связи).

Все связи расширяемы. Допустим, внутри первой связи мы можем задавать одни методы, внутри второй — другие. Также возможно использование модулей для расширения функционала.

ActiveRecord используется для выборки данных из базы (в отличие от многих фреймворков, которые доступны на рынке). Чтобы работать с базой данных, знать SQL необязательно.

Вообще в Rails-мире считается, если вы пишете на SQL, то вы либо не знаете, что делаете, либо точно знаете, но тогда вам уже по-другому просто никак. Во всех остальных случаях можно обойтись методами ActiveRecord. Это чаще всего более обоснованно, потому что позволяет создавать различные вещи (например, быстро добавлять фильтры в зависимости от условий, при этом не заботясь о формировании SQL).

ActiveRecord при поиске предоставляет защиту от SQL-инъекций. Если вы в запрос напрямую не "втыкаете" параметры, а пользуетесь, например, conditions => name => ‘Google’ и используете параметры, полученные от пользователя, то по умолчанию защита от SQL-инъекций обеспечена.

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

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

Скоро выйдет третья версия Rails. Мы ее ждем уже больше года. В ней ActiveRecord будет разделен еще на несколько частей, появится ActiveModel — Единый интерфейс программирования приложений для хранилищ. Будет снято ограничение на использование реляционных баз данных.

В качестве хранилищ можно будет использовать не SQL-базы данных (MongoDB, Cassandra), Redis и создавать собственные драйверы для хранилищ.

В частности, на ActiveModel будет построена работа с внешними ресурсами через HTTP.

Появится новый язык выборок.

Такие большие конструкции. И как выглядит сейчас.

Язык Ruby стал более мощным.

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

Причем в Rails уже встроена передача представлений состояний (англ. REST). В зависимости от используемого HTTP-метода внутри контроллера будут применены разные методы.

В третьих Rails предусмотрено перенаправление разных методов на разные контроллеры. Это очень удобно в том плане, что вам будет достаточно сформировать запрос правильным образом. Сформировав его, вы будете знать о месте его направления. Серию различных URL создавать больше не требуется. Это удобно при разработке интерфейса программирования приложений (англ. API).

Следующее — это фильтры. В контроллерах предусмотрена возможность пре- и постобработки запроса. Входящий запрос направляется в фильтр, где можно проверить, авторизован ли пользователь и т.д. Полученный результат можно обработать, добавить cookie и ответ. Логику обработки запроса можно разделять.

Контроллер поддерживает ответы в разных форматах. Один и тот же метод на разные запросы может отвечать по-разному. Грубо говоря, если вы создаете запрос на определенный URL из браузера, то получаете HTML. Если вы создаете запрос на AJAX, то получаете JSON.

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

Следующее — это View, т.е. шаблоны, представления, вид представляемых данных. В Rails существует возможность использования собственных шаблонов. По умолчанию используется ERB (embedded Ruby). Это обыкновенный HTML, в котором размещаются фрагменты кода.

В целом это неплохо, но находятся любители других шаблонизаторов, например, HAML. Это шаблонизатор в стиле дзен, где не требуется писать закрывающиеся тэги и угловые скобки.

Для Rails существует около двадцати шаблонизаторов на любой вкус. View поддерживает разные шаблоны для разных майнтайпов.

В зависимости от типа запроса, можно дать соответствующий ответ. Если запрос направляется с HTML-страницы — ответ один, если с RSS — другой. Можно даже выдавать разные страницы на разные языки. В зависимости от языка пользователя, допустимо выдавать разные шаблоны.

В Rails присутствует большое количество помощников (англ. helper), т.е. методов, помогающих формировать страницу. Вместо создания кода вручную, можно использовать помощников. В Rails их достаточно много.

Приведем пример создания формы через помощник form_for. Ему передана модель ActiveRecord. Форма автоматически создает поля, куда вставляется имя самого поля и его значение из модели.

Rails формирует набор помощников (в данном случае — new_user_path), которые помогают проставлять формирование URL соответствующих страниц. То есть new_user_path — это, например, URL страницы добавления пользователя.

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

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

В Rails работает встроенная поддержка локализации. Вы можете сделать приложение многоязычным. В зависимости от запроса пользователя возможна выдача ответов на разных языках. Аналогично - в случае с контроллерами. Доступ к этим данным предоставляется практически везде.

Настоящая сила Rails — в расширениях. Для Ruby и Rails в общей сложности написано более 12 тысяч расширений: плагинов, так называемых Gems (пакетов функционала, который располагается в репозитории, откуда его можно скачать, легко подключить и использовать).

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

Что такое нетиповая задача? Например, это — работа с Excel из UX.

Что касается поиска расширений, то его можно осуществлять всего в двух местах. На GitHub (где располагается большинство плагинов) и RubyGems (где располагается большинство gem).

Не так давно при подготовке к выпуску Rails 3 был разработан Bundler. Это инструмент для формирования зависимости проекта. Если, допустим, ваш проект использует 10-20 различных gem, их можно вручную вставить в систему.

Третья версия Rails максимально адаптирована для расширения. В ней добавлено довольно много возможностей для расшерения Rails.

Каковы типичные ошибки при переходе на Rails?

Первая ошибка. Мы хотим писать на Ruby, как на PHP (или Perl). Это недопустимо, т.к. языки довольно сильно отличаются друг от друга — не синтаксисом, а, скорее, подходом к качеству.

В Ruby более высокий уровень требований к качеству проектов вообще. На сайте Rails приведены примеры того, как надо писать: демонстрации, видеозаписи, руководства и т.д.

Вторая ошибка - изобретение велосипедов. Изобретать нечто новое — очень полезно. Но лучше сначала проверить те 12 тысяч плагинов и gem, о которых я упоминал. Поэтому лучше всего проконсультироваться у специалиста по интересующему вопросу, например, на форуме.

Третья ошибка - ощущение, что Ruby - это панацея от всех бед. Это не так. Перед Ruby стоит вполне конкретная задача — это создание веб-проектов. Обработку видео и графики, создание многопоточных систем на Ruby осуществлять нельзя.

Rails очень хорошо работает в команде с другими сервисами. В частности, в плане поиска (со Sphinx) или обработки изображений (с ImageMagick).

Мифы относительно Ruby on Rails

Существует несколько мифов о Ruby on Rails, которые распространяют люди, никогда на нем не работавшие.

Первый миф - Rails медленнее, чем другой язык

Возможно. Но вопрос в том, как измерять скорость.

Существует определенный набор синтетических тестов, которые измеряют скорость языка программирования при решении типовой задачи. Но подавляющее большинство синтетических тестов меряют абстрактную скорость.

Rails достаточно быстрый, чтобы решать необходимые задачи. Например, необходимо передать человеку изображение или страницу. Будет она сгенерирована за 50 миллисекунд или за 70 - принципиальной разницы в этом нет.

Rails вполне достаточно для того, чтобы поддерживать на одном сервере проекты, в которых задействованы сотни тысяч пользователей в сутки и просходят миллионы просмотров. Как это осуществляется?

Скорость каравана определяется скоростью самого медленного верблюда. При высоких нагрузках самыми медленными верблюдами становятся хранилища. Это база данных, файловая система — то, во что упираются любые проекты.

Самый простой способ ускорить Rails — ускорить то, с чем работает язык. Необходимо оптимизировать базу данных и запросы по сети, если таковые имеют место.

Также необходимо заниматься кэшированием - когда все "падает". Раньше — не имеет смысла.

Нужно помнить о типичной ошибке №3 (Rails не серебряная пуля, т.е. не панацея). Для особо чувствительных к низкой скорости мест рационально использовать более быстрые языки. Может быть, "C". Благо, на нем можно писать расширения для Ruby. Ruby сам написан на "C".

Плюс можно использовать такие замечательные языки, как Perl, Java, C#. Если у вас посещаемость проекта достигает 10 тысяч, а некий виджет с проекта получает 200 миллионов просмотров в сутки, то лучше его написать на Perl. Но писать весь проект на Perl из-за одного виджета, я не вижу смысла.

Миф №2: Rails не масштабируются

Специалисты производственного сектора, для кого кластер начинается от ста серверов, очень любят говорить такое.

«Рельсы» (англ. rails) замечательно масштабируются элементарным добавлением серверов, но упираются в проблему хранилищ. В конечном счете все сводится к масштабированию базы данных, файловой системы и т.п. Сервисы, которые успешно справлялись с данной задачей, существуют.

Третий миф — дорогой хостинг

Стоимость хостинга — $19,95 в месяц. То есть достаточно заплатить 585 рублей, чтобы "поднять" обычный Rails-проект. Время программистов стоит дороже, чем хостинг. Вы можете экономить столько, что вам хватит средств на три таких хостинга.

В каких случаях уместно применение Ruby?

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

Прошло около года с момента публичного дебюта Ruby on Rails в 25 июля, 2004. За этот довольно короткий срок, Rails превратилась из уже достаточно впечатляющей версии 0.5 в устрашающе-вдохновляющую, готовящуюся к выходу версию 1.0, которой удалось сохранить свою простоту использования и продуктивность, в то же время добавив будоражащий ум массив новых возможностей. Эта статья познакомит вас с компонентами грядущей версии Ruby on Rails 1.0 и постарается рассказать, о чём же собственно столько разговоров.

Я не намереваюсь учить вас как использовать Rails для создания веб приложений. Для этого, вам скорей всего следует начать со статьи Rolling with Ruby on Rails. Эта статья, является введением и картой к огромному количеству возможностей Rails.

Высокая продуктивность и высокая скорость разработки

На уровне возможностей, Ruby on Rails не предлагает ничего нового. Существующие веб фреймворки уже всё это делали. В чём же тогда дело? Различие лежит в том, как это делает Ruby on Rails. Когда вы можете закончить простое веб приложение за дни вместо недель и более сложное за недели вместо месяцев, люди обращают на это внимание!

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

Внимание также оказалось бы недолгим, если бы Ruby on Rails не имела глубины - то есть, если бы раз попробовав использовать её для чего-то сложнее самого простого веб приложения, вы сразу натыкались бы на стену, не имея возможности продолжить из-за ограничений системы. Опытные разработчики, которые знают толк во всемирной паутине и программировании не перестают повторять, что для Rails это не так. К примеру, автор Tomcat, Ant и Servlet API, James Duncan Davidson недавно написал:

Rails это самая хорошо продуманная среда веб разработки которую я когда-либо использовал. И это за десять лет моей работы веб разработчиком. Я разрабатывал свои фреймворки, помогал разрабатывать Servlet API, и создал больше пары веб серверов с нуля. До Rails, никто раньше так не делал. Я не хочу сказать что они всё сделали правильно. Ни под каким видом она не совершенна. У меня есть несколько придирок к тому как всё собрано вместе. Но дело не в совершенстве. Дело в том, что Rails позволяет работать очень быстро, при том что есть глубина которая помогает вам двигаться вперёд. И у Rails это очень хорошо получается.

Может быть сложно поверить в то, что это возможно без какого-то значительного недостатка. К счастью, вам не придётся верить мне на слово (также как кому-либо ещё). Вы можете легко доказать себе за день или меньше просто пройдя через учебник по Ruby on Rails и тут же разработав скромное приложение на свой выбор. В конце концов, лучше один раз увидеть, чем сто раз услышать. Если вы не хотите смотреть на себя сверх продуктивного, вы всегда можете посмотреть на кого-то ещё, кто за вас делает всё это в новом Rails видео.

Как Rails это делает?

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

Большая часть мощи Rails кроется в языке программирования Ruby. Уникальный дизайн Ruby делает легким создание языков для разных предметных областей и метапрограммирование. Rails пользуется этим на полную катушку.

Полная реализация MVC

Rails это MVC (модель, вид, представление) фреймворк, она предоставляет компоненты для каждого уровня которые безупречно работают друг с другом. Другие фреймворки часто реализуют только часть решения, обязывая разработчика интегрировать несколько различных фреймворк в приложение, а затем заставить их работать вместе. (К примеру, Java разработчик может использовать Hibernate, Struts и Tiles для полной поддержки MVC.)

Соглашение вместо конфигурации

Соглашение вместо конфигурации означает конец подробным файлам конфигурации на XML - в Rails нет ни одного! Вместо трудоёмкого XML, приложение на Rails использует несколько простых программерских соглашений которые позволяют узнать всё через рефлекцию и обнаружение. Например, Rails использует разумную рефлекцию для привязки таблиц базы данных к объектам Ruby. Код вашего приложения и работающая база данных уже содержат всё, что Rails нужно было знать.

Меньше кода

Следование простым программным соглашениям Rails не только устраняет необходимость в конфигурационных файлах. Оно также означает что Rails может автоматически брать на себя мириады низко-уровневых деталей, без необходимости вам говорить ей об этом. Это значит, что вам приходится писать меньше строк кода чтобы реализовать своё приложение. А чем меньше кода, тем быстрее идёт разработка и тем меньше багов, что делает код легким для понимания, поддержки и расширения.

Генераторы

То как Rails использует динамическую рефлекцию и метапрограммирование устраняет большую часть типового кода который вам в противном случае пришлось бы писать. Но часто, можно избежать написания и оставшейся его части используя встроенные скрипты-генераторы. Это даёт вам больше времени чтобы сконцентрироваться на коде который действительно важен - вашей бизнес-логике.

Быстрая отдача

Типичный цикл разработки для тестирования изменений в веб приложении состоит из конфигурирования, компилирования, выкладывания на сервер, сброса и тестирования. Это занимает очень много времени. Среда разработки Rails не имеет ничего подобного. Вы просто вносите изменения и видите как они работают. Не делайте ошибку, списывая это со счетов как не важный момент. Сложно переоценить влияние этого факта на продуктивность и творческий процесс, ведь вам не приходится прерываться и ждать.

Скаффолдинг (Scaffolding - строительные леса, подмости. Прим. пер.)

Rails может автоматически создать полный набор CRUD (Create, Retrieve, Update, and Delete) операций и представления для любой таблицы базы данных. Эта функциональность называется скаффолдингом и помогает вам быстрее начать манипулировать своими таблицами. Со временем, вы можете постепенно заменить сгенерированные операции и представление своими собственными - которые, разумеется, будут намного красивее и функциональнее.

Компоненты Rails

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

* Active Record это слой объектно-реляционного отображения (ORM) который связывает бизнес объекты (модели) с таблицами базы данных. Это реализация паттерна активная запись описанного Мартином Фаулером.
* Action Pack это компонент который реализует два слоя архитектуры MVC: контроллер и представление. Контроллер управляет входящими запросами от браузера пользователя и отправляет их к соответствующему методу класса-контроллера. Представление строит ответ браузеру используя шаблонную систему на подобии ASP или JSP.
* Prototype это компонент который реализует Ajax, drag’n’drop и визуальные эффекты на ваших страницах.
* Action Mailer это тот компонент который отвечает за отправку и получение электронной почты.
* Action Web Service позволит вам легко добавить API веб службы к своему приложению. Action Web Service поддерживает SOAP, XML-RPC и WSDL.

* Active Record is the object-relational mapping (ORM) layer that connects business objects (models) to database tables. It is an implementation of the Active Record pattern described by Martin Fowler.
* Action Pack is the component that implements both the view and controller portions of the MVC architecture. The controller part handles incoming requests from the user’s browser and routes them to the correct method of a controller class. The view part builds the response to send back to the browser using a templating system similar to that of ASP or JSP.
* Prototype is the component that implements the Ajax, drag-and-drop, and visual effects within your web pages.
* Action Mailer is the component that handles the sending and receiving of email.
* Action Web Service is the component that makes it easy to add web service APIs to your web application. Action Web Service supports SOAP, XML-RPC, and WSDL.

Основные возможности

У Rails есть некоторые основные и специфичные характеристики.

Веб серверы

Rails можно запустить практически на любом веб сервере который поддерживает CGI. Однако, производительность CGI никуда не годится, поэтому предпочитаемый способ развёртывания это использование FastCGI. Довольно хорошо протестирован способ развёртывания Rails приложений на Apache и LightTPD. Кстати, недавно появился новичок, SCGI, который предоставляет производительность FastCGI без сложностей его установки.

Во время разработки, чаще всего самым простым способом является использование WEBrick - веб сервера который поставляется вместе с Ruby.

Базы данных

На данный момент Rails поддерживает следующие СУБД:

* MySQL
* PostgreSQL
* SQLite
* SQL Server
* DB2
* Oracle

Сам адаптер базы данных состоит из примерно 100 строк Ruby кода, поэтому расширить этот лист ещё одним элементом не составит большого труда.

Отладка

Когда что-нибудь в вашем Rails приложении идёт не так как надо, обычно вы получите довольно детальное сообщение об ошибки в вашем браузере (если вы работаете в режиме разработки). Часто, этого достаточно чтобы обнаружить проблему. Если нет, то у вас есть следующие варианты отладки:

* Вставить отладочный вывод в контроллер. Например:

render_text «Дошёл до сюда»

render_text «объект user = » + user_obj

* Проверить логи Rails. (Используйте tail на *nix системах.) Посмотрите на файлы development.log, production.log и fastcgi.crash.log. Помните, что ваш веб сервер тоже ведёт логи.
* Использовать брейкпоинты.
* Использовать коммерческую среду разработки (такую как ArachnoRuby) со встроенным отладчиком.

Настраиваемые (красивые) URL

То, как Rails по умолчанию привязывает URL к действиям контроллера очень просто понять. Rails очень старается чтобы пользователь видел только «красивые» URL адреса. URL в Rails простые и понятные, а не длинные и зашифрованные.

Несмотря на это, вы всё равно можете настроить адреса URL используя систему роутинга Rails. URL роутинг в Rails достаточно гибок для того, чтобы позволить вам создать практически любую схему привязки URL.

Система роутинга Rails это чистый Ruby код который позволяет вам использовать даже регулярные выражения. Поскольку Rails не использует возможности веб сервера при привязке URL (например mod_rewrite в Apache), ваша схема привязки URL будет работать одинаково на любом веб сервере.

Модульное тестирование

Rails активно навязывает (в хорошем смысле, прим. пер.) разработчику модульное тестирование:

* Генерация новых контроллеров, моделей и скаффолдига, также создаёт соответствующие скелеты модульных тестов.
* Чёткое следование архитектуре MVC как результат приводит к хорошо тестируемым действиям и компонентам.
* Rails включает в себя Rake (Ruby Make) скрипт, который может автоматически запускать все ваши модульные тесты.

Детали процесса подробно описаны в Руководстве о тестировании в Rails.

Active Record

Active Record это часть Rails которая отвечает за автоматическую динамическую привязку таблиц вашей базы данных к объектам моделей. Это буква M в MVC, и это реализация слоя ORM в Rails.

Для самых распространённых случаев использования (и не таких уж распространённых), вам никогда не придётся видеть или писать SQL код для доступа к или обновления вашей базы. Цель Active Record - работать исключительно с реляционными базами данных; она не пытается абстрагироваться от использования SQL. Когда надо, Active Record облегчает использование ваших собственных SQL запросов, для тех сложных случаев где это необходимо. Но даже в таких случаях, часто можно обойтись без написания SQL кода вручную.

Автоматическая привязка

Active Record автоматически привязывает таблицы к классам, строки к объектам (экземплярам класса модели), и поля к аттрибутам объекта. Например код:

class Product < ActiveRecord::Base end

автоматически привязывается к таблице с именем products, такой как:

CREATE TABLE products (id int(11) NOT NULL auto_increment, name varchar(255), PRIMARY KEY (id));

а также автоматически создаёт аттрибут name который вы можете использовать так:

my_product = Product.find(:first) STDOUT.print my_product.name my_product.name = "Название нового продукта"

Active Record использует правила плюрализации английского языка для привязки классов к таблицам. Имя класса модели состоит в единственном числе и пишется с заглавной буквы, а имя таблицы в множественном и в нижнем регистре. Вот несколько примеров:

* Класс модели Invoice привязывается к таблице invoices.
* Класс модели Person привязывается к таблице people.
* Класс модели Country привязывается к таблице countries.
* Класс модели SecurityLevel привязывается к таблице security_levels.

Соглашение о единственных/множественных числах выливается в довольно натурально читаемый код. Заметьте как разумна привязка в своём использовании правил плюрализации английского. Также обратите внимание, что имена классов используют CamelCase (правило Ruby), в отличии от таблиц, имена которых все в нижнем регистре со знаками нижнего подчёркивания между словами.

В тех случаях когда это не срабатывает (например тогда, когда вам приходится работать с устаревшей базой данных, где вы не имеете контроля над именами таблиц), вы можете прямо указать Active Record какое имя следует использовать.

Документация класса ActiveRecord::Base описывает процесс автоматической привязки подробней.

Ассоциации

Таблицы не существуют в одиночестве. По крайней мере, обычно. Большинство приложений для баз данных используют несколько таблиц со своими отношениями между ними. Вы можете рассказать Active Record об этих отношениях в классах своих моделей, и Active Record сгенерирует целый набор методов для навигации по ассоциациям, которые помогут вам получить доступ к нужным данным. Следующий код модели:

class Firm < ActiveRecord::Base has_many:clients has_one:account belongs_to:conglomerate end

позволяет вам написать следующий код:

my_firm = Firm.find(:last) STDOUT.print my_firm.account.name STDOUT.print my_firm.conglomerate.employee_count for c in my_firm.clients STDOUT.print "Клиент: " + c.name + "n" end

Этот код будет работать корректно если в базе данных есть таблицы clients и accounts в каждой из которых есть поле name, и таблица conglomerates с полем employee_count.

Документация модуля ActiveRecord::Associations подробно объясняет все тонкости ассоциаций в Rails.

Валидация

Поскольку вы скорей всего не хотите хранить в своей базе что попало, вы скорей всего захотите проверить свои данные перед сохранением. Active Record содержит набор макро-подобных валидаторов которые вы можете добавить к своей модели.

class Account < ActiveRecord::Base validates_presence_of:subdomain, :name, :email_address, :password validates_uniqueness_of:subdomain validates_acceptance_of:terms_of_service, :on => :create validates_confirmation_of:password, :email_address, :on => :create end

Если встроенные макросы валидации не могут дать вам то, что нужно, вы всегдо можете написать свой метод для валидации.

class Person < ActiveRecord::Base protected def validate errors.add_on_empty %w(first_name last_name) errors.add("phone_number", "has invalid format") unless phone_number =~ /*/ end def validate_on_create # only runs the first time a new object is saved unless valid_discount?(membership_discount) errors.add("membership_discount", "has expired") end end def validate_on_update errors.add_to_base("Изменений не было") if unchanged_attributes? end end person = Person.new("first_name" => "David", "phone_number" => "what?") person.save # => false (and doesn"t do the save) person.errors.empty? # => false person.count # => 2 person.errors.on "last_name" # => "can"t be empty" person.errors.on "phone_number" # => "has invalid format" person.each_full { |msg| puts msg } # => "Last name can"t be emptyn" + "Phone number has invalid format" person.attributes = { "last_name" => "Heinemeier", "phone_number" => "555-555" } person.save # => true (и person сохраняется в базе данных)

Если метод validate существует, Rails вызовет его прямо перед записью любого объекта в базу данных. Если валидация провалилась, она не запишет объект в базу. Методы validate_on_create и validate_on_update похожи, за исключением того, что первый вызывается только тогда когда Rails создаёт в базе новую запись, тогда как последний вызывается только когда Rails собирается обновить существующую.

Документация модуля ActiveRecord::Validations подробно описывает все тонкости.

Обратные вызовы

Вы можете наблюдать за тем, как Active Record создаёт и удаляет объекты модели, создаёт и изменяет их в базе данных, используя методы обратных вызовов (callbacks). Вы можете использовать обратные вызовы для того, чтобы позаботиться о сложной бизнес логике, изменить данные перед тем как Rails запишет их в базу (или после того как Rails прочитает их из базы), или в любой другой момент который вам нужен.

К примеру, метод save который сохраняет данные объекта модели в базу данных, имеет восемь методов обратного вызова:

1. before_validation
2. before_validation_on_create
3. after_validation
4. after_validation_on_create
5. before_save
6. before_create
7. after_create
8. after_save

Это даёт вам полный контроль над объектами модели тогда, когда он вам нужен.

class CreditCard < ActiveRecord::Base # Выдрать всё, кроме цифр, так чтобы пользователь мог ввести "555 234 34" или # "5552-3434". Чтобы оба варианта значили "55523434" def before_validation_on_create self.number = number.gsub(/[^0-9]/, "") if attribute_present?("number") end end class Subscription < ActiveRecord::Base before_create:record_signup private def record_signup self.signed_up_on = Date.today end end class Firm < ActiveRecord::Base # Уничтожает ассоциированных клиентов и людей, когда уничтожается фирма before_destroy { |record| Person.destroy_all "firm_id = #{record.id}" } before_destroy { |record| Client.destroy_all "client_of = #{record.id}" } end

Документация модуля ActiveRecord::Callbacks подробно рассказывает о методах обратного вызова.

Транзакции

Транзакции необходимы если вы выполняете несколько операций над базой данных которые все должны пройти успешно перед тем как данные в базе изменятся. Если одна из них проваливается, данные не должны измениться. Используйте блоки транзакций чтобы включить этот режим.

Транзакции уровня базы данных, показанные выше, не допустят снятие денег со счёта David’а в случае если не получится зачислить эти деньги на счёт Mary. Однако, это не защитит объекты david и mary от изменения. Чтобы добиться этого, вам следует использовать транзакции уровня объектов:

Любой сбой в этом коде вернёт назад предыдущее состояние объектов, также как и базы данных.

Документация модуля ActiveRecords::Transactions объясняет подробнее.

И это далеко не всё

Active Record содержит в себе намного больше, чем я могу здесь описать. Чтобы узнать больше, загляните в Active Record API.

Action Pack реализует уровни контроллера и представления в Rails.

Шаблоны представления

Шаблоны представления формируют HTML который возвращается в ответе браузеру. Шаблоны являются файлами rhtml (HTML со встроенным Ruby) которые очень похожи на ASP или JSP файлы. Текст внутри <% %> это Ruby код который будет запущен, а текст внутри <%= %> это Ruby код который будет также запущен и результат запуска которого будет подставлен обратно в HTML.

Счета для <%= @name %> <% render_partial "invoices_by_customer" %>

По умолчанию, Rails попытается найти шаблон чьё имя совпадает с действием которое сейчас выполняется. Если например, Rails выполняет действие edit в вашем InvoiceController, тогда она попытается найти и вывести шаблон представления …/app/views/invoices/edit.rhtml.

Вы можете также конструировать XML (или HTML) вывод в действии вашего контроллера. Это полезно, к примеру, для построения RSS лент или ответа на XML-RPC запросы. В следующем примере, xm это экземпляр класса XmlMarkup.

xm.em("подчёркнутый") # => подчёркнутый xm.em { xmm.b("emp & bold") } # => emph & bold xm.a("A Link", "href"=>"http://onestepback.org") # => A Link xm.div { br } # =>


xm.target("name"=>"compile", "option"=>"fast") # => # ВНИМАНИЕ: порядок аттрибутов не сохраняется. xm.instruct! # xm.html { # xm.head { # xm.title("История") # История } # xm.body { # xm.comment! "HI" # xm.h1("Заголовок") #

Заголовок

xm.p("параграф") #

параграф

} # } #

Роутинг URL

Запрашиваемый URL всегда привязывается к какому-то действию внутри контроллера. Контроллер это простой класс Ruby и каждое действие реализованное контроллером это публичный метод этого класса. По умолчанию, URL привязан к действию по следующей схеме:

/:controller/:action/:id

Это легче всего объяснить на примере. Если Rails получает URL http://myapp.com/invoices/show/37, то она автоматически привяжет его к классу-контроллеру InvoicesController и к методу этого класса под именем show. Rails также передаст значение 37 в метод как часть хэша параметров под именем id. Хэш параметров содержит в себе значения полей запроса(взятых из URL) и данные элементов форм. Код может выглядеть следующим образом:

class InvoicesController def show @invoice = Invoice.find(params[:id]) end end

Поскольку действия это методы сгруппированные внутри контроллера (вместо отдельных командных объектов), они могут легко разделять между собой вспомогательные методы.

Если стандартный способ привязки URL вас не устраивает, вы можете с лёгкостью указать свои правила роутинга, даже используя регулярные выражения. Поскольку Rails реализует свой механизм URL роутинга, вам не надо связываться с Apache mod_rewrite и ваши правила роутинга будут работать одинаково на всех веб серверах.

Правила роутинга URL в Rails это простой Ruby код. Вот пример:

map.connect "date/:year/:month/:day", :controller => "blog", :action => "by_date", :month => nil, :day => nil, :requirements => {:year => /d{4}/, :day => /d{1,2}/, :month => /d{1,2}/}

С этим правилом роутинга становятся рабочими следующие адреса:

http://myblog.com/date/2005
http://myblog.com/date/2005/08
http://myblog.com/date/2005/08/01

Это правило разбивает URL содержащий дату, которую, блог может использовать для отображения постов за конкретное число. URL который совпадает с правилом будет привязан к классу BlogController и к методу by_date. Хэш параметров будет содержать значения для года из четырёх цифр(/d{4}/ это регулярное выражение Ruby) и месяц и день из двух. Также, месяц и день не обязательны; если значение не присутствует, в хэше параметров будет сохранено значение по умолчанию - nil.

Смотрите руководство по роутингу в Rails для подробного описания.

Фильтры позволяют вам выполнять предварительный код перед тем как Rails выполнит действие, а также после его выполнения. Это может быть полезно для таких вещей как кэширование или аутентификация перед вызовом действия, и компрессия или локализация ответа после его вызова. Фильтр before_filter может либо разрешить действию быть выполненным в нормальном режиме, возвратив true, либо отменить вызов вернув false (или выполнив операцию render или redirect).

Например:

class BankController < ActionController::Base before_filter:audit private def audit # записать действие и параметры в лог для аудита end end class VaultController < BankController before_filter:verify_credentials private def verify_credentials # убедиться что пользователь имеет доступ в хранилище end end

Остальные детали в документации класса ActionController::Filters.

Помошники (helpers)

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

Вы можете создавать своих собственных помошников, но как вы могли догадаться несколько помошников поставляется встроенными в Rails. Помошник link_to, например, генерирует тэги ссылок которые ссылаются на контроллеры и действия. Пример:

<%= link_to "Помощь", { :action => "help" } %>

<%= link_to "Содержание справки", { :controller => "help", :action => "index" } %>

<%= link_to "Удалить этот счёт", { :controller => "invoices", :action => "delete", :id => @invoice.id }, :confirm => "Вы действительно хотите это удалить?" %>

Это создаст ссылку на метод delete в классе InvoiceController, и передаст параметр id (в качестве указателя на то, какой счёт нужно удалить). Здесь также используется специальная опция confirm которая создаёт всплывающее окно подтверждения через JavaScript.

Существует большой набор помощников для создания форм просмотра и обновления значение объектов ваших ActiveRecord моделей, то есть — для значений в вашей базе данных. Предположим что в вашей базе данных есть таблица people со столбцами для имени, пароля, описания и булева значения определяющего женат человек или холост (ОК, довольно странная табличка вышла:). Вот часть шаблона с примером тэгов формы которые можно было бы использовать. (Допустим что переменная @person содержит объект класса Person, считанный из строки в таблице people.)

Имя: <%= text_field "person", "name", "size" => 20 %> Пароль: <%= password_field "person", "password", "maxsize" => 20 %> Холост?: <%= check_box "person", "single" %> Описание: <%= text_area "person", "description", "cols" => 20 %>

Данный код генерирует следующий HTML ответ:

Имя: Пароль: Холост?: Описание:

Есть помощники для создания тэгов option для списков select из набора строк считанных из базы данных; помощники для работы с датами, числами и валютой; и много других.

* Active Record Helpers
* Asset Tag Helpers
* Benchmark Helpers
* Cache Helpers
* Capture Helpers
* Date Helpers
* Debug Helpers
* Form Helpers
* Form Options Helpers
* Form Tag Helpers
* JavaScript Helpers
* Number Helpers
* Pagination Helpers
* Tag Helpers
* Text Helpers
* Upload Progress Helpers
* URL Helpers

AJAX и JavaScript помощники

Rails включает в себя JavaScript библиотеку Prototype для реализации своей поддержки AJAX, визуальных эффектов и drag-n-drop возможностей.

Модель того, как Rails реализует AJAX операции проста и надёжна. Как только браузер обработал и отобразил первоначальную страницу, различные действия пользователя могут вызвать либо отображение новой страницы (как в традиционных веб-приложениях) либо инициировать AJAX действие:

1. Срабатывает триггер. Это может быть кликом пользователя на кнопку или ссылку, изменение данных в форме или поле, или просто временный триггер (на основе таймера).
2. Клиент асинхронно отсылает данные ассоциированные с триггером (поле или целую форму) к действию-обработчику на стороне сервера через XMLHttpRequest.
3. На стороне сервера действие-обработчик выполняет какие-то действия над данными и возвращает HTML фрагмент в качестве ответа.
4. JavaScript на стороне клиента (код генерируется Rails автоматически) принимает этот HTML фрагмент и использует его для обновления конкретной части HTML текущей страницы, часто фрагмент подставляется содержимым в тэг

.

Вся прелесть в том, как просто Rails позволяет реализовать всё это в вашем веб-приложении. Следующий простой пример добавляет новые элементы в список:

Демонстрация списка с AJAX <%= javascript_include_tag "prototype" %>

Добавить к списку с помощью AJAX

<%= form_remote_tag(:update => "my_list", :url => { :action => :add_item }, :position => "top") %> Текст нового элемента: <%= text_field_tag:newitem %> <%= submit_tag "Добавить элемент через AJAX" %> <%= end_form_tag %>
  • Начальный элемент... добавьте ещё!

Статья AJAX on Rails и API JavaScript помощников рассказывают о поддержке AJAX в Rails более подробно.

Библиотека Prototype также предоставляет Rails разработчику целый набор визуальных эффектов на стороне браузера. Script.aculo.us содержит документацию и живую демонстрацию эффектов Prototype. Prototype также позволяет легко добавить к своему приложению drag-and-drop функциональность, об этом также можно узнать на сайте script.aculo.us.

Макеты (Layouts)

Макеты позволюят вам указать набор основных элементов для отображения на каждой странице выдаваемой контроллером. Это обычно полезно для вывода общей шапки, низа и боковых панелей. По умолчанию, Rails смотрит в свой каталог layouts в поисках rhtml файла чьё имя совпадает с именем контроллера. Шаблон макета может выглядеть вот так:

<%= @page_title %>

Шапка для этого макета
<%= @content_for_layout %>
Низ этого макета

Rails подставит HTML который сгенерируется действием в этот макет, в то место где написано @content_for_layout.

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

Чтобы узнать о макетах больше, смотрите документацию ActionController::Layout.

Partials и компоненты

Компоненты и partials (части, отрывки. прим.пер.) позволяют вам разделить ваши шаблоны представления на модули.

Проще всего использовать partials, которые позволяют вам выделить общую часть шаблона в отдельный файл и затем отображать его из множества других шаблонов (или много раз в одном шаблоне).
Шаблоны partials всегда имеют знак нижнего подчёркивания (_) перед названием их файла, чтобы было легче отлечить их от полных шаблонов.

Типичный пример использования partials это отображение массива (или другой коллекции) элементов.

<% for ad in @advertisements %> <%= render:partial => "adview", :locals => { :item => ad } %> <% end %>

Это отобразит шаблон partial _adview.rhtml несколько раз (по разу на каждый элемент массива @advertisments). Для каждого отображения, Rails будет передавать в _adview.rhtml локальную переменную с именем item которая содержит объект ad.

Документация ActionView::Partials содержит подробную информацию. На Pointstorm есть более детальная презентация partials, но она несколько устарела, поскольку использует устаревший синтаксис вызова partials.

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

<%= render_component:controller => "calendar", :action => "today" %>

Загляните в раздел Компоненты руководства по Rails если хотите узнать больше.
Скаффолдинг (scaffolding)

Скаффолдинг позволяет вам получить быструю реализацию CRUD (Create, Retrieve, Update, and Delete) операций для любой таблицы базы данных. Они не очень красивы, но позволяют получить немедленный доступ через веб-интерфейс к вашим таблицам. С течением времени, вы можете постепенно заменить сгенерированные операции и шаблоны на свои.

Rails поддерживает статический и динамический скаффолдинг. Статический физически генерирует модель, контроллер и файлы шаблонов. Это позволяет вам увидеть как всё работает и начать улучшать и изменять существующий код. Для генерации статического скаффолдинга, зайдите через файловую систему в главный каталог вашего Rails приложения и выполните команду на подобии этой:

$ ruby script/generate scaffold invoices

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

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

Динамический скаффолдинг не генерирует никаких файлов. Rails просто создаёт то, что ей нужно на лету во время работы приложения. Это значит, что каждый раз когда вы меняете схему таблицы, скаффолдинг автоматически отражает эти изменения. Чтобы включить динамический скаффолдинг поместите единственную строчку кода в контроллер:

class AccountController < ActionController::Base scaffold:account end

И много всего другого

Также как и в Active Record, в Action Pack очень много вещей о которых я не могу здесь рассказать. Если хотите узнать больше, посмотрите на Action Pack API.

Action Mailer это простая технология для отправки и приёма email в вашем веб-приложении. Вот метод для отправки email с вложением:

# отправляем email с вложением def signup_notification(recipient) recipients recipient.email_address_with_name subject "Информация о новом аккаунте" from "[email protected]" attachment:content_type => "image/jpeg", :body => File.read("an-image.jpg") attachment "application/pdf" do |a| a.body = generate_your_pdf_here() end end

Узнать больше можно в Action Mailer API и главе 19 книги Agile Web Development with Rails.

Action Web Service

Action Web Service реализует серверную поддержку для протоколов веб-служб SOAP и XML-RPC, позволяет просто создавать свои API и публиковать их через WSDL.

Вот часть MetaWeblog API реализованного Typo (open source блог система написанная на Rails):

class MetaWeblogApi < ActionWebService::API::Base api_method:getRecentPosts, :expects => [ {:blogid => :string}, {:username => :string}, {:password => :string}, {:numberOfPosts => :int} ], :returns => [] api_method:deletePost, :expects => [ {:appkey => :string}, {:postid => :string}, {:username => :string}, {:password => :string}, {:publish => :int} ], :returns => [:bool] end class MetaWeblogService < TypoWebService web_service_api MetaWeblogApi def getRecentPosts(blogid, username, password, numberOfPosts) articles = Article.find_all(nil, "created_at DESC", numberOfPosts) articles.to_a.collect{ |c| article_dto_from(c) } end def deletePost(appkey, postid, username, password, publish) article = Article.find(postid) article.destroy true end end

Этот отрывок показывает только два из семи методов API определённых Typo в этом классе.

Если хотите узнать больше, прочтите руководство по Action Web Service

Мысли о разделении

Обычно можно разделить фреймворки для создания веб-приложения и разработчиков которые их используют на две отдельных категории. В одном конце спектра находятся фреймворки-тяжеловесы для "серъёзных" программистов, на другой — лёгкие, простые для использования фреймфорки для любителей "поиграть." Каждая из этих групп чаще всего относится друг к другу без всякого уважения.

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

Последние ~14 рабочих часов провёл исключительно на Ruby on Rails, программируя простенький проект “Ы”, так сказать, такую рамку небольшую. Всё причём идёт под…

Ruby  - динамический, рефлективный, интерпретируемый высокоуровневый язык программирования для быстрого и удобного объектно-ориентированного программирования.

Ruby on Rails  - полноценный, многоуровневый фреймворк для построения веб-приложений, использующих базы данных, который основан на архитектуре Модель-Представление-Контроллер (Model-View-Controller, MVC).

Разработчики

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

Основные преимущества Ruby / Ruby on Rails

Скорость разработки

Основным преимуществом языка программирования Ruby и фреймворка Ruby on Rails считается скорость разработки. Практика показывает, что скорость разработки проектов на RoR увеличивается на 30–40 процентов по отношению к любому другому языку программирования или фреймворку. В первую очередь прирост скорости разработки определяется обширным набором готовых к работе штатных инструментов RoR, колоссальным набором готовых решений в сообществе, языку Ruby и простоте программирования на нем.

Одной из важнейших частей культуры RoR является социальность. Решил проблему, - помоги решить другим. Реализовал свой модуль, - поделись с сообществом. Таким образом, на данный момент в открытом доступе хранятся тысячи готовых решений тех или иных задач. Системы аутентификации, авторизации, комментирования, системы платежей, почтовые рассылки и многое другое (все то, что обычно разрабатывается «с нуля») внедряются реализованные кем–то другим, протестированные и рекомендованные многочисленным сообществом.

Культура и стандарты

Ruby on Rails - это фреймворк. Зачастую фреймворк не позволяет вам самодеятельность. Конечно же, в Ruby on Rails можно «изобрести свой велосипед» и программировать в любых направлениях, не опираясь на стандарты; но зачастую этого не требуется. Стандарты размещения файлов в проекте, стандарты написания кода в проекте, общие правила программирования в Ruby on Rails сильно структурируют любой проект. За счет этого проект становится читаемым. Вхождение в проект новичков происходит очень быстро. Опыт показывает, что любой новичок в проекте в первый же день работы делает свои первые полезные правки. За счет этого не считается большой проблемой, если разработку проекта изначально вела одна команда программистов, а поддержку проекта или доработку - совершенно другая. Проект на RoR априори понятен любому разработчику.

Некоторые приятные инструменты разработки

Тестирование

При разработке любого крупного проекта встает резонный вопрос. Как и кто будет тестировать проект? Не всегда есть средства и желание создавать целые отделы тестирования, к тому же хочется автоматизировать этот процесс. В отличие от других фреймворков, в составе RoR есть отличные средства автоматизированного тестирования. В других языках программирования и фреймворках штатных средств тестирования нет. Конечно, есть сторонние разработки, позволяющие организовать автоматическое тестирование проекта на PHP, но они не ставятся “из коробки” и об их использовании программисты чаще не задумываются. В проекте на Ruby on Rails, в идеале, код проекта не пишется до тех пор, пока под этот код не написаны тесты. RoR идеология предполагает изначальное использование методов BDD (Behavior Driven Development) или TDD (Test Driven Development).

Кеширование

Кеширование проектов - один из важнейших этапов разработки крупного интернет–проекта. В PHP имеются различные варианты кеширования данных. Эти варианты и инструменты прикручиваются, пристраиваются, приделываются, прикрепляются сбоку. До сих пор в сообществе PHP нет единого мнения: что лучше использовать, как лучше кешировать данные, какими инструментами пользоваться.

Ruby on Rails в его базовой комплектации имеет штатные средства кеширования данных. На старте предоставляются инструменты, позволяющие реализовать кеширование данных на проекте. Вы можете кешировать целые страницы или же блоки кода. Можете кешировать результаты запросов и ActiveRecord–модели. Кешировать можно как при помощи memcached или redis, так и другими средствами. Для реализации кеширования на Ruby on Rails проекте вам в 95 процентах случаев не потребуется ничего кроме уже готовых и штатных решений.

Локализация

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

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

Роутинг (красивые урлы или ЧПУ)

Зачастую во многих PHP проектах мы можем видеть картину, когда адрес определенной страницы огромен и непонятен. В Ruby on Rails есть штатная возможность гибко настроить ваш роутинг, вид адресов, названия основных разделов. Есть возможность быстро изменить адреса в одном месте без необходимости изменения этого адреса во всем проекте. В сообществе RoR–разработчиков активно используются идеология REST. Адреса страниц в проектах на Ruby on Rails всегда понятны, красивы, прекрасно понимаются поисковиками, просты.

Валидации

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

Миграции и работа с базой данных

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

Безопасность

Ruby on Rails по умолчанию сильно заточены под безопасность проекта. При использовании инструментов RoR исключены SQL инъекции и XSS атаки. Все входные параметры экранируется по умолчанию. Выводимые переменные в шаблонах также экранируются, только если вы не указали обратной опции. У разработчика нет шансов допустить ошибки безопасности (не без исключений, разумеется).

Деплой

В среде Ruby on Rails существует много удобных и приятных инструментов. В том числе инструменты, которые применяются в процессе деплоя. Например, используя Capistrano, выкатка новой версии приложения на боевой сервер (или несколько серверов) потребует одной команды в консоли: cap deploy.

Дополнительные принципы разработки на Ruby / Ruby On Rails

Системы контроля версий

При разработке любого Ruby on Rails проекта подразумевается использование известных систем контроля версий. Использование git, как говорится, «добровольно–принудительно», так как многие системы автоматического развертывания проекта на «боевых» серверах не работают без них. Программисты на RoR изначально, при изучении платформы, вынуждены осваивать git, так как многочисленные примеры кода в документации подразумевают использования данных систем контроля версий. Во многом из за этого неопытным новичкам проще начать изучать PHP и не трогать Rails до достижения определенного уровня понимания веб–разработки как таковой и ее принципов.

Системы управления проектами/таск менеджеры

Ruby on Rails был изначально разработан для того, чтобы реализовать систему управления проектом - Basecamp. Также на RoR был создан Redmine (популярная и бесплатная система управления проектом). Поэтому при работе над Rails проектами «добровольно–принудительно» использование таких систем. Все системы интегрируются с системами контроля версий, что позволяет более гибко регулировать процессы разработки проекта.

Мифы и предрассудки

Разработчиков на Ruby on Rails нет

Начнем с того, что разработчики есть, но они менее многочисленны, нежели разработчики на PHP. Это связано с разным порогом входа в освоение технологии (обычно в Ruby попадают люди после нескольких лет PHP), что говорит о качестве разработчиков. Хороших разработчиков одинаково мало во всех технологиях.

Разработчики на Ruby on Rails стоят очень дорого

Разработчики высокого уровня стоят действительно дорого. Причем они одинаково дорого стоят на любых языках программирования и платформах. В RoR мало дешевых разработчиков из–за отсутствия плохих разработчиков в сообществе (не без исключений, разумеется).

«Рельсы» не масштабируются

Это самое главное заблуждение тех людей, которые не пробовали писать на RoR серьезных проектов. Ruby on Rails прекрасно масштабируются. Посмотрите на GitHub, Groupon, Basecamp и др. Все эти проекты написаны на Rails и все эти проекты имеют любые другие проблемы, но только не проблемы масштабирования (чаще всего проблемы с производительностью баз данных).

Ruby медленнее чем PHP

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

При этом у вас есть возможность пользоваться главным преимуществом RoR - скоростью разработки проектов и низкой стоимостью их поддержки. В данный момент стоимость разработчиков на порядок дороже стоимости лишней планки памяти в сервер. В любом случае, проблемы производительности любого проекта, - это не проблемы неверного выбора платформы или языка программирования. Скорее всего, это проблемы изначально ошибочной архитектуры проекта, кеширования данных или оптимизации БД.

Несколько цитат известных в Ruby-сообществе людей

« Ruby on Rails  - это прорыв в снижении входного барьера в программировании. Мощные веб–приложения, которые раньше разрабатывались за недели или месяцы, теперь могут быть сделаны за считанные дни».

« Ruby on Rails и PHP  - это как Apple Macintosh и PC. Нас мало, но мы элита. Ruby on Rails и PHP - это культура против хаоса. PHP позволяет вам построить свой велосипед из частей других велосипедов, не ориентируясь при этом ни на какую «велосипедную библию». RoR–разработчики более продвинуты, чем любой школьник, которому достаточно прочитать одну книжку и говорить, что он знает PHP. Наш плюс в том, что при всем бардаке PHP, мы более организованны».

«Мой опыт показывает, что в программах, написанных на Ruby, меньше строк, чем в аналогичных программах на языках Java и C#. А чем меньше кода, тем проще его сопровождать, что немаловажно, так как затраты на долгосрочное сопровождение считаются самой крупной стоимостной составляющей успешных программных проектов. Отладка небольших программ занимает меньше времени даже без “навороченных” инструментов отладки».

«Почему опытные разработчики корпоративных приложений вроде меня влюбляются в Ruby и Rails? Для удовлетворения предъявленных требований сложность решений, создаваемых с применением технологий Java и Microsoft, просто неприемлема. Излишняя сложность не позволяет отдельному человеку понять проект в целом и сильно усложняет коммуникацию внутри команды. Из–за упора на следование паттернам проектирования и зацикленности на производительности на этих платформах пропадает удовольствие от работы над приложением».

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

« Ruby  - красивый язык. Кодировать на Ruby приятно. Все мои знакомые, перешедшие на Ruby и Rails, говорят, что стали счастливее. Главным образом, по этой причине Ruby и Rails изменяют статус кво, особенно в области разработки корпоративных приложений. Прежде чем стать приверженцем Rails, я привык работать над проектом с нечеткими требованиями, не имеющими отношения к реальным потребностям. Я устал выбирать между конкурирующими платформами и интегрировать их между собой, устал писать уродливый код. А Ruby - динамический, высокоуровневый язык. Код на Ruby проще читать и писать, поскольку он более естественно отображается на конкретную предметную область и по стилю ближе к естественному человеческому языку. Удобство восприятия имеет массу преимуществ не только в краткосрочной, но и в долгосрочной перспективе, поскольку программа передается в промышленную эксплуатацию и должна быть понятна программистам сопровождения».

« В сообществе Rails нет места принуждению. David Heinemeier Hansson выбрал язык, который доставлял ему радость. Платформа Rails родилась из кода, который представлялся ему красивым. Это и задало тон общения в сообществе Rails. Все в мире Rails субъективно. Человек либо приемлет что–то, либо нет. Но между теми, кто приемлет, и теми, кто не приемлет, нет злобы, а лишь кроткая попытка убедить».

«В начале своей карьеры веб–разработчика, я долго программировал на PHP. Как и любой программист, я дошел до того, что стал писать собственную CMS. Меня постоянно не устраивали те средства, которые предоставляет мне PHP и я придумал свой собственный небольшой фреймворк. В собственном фреймворке я реализовал все так, как мне было удобно. Какого же было мое удивление, когда я увидел Rails. Я понял, что Ruby on Rails очень похож на мой фреймворк, следовательно, в нем реализовали и допилили все то, чего мне так не хватало в PHP. Прибавим к этому огромное сообщество, которое постоянно обновляет рельсы - получаем инструмент, в котором просто удобно и хорошо делать любые веб–проекты. Свой фреймворк я бросил и с радостью перешел на RoR. Считаю, что Ruby on Rails делает программиста счастливее».

Гэри Гэри Полличе (Gary Pollice)
Опубликовано 27.05.2008

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

В поисках большей отдачи на единицу трудовых затрат

С тех пор, как программисты начали создавать программы, они не перестают думать о том, как вложить больше потребительской ценности в программы при тех же трудовых затратах. В последние пятьдесят лет появилось немало теорий о том, как этого добиться. Мы, безусловно, стали свидетелями эволюции языков программирования высокого уровня. Но постепенное совершенствование высокоуровневых языков вряд ли заставит нас подпрыгнуть на стуле, хлопнуть себя по лбу и воскликнуть "ну надо же!" Даже динамичные языки программирования, которые в 90-е годы были отнесены к категории "языков сверхвысокого уровня" (Very High Level Language, VHLL), не смогли предложить тех преимуществ, которые большинство из нас хотели бы получить и которые необходимы для обеспечения соответствия все возрастающим требованиям к программному обеспечению.

Мы предлагали идеи по поводу того, как повысить производительность труда программиста при помощи многократно используемых инфраструктур, перекрестных технологий, например, аспектно-ориентированного программирования, компонентной разработки, сервис-ориентированных архитектур, архитектуры, управляемой моделями, и многое другое. Все это давало определенный прирост производительности при условии правильного применения. Хотя мы до сих пор не создали технологии,которая позволила бы создавать программы без участия программиста (а именно об этом мечтают некоторые специалисты), мы сделали большой шаг вперед в направлении повышения производительности труда программистов. Тем не менее, мы все еще не получили 10-100 кратного повышения производительности, о котором мы мечтаем.

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

Что такое Rails?

Rails - это инфраструктура, построенная на базе языка программирования Ruby и предназначенная для разработки, обслуживания и развертывания Web-приложений. С некоторыми допущениями инфраструктуру можно определить как генератор приложений или полуфабрикат приложения, который можно приспособить для различных целей (использования в различных предметных областях). Вот и все! Rails представляет собой расширение общего назначения для языка Ruby. Эта инфраструктура разработана для конкретной предметной области - Web-разработки. Rails строится на нескольких базовых принципах, которые значительно облегчают некоторые обычные задачи и делают возможным выполнение тех задач, которые недостижимы обычными средствами. Rails щедро вознаграждает программистов за соблюдение соглашений, принятых проектировщиками этой инфраструктуры, тем, что генерирует большую часть типичного Web-приложения, требуя очень небольшого объема программирования. Вы можете удивить своих коллег и руководителей, создавая мастерски сделанные Web-приложения, даже если вы всего лишь новичок в сфере Web-технологий.

Rails, в некоторых статьях называемый также "Ruby on Rails" - детище Дэвида Хейнемейера Ханссона (David Heinemeier Hansson), разработчика Web-приложений из Дании, использующего в работе язык программирования Ruby. Он заметил, что в процессе создания приложений ему приходится выполнять много общих задач. Как многие хорошие разработчики, он приступил к поиску способов автоматизации этой работы. Результатом этих поисков стала инфраструктура Rails. Hansson создал Rails на основе приложения под названием Basecamp. Фактически, Rails был извлечен из Basecamp и подвергнут генерализации путем выделения общих моментов и инкапсуляции изменчивости. Именно этот принцип мы обычно используем для создания языков, специфичных для различных предметных областей.

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

Простой пример

Вероятно, каждая статья или книга о Rails начинается простым примером. Я не стану приводить такой пример и подробно его описывать, просто продемонстрирую вам особенно яркие моменты примера из самой популярной книги по Rails, Agile Development with Rails (Динамичная разработка при помощи Rails), авторы Томас (Thomas) и Ханссон (Hansson). Этот пример представляет собой основу сайта интернет-магазина. Продукты, которые мы хотим продавать, имеют наименование, описание, изображение и цену. После того, как я потратил полчаса на чтение и изучение текста, я нашел в приложении точку, в которой можно добавлять продукты в базу данных, изменять информацию о них и удалять их. Это приложение использует обычную архитектуру Model-View-Controller (Модель-представление-контроллер), а Rails облегчает сохранение разделения ответственностей, поскольку эта инфраструктура автоматически генерирует корректные исходные файлы в отдельных каталогах, что делает очевидным их назначение.

Тело окончательной Web-страницы, которую я создал, показано на рисунке 1. В моем каталоге на данный момент только два продукта, но на этой странице мы можем увидеть некоторые моменты. Если продукт имеет изображение типа моей схемы механизма по наклейке этикеток, оно отображается на странице. Отображается первая часть описания продукта вместе с разметкой HTML. Рядом с каждым продуктом имеются три ссылки, чтобы можно было увидеть, как выглядит продукт, когда мы отображаем его, редактируем элемент или удаляем его. Кроме того, имеется ссылка на страницу создания нового продукта. Мы явно не готовы предъявить эту Web-страницу миру, но зато можем приступить к работе с заинтересованными лицами, которые предъявляют требования к нашему приложению. Это позволяет нам использовать итеративный подход к получению определенных требований, их реализации, анализу работы и внесению изменений перед следующей итерацией.

Рисунок 1. Страница управления каталогом продукции

Внешняя отделка моей Web-страницы вряд ли может кого-либо удивить, но то, что мне пришлось сделать к этому моменту, отличается поразительно малым объемом. Я измеряю объем работы количеством команд, которые мне пришлось ввести с терминала, количеством строк кода на языке Ruby, HTML и встроенного Ruby (ERb), которое мне пришлось написать. Я немного сократил работу, скопировав файл CCS (Cascading Style Sheets, каскадная таблица стилей) из загружаемых файлов к книге Томаса и Ханссона, поэтому в своей оценке трудовых затрат эти строки я не учитываю. В таблице 1 представлены результаты моих подсчетов.

Таблица 1. Трудовые затраты на управление каталогом продукции

Цифры в таблице 1 были округлены, поскольку я немного экспериментировал с кодом. Но если бы я даже написал в два раза больше строк кода на языке Ruby, общее количество строк, введенных мной в редакторе или строк команд в оболочке терминала было бы гораздо меньше 100. Вы можете спросить, а что я на самом деле получил, написав несколько десятков строк программного кода? Вот список:

Кроме того, я обнаружил еще более восхитительные моменты, которыми мне не пришлось заниматься:

  • Я не написал ни одной строки кода SQL, тем не менее мое приложение оснащено реляционной базой данных;
  • Мне нужно было всего лишь написать метод проверки корректности, чтобы гарантировать корректное указание цены;
  • Мне не пришлось писать специальный код для обновления кода моего приложения при изменении схемы базы данных.

Я не являюсь разработчиком Web-приложений. (Я не слишком преуспел в изучении технологий, поскольку уделял больше внимания другим аспектам разработки программного обеспечения. В одно и то же время можно сделать лишь определенный объем вещей из всех доступных.) Но, имея явно недостаточные знания языков Ruby и HTML, я произвел хорошее впечатление на своих студентов, демонстрируя свои познания в области Web-разработки.

Принципы Rails

Каким образом Rails обеспечивает описанный объем функциональности при столь небольших требованиях к трудовым затратам разработчика? Один из принципов многократного использования заключается в том, что существует обратно пропорциональная зависимость между универсальностью приложения и многократностью его использования. Если вы хотите, чтобы ваш компонент или система лучше поддерживали многократное использование - то есть, имели бы больше элементов многократного использования - то вам придется сузить предметную область, в которой они применяются. Это первое, что мне пришло в голову при работе с Rails. Rails - это не обычная инфраструктура, которая позволяет вам создавать Web-приложения любым способом; скорее, он предназначен для поддержки конкретного принципа разработки Web-приложений. Если вы будете выполнять рекомендации, то сможете добиться потрясающей многократности использования. Но если вы отойдете от заданного направления, то многократность использования заметно понизится.

Model-View-Controller (Модель-представление-контроллер)

Разработчикам программного обеспечения хорошо известна архитектура Model-View-Controller (Модель-представление-контроль). Эта архитектура лежала в основе ранних систем графического интерфейса пользователя (GUI) типа интерфейса среды Smalltalk-80. Концепция не отличается сложностью: система делится на три разных части (см. рисунок 2).

Рисунок 2. Архитектура Model-View-Controller

Архитектура MVC делит сферы ответственности в приложении на три разных части. Модель отвечает за обслуживание состояния приложения. Оно не только извлекает и хранит данные, но также гарантирует их целостность. Бизнес-логика, которая должна применяться к этим данным, инкапсулирована в модель. Представление отвечает за отображение модели для пользователя в одном или нескольких форматах. Это позволяет отображать модель различными способами, в зависимости от потребностей пользователя. Контроллер отвечает за обеспечение того, чтобы другие компоненты осуществляли нужные действия в нужное время. Он получает запросы от пользователя и распределяет их по соответствующим компонентам. MVC - надежная, эффективная архитектура для многих типов приложений, в том числе, для клиент-серверных Web-приложений.

Соблюдая соглашения Rails, вы получите превосходное разделение вопросов по этим трем компонентам. На рисунке 3 показан фрагмент макета моего простого приложения. Мы видим, что это приложение имеет отдельные каталоги для всех компонентов, и еще один для всех вспомогательных объектов, необходимых для их поддержки.

Рисунок 3. Фрагмент структуры приложения

На данный момент разработки у нас всего один контроллер, контроллер admin. Rails получает информацию о том, какой контроллер необходимо вызвать, из текущего URL в адресной строке браузера. В данном случае, это указывается в URL после адреса Web-cервера. Тестируя приложение, я указываю в адресной строке браузера URL http://localhost:3000/admin , после чего localhost:3000 подключается к используемому мной серверу -- в данном случае, к серверу по умолчанию WEBrick, который поставляется с Rails. Контроллер приложений Rails направляет запрос классу AdminController. Если вам интересно содержимое этого класса, можете изучить файл в архиве, прилагаемом к данной статье. Вы сможете сопоставить большую часть методов этого класса со ссылками на Web-странице, показанной на рисунке 1. Большая часть реальной работы сделана классом ApplicationController, который расширяет класс AdminController. Не беспокойтесь, если вы не понимаете всех деталей. Файл, содержащий определение класса AdminController, admin_controller.rb - это один из самых больших файлов в приложении, и я не написал ни одной строки в этом файле. Он был полностью сгенерирован Rails по одной моей команде.

Представлением Web-приложения являются Web-страницы, которые отображаются перед пользователем. Rails генерирует для вас большую часть Web-страниц, но вы все же должны иметь базовые знания HTML и обладать достаточными навыками программирования на языке Ruby, чтобы написать несколько строк ERb. В представлении в Rails нет ничего уникального. Просто для каждого действия мы должны создать файл.rhtml (Ruby HTML).

К этому моменту модель моего приложения достаточно проста, в базе данных имеется только одна таблица для продуктов, а продукт имеет четыре свойства, о которых я уже говорил ранее. Я решил сделать URL изображения необязательным свойством, поэтому для него не предусмотрена проверка корректности. Для всех остальных полей производится проверка корректности. Ниже представлен полный текст файла product.rb. Правда, он не слишком велик?

class Product < ActiveRecord::Base validates_presence_of:title, :description validates_numericality_of:price validates_uniqueness_of:title, :message => "We already have that in our catalog" protected def validate errors.add(:price, "must be worth something") if price.nil? || price < 0.01 end end

Первые три метода validates_ methods являются встроенными методами Rails, при этом метод проверки корректности автоматически вызывается для любого продукта, поступающего в систему. Я добавил проверку, чтобы гарантировать, что цена любого продукта будет не менее 0,01 доллара.

Возможно, вы поинтересуетесь, как была создана таблица для записи продуктов, если я не написал ни строки SQL? В Rails есть достаточно волшебный компонент, который называется Active Record. Active Record представляет собой объектно-реляционное отображение (object-relational mapping, ORM), использующее стандартную ORM-модель. В своей основе он представляет собой абстрактную реализацию шаблона проекта ActiveRecord. То есть, таблицы отображаются в классы, объекты отображаются в строки, а свойства объектов отображаются в столбцы. Active Record, как и Rails в целом, использует стандартный способ управления отображением. Он не поддерживает полной универсальности без определенной дополнительной работы. Однако если вы намерены использовать его стандартные возможности по умолчанию, то вам придется сделать совсем немного. Следующий код представляет содержимое файла, который создает таблицу:

class CreateProducts < ActiveRecord::Migration def self.up create_table:products do |t| t.column:title, :string t.column:description, :text t.column:image_url, :string end end def self.down drop_table:products end end

Все, что я написал в этом коде - это три строки t.column.... . Они определяют свойства наименование, описание и URL изображения. Чтобы получить готовую и настроенную базу данных, я выполнил следующие действия:

  1. В командной строке я ввел команду:

    Mysqladmin -u root create depot_development

    В результате этой команды была создана база данных для моей разработки;

  2. Я перешел в корневой каталог приложения и ввел следующую команду:

    Ruby script/generate model product

    В базе данных была создана таблица PRODUCT. Кроме того, было создано несколько файлов, в том числе, файл 001_create_products.rb в каталоге db/migrate приложения. Именно этот файл был показан в предыдущем листинге;

  3. Я отредактировал файл, добавив в него три определения для столбцов;
  4. Я ввел команду:

    Rake db:migrate

    В таблице PRODUCT были созданы столбцы. Команда rake - это аналог команды make, который используется в Rails.

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

На этом мы закончим изучение архитектуры MVC, основы приложения Rails, и перейдем к другим принципам.

Соглашение по поводу конфигурации

Я уже продемонстрировал этот принцип в действии. Приложение Rails довольно жестко соблюдает некоторые соглашения. Одни соглашения представляют собой обычные соглашения о назначении имен, а другие больше относятся к архитектуре приложения. Rails имеет весьма четкий взгляд на построение Web-приложения, он использует умолчания, основанные на этой модели. Допущение умолчаний позволяет сгенерировать гораздо большую часть приложения, чем это было бы возможно для инфраструктуры в противном случае. Это также избавляет разработчика от необходимости длительной настройки конфигурации сред для разработки, тестирования и развертывания. Существует два конфигурационных файла, которые можно изменять, если нужно добавить MIME-типы или другую информацию, которая не вписывается в обычные сценарии применения. Один из файлов, который, вероятно, придется редактировать, это файл database.yml, описывающий основные параметры для сред разработки, тестирования и развертывания. Когда я создавал приложение, этот файл был сгенерирован со значениями по умолчанию, как показано в следующем листинге.

# MySQL (установки по умолчанию). Рекомендуется использовать версии 4.1 и 5.0. # # Установка драйвера MySQL: # gem install mysql # На MacOS X: # gem install mysql -- --include=/usr/local/lib # На Windows: # gem install mysql # Выберите сборку win32. # Установите MySQL и поместите сборку в каталог /bin, указанный в переменной path. # # Убедитесь, что вы мспользуете новый стиль хэширования пароля: # http://dev.mysql.com/doc/refman/5.0/en/old-client.html development: adapter: mysql database: depot_development username: root password: host: localhost # Внимание: База данных, определенная как "test", будет стерта и #сгенерированна повторно из вашей разработанной базы данных, когда вы запустите "rake". # Не присваивайте этой БД того же имени, которое было при разработке # или при реальной эксплуатации. test: adapter: mysql database: depot_test username: root password: host: localhost production: adapter: mysql database: depot_production username: root password: host: localhost

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

Принцип DRY

Последний принцип, который используется в приложениях Rails - это принцип DRY (Don"t Repeat Yourself, не повторяйся). Хорошие проектировщики и программисты используют этот принцип на практике. Они знают, что если что-то делается один раз, в одном месте, то проекты становятся более простыми, а работа гораздо более управляемой.

Способ организации и генерации приложений в Rails с соблюдением принципа DRY не представляет сложности, если соблюдать соглашения. Если вы научитесь ориентироваться в базовом коде для одного из приложений Rails, то можно считать, что вы сумеете разобраться в любом приложении Rails, в котором соблюдаются соглашения. Ничто не повторяется. Все находится в одном месте и все имеет смысл.

Но будет ли приложение масштабируемым?

Когда я встречал что-либо, кажущееся столь же простым, как Rails, я удивлялся, если оно могло работать в реальной сильно загруженной рабочей среде. Я видел слишком много инструментов, которые обещали значительный прирост производительности. Они хорошо показывали себя на "игрушечных" проектах, но терпели полный крах при первых же попытках применить их для решения реальных проблем. Я знаю довольно много историй успеха, связанных с Rails, но настоящая уверенность пришла ко мне в прошлом году, когда мы успешно применили Rails в нашем институте.

Один из моих коллег по Вустерскому политехническому институту (Worcester Polytechnic Institute) занимался разработкой интеллектуальной обучающей системы под названием Assistments, которая должна была помочь преподавателям и студентам различных курсов в изучении и преподавании различных предметов. Так же, как во многих штатах, учащиеся начальной и средней школы нашего штата в процессе обучения должны сдать серию стандартизированных тестов, что, в конечном итоге, необходимо для получения документа об образовании. Эти тесты, так называемые тесты MCAS , предлагаются на каждой ступени обучения, чтобы можно было оценить уровень подготовки учащихся по основным учебным дисциплинам. Обучающая система Assistments показала свою эффективность в помощи учащимся в получении необходимых знаний и навыков. В прошлом году система Assistment использовалась небольшой группой студентов в Вустере, штат Массачусетс, но группе моего коллеги, которая занималась Assistments, скоро пришлось готовиться к более масштабному развертыванию.

Assistments представляет собой типичное клиент-серверное Web-приложение. Оно не только помогает учителям и студентам себя использовать, но также поддерживает исследователей в разработке новых обучающих методик и предоставлении функций оценки. В прошлом году система Assistments насчитывала больше 50 000 строк программного кода, главным образом, на языке Java. Код включал множество пакетов и классов, которые были разработаны за несколько лет аспирантами и студентами. К сожалению, группе разработчиков не доставало последовательности, поэтому код превратился в крайне неуправляемый - то есть, с каждым днем становился все более хрупким. Что могла предпринять группа для обеспечения качества, необходимого для крупномасштабного развертывания?

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

Третий вариант мы получили благодаря одному из аспирантов, принимавших участие в работе над Assistments - он предложил переписать систему при помощи Rails. Можно себе представить, какое раздражение вызвало это предложение у его товарищей и профессора, курировавшего группу. Студент потратил несколько недель на разработку главного приложения, которое содержало большую часть функций системы Assistments. Для этого ему пришлось написать тысячу строк программного кода.

Ему удалось убедить всех. Группа утвердила процесс разработки и приступила к работе. Новая система имеет все функции старой системы и несколько новых, в том числе, улучшенный пользовательский интерфейс. Согласно последней полученной мной информации, группе пришлось написать и обслужить меньше 5 000 строк кода. Это означает более чем 10-кратное повышение производительности, при этом количество дефектов, обнаруженных в системе, меньше, чем средний показатель.

Да, Rails - это не игрушка.

Вместо заключения

Идея автоматической генерации программ не нова. Однако в последние годы мы значительно усовершенствовали эту технологию. Rails - это одна из очень эффективных инфраструктур для создания определенного вида программ понятным, непротиворечивым способом с минимальными трудовыми затратами. Можно ожидать появления систем, подобных Rails, для других предметных областей. Это совсем неплохо в экономическом смысле. Фактически, в сфере создания Web-приложений существует еще два явления. Это две похожих на Rails инфраструктуры, написанные на языке PHP. Они называются Symfony и CakePHP. Недавно появилось еще одно интересное явление в этой области, это Project Zero, инкубаторный проект IBM. Project Zero не является генератором приложений, но он предоставляет соглашения и структуру, напоминающую Rails

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

Примечания

1 На этом пути вам могут помочь многочисленные учебные руководства. Некоторые из них перечислены в разделе Ресурсы в конце этой статьи. Изучите учебное руководство, и вы удивитесь, насколько просто можно создать Web-приложение.

2 Первая бета-версия Rails была выпущена в июле 2004 года. Rails 1.0 увидела свет в декабре 2005 года. В примерах, приведенных в данной статье, используется версия 1.2.2.

10 Massachusetts Comprehensive Assessment System (Комплексная обучающая система Массачусетского университета) См.