Изучаем Ruby on Rails
Суть Ruby on Rails хорошо отражена фразой, которая бросается в глаза на домашней Web-странице проекта. Этот девиз показан на рисунке 6.
Рисунок 6. Девиз Rails
"Web-разработка без проблем" – это первый девиз. Есть еще и другой – "не повторяться". Среда Ruby on Rails предполагает следование определенным соглашениям, а разработчик может сконцентрироваться на действительно важных вещах, не "изобретая велосипед" каждый раз при написании нового приложения.
Например, каждое Rails-приложение организовано строгим образом: конфигурация, таблицы стилей, код JavaScript – каждый компонент хранится в определенном месте. Такого рода соглашения придают стиль, ускоряют дизайн, разработку и развертывание приложений и способствуют повторному использованию готового кода.
Более того, все приложения Ruby on Rails имеют в основе проверенную временем парадигму "модель-представление-поведение" (MVC).
Принцип "модель-представление-поведение"
Как было уже упомянуто, желательно отделять логику от представления. Также лучше не смешивать логику и сложный пользовательский интерфейс. На таких фундаментальных разделениях и основан принцип "модель-представление-поведение".
Модель
"Модель" включает в себя данные. Например, модель сотрудника Superheroes, Inc. включала бы в себя имя, город, сверхъестественные способности и другие свойства, такие как дата появления супергероя. Помимо этого, модель может содержать код, порождающий дополнительные характеристики, что похоже на случай, когда некий объект в объектно-ориентированном языке предоставляет открытые методы, оперирующие скрытыми свойствами и реализующие свойства, производные от базовых.
Представление
"Представление" отображает информацию. Как и механизм шаблонов, оно извлекает структуры данных и организует информацию на экране понятным образом, в том числе заведует элементами интерфейса, с помощью которых пользователь может работать с данными. В случае с супергероями приложение должно, например, отображать сведения о сотрудниках и содержать средства для добавления, редактирования и удаления данных.
Поведение
Наконец, "поведение" заведует входными и выходными данными. Оно интерпретирует входные данные, поступающие от Web-форм и других элементов ввода, изменяет модель в соответствии с бизнес-логикой, а затем готовит выходные данные для отображения.
Распределение обязанностей
Распределение обязанностей между моделью, представлением и поведением упрощает задачу и наводит порядок. Разработчики иногда усложняют этот принцип, а именно:
- Каждая модель описывает единственную сущность
- Каждое представление обслуживает единственную задачу
- Каждое поведение реализует только один процесс
Обладатели iPhone уже смогли прочувствовать такой вариант этого принципа – на нем основан интерфейс этого популярного гаджета.
Реализация приложения Superheroes на Ruby on Rails
А теперь напишем заново приложение для работы с реестром супергероев, но теперь на Ruby on Rails. Для удобства и простоты в Rails есть собственный Web-сервер WEBrick. (Когда ваше приложение будет готово обслуживать реальных клиентов по всему миру, вы сможете заменить WEBrick на более мощный lighttpd).
Установка Ruby и Rails
Сервер баз данных у нас уже есть, поэтому требуется установить Ruby и Rails. Последняя версия Ruby, совместимая с Rails, – 1.8.6, а самая новая версия Rails – 2.1.0. Как и раньше, Aptitude загрузит и установит необходимые пакеты:
$ sudo apt-get install ruby rubygems rails
$ sudo gem install rails --include-dependencies
|
Первая команда устанавливает сам язык Ruby, менеджер Ruby-пакетов RubyGems и набор инструментов Rails. Gem похож на Aptitude, только работает с библиотеками и модулями Ruby. Во второй команде gem устанавливает библиотеки Rails со всем необходимым.
Начальная подготовка приложения
После установки Rails можно приступать к написанию программы. Убедитесь, что вы не являетесь пользователем root, и перейдите в домашний каталог. Начальная подготовка вашего приложения делается при помощи утилиты rails. От вас требуется только указать имя приложения (в нашем случае – superheroes) в параметре, а утилита сделает все автоматически, как показано в листинге 8.
Листинг 8. Начальная подготовка приложения утилитой rails
$ cd
$ rails superheroes
create
create app/controllers
create app/helpers
create app/models
create app/views/layouts
create config/environments
create config/initializers
create db
create doc
create lib
create lib/tasks
create log
create public/images
create public/javascripts
create public/stylesheets
create script/performance
create script/process
create test/fixtures
create test/functional
create test/integration
create test/mocks/development
create test/mocks/test
create test/unit
create vendor
create vendor/plugins
create tmp/sessions
create tmp/sockets
create tmp/cache
create tmp/pids
create Rakefile
create README
create app/controllers/application.rb
create app/helpers/application_helper.rb
create test/test_helper.rb
create config/database.yml
create config/routes.rb
create public/.htaccess
create config/initializers/inflections.rb
create config/initializers/mime_types.rb
create config/boot.rb
create config/environment.rb
create config/environments/production.rb
create config/environments/development.rb
create config/environments/test.rb
create script/about
create script/console
create script/destroy
create script/generate
create script/performance/benchmarker
create script/performance/profiler
create script/performance/request
create script/process/reaper
create script/process/spawner
create script/process/inspector
create script/runner
create script/server
create script/plugin
create public/dispatch.rb
create public/dispatch.cgi
create public/dispatch.fcgi
create public/404.html
create public/422.html
create public/500.html
create public/index.html
create public/favicon.ico
create public/robots.txt
create public/images/rails.png
create public/javascripts/prototype.js
create public/javascripts/effects.js
create public/javascripts/dragdrop.js
create public/javascripts/controls.js
create public/javascripts/application.js
create doc/README_FOR_APP
create log/server.log
create log/production.log
create log/development.log
create log/test.log
|
Утилита rails создает все каталоги и файлы, необходимые для наполнения и сборки вашего приложения – файловое дерево приложения имеет строго определенную структуру.
Создание базы данных
Далее, нам понадобится отдельная база данных. База superheroes уже существует, поэтому назовем новую базу данных superheroes_development. Это еще одно соглашение Ruby – добавлять к имени приложения суффикс "_development." (Если вы вдруг забыли нужные суффиксы, откройте файл db/database.yml и взгляните на имена баз данных.) Для создания базы данных прямо из командной строки воспользуйтесь утилитой mysqladmin:
$ sudo mysqladmin -uroot -p create superheroes_development
|
Настройка связи приложения с базой данных
Создав нужную базу данных, можно приступить к настройке связи Rails-приложения с базой данных. Перейдите в каталог superheroes, откройте в редакторе файл config/databases.yaml и отредактируйте указанный фрагмент, как показано в листинге 9.
Листинг 9. Файл config/databases.yaml после редактирования
development:
adapter: mysql
encoding: utf8
database: superheroes_development
username: hero
password: shizzle
socket: /var/run/mysqld/mysqld.sock
|
Вам придется изменить только параметры username и password в секции development, так как остальные поля были заполнены автоматическими стандартными значениями при создании начальных файлов проекта. Сохраните изменения и закройте редактор.
Создание таблиц
На данный момент у нас есть доступ к базе данных, пусть и не содержащей никакой информации. Следующим шагом будет создание таблиц.
В отличие от PHP-программы, для которой нам пришлось создавать таблицы при помощи скрипта, здесь мы можем воспользоваться средствами Rails. При этом будет создана таблица сотрудников (т.е. модель) и несложный интерфейс для добавления, редактирования и удаления сведений о сотрудниках (т.е. представление и поведение). В Rails эта функция называется скаффолдинг (от англ. scaffold – подмостки, строительный лес). Скаффолдинг приходит на помощь, когда вы начинаете "возводить" какую-либо часть вашего приложения, и убирается, когда функциональность "построена".
Для создания скаффолдинга нужно придумать ему имя и передать список пар "поле-тип". Как и в случае с PHP, модель сотрудника содержит имя, название сверхъестественной способности, город и дату появления. Соответствующая команда приведена в листинге 10.
Листинг 10. Сценарий для создания таблицы сотрудников
$ ruby ./script/generate scaffold member name:string city:string initiated:date
exists app/models/
exists app/controllers/
exists app/helpers/
create app/views/members
exists app/views/layouts/
exists test/functional/
exists test/unit/
create app/views/members/index.html.erb
create app/views/members/show.html.erb
create app/views/members/new.html.erb
create app/views/members/edit.html.erb
create app/views/layouts/members.html.erb
create public/stylesheets/scaffold.css
dependency model
exists app/models/
exists test/unit/
exists test/fixtures/
create app/models/member.rb
create test/unit/member_test.rb
create test/fixtures/members.yml
create db/migrate
create db/migrate/001_create_members.rb
create app/controllers/members_controller.rb
create test/functional/members_controller_test.rb
create app/helpers/members_helper.rb
route map.resources :members
|
Организация принципа "модель-представление-поведение" в Rails
Просмотрев список файлов, созданных при скаффолдинге, можно понять, каким образом в Rails организован принцип "модель-представление-поведение".
В файле member.rb создана модель, которая называется Member. По соглашению, она связана с таблицей members. Чуть ниже есть строка о файле 001_create_members.rb, который был сгенерирован специально для создания этой таблицы. Файл представлен в листинге 11. В блоке create_table перечислены указанные нами поля.
Листинг 11. 001_create_members.rb
class CreateMembers < ActiveRecord::Migration
def self.up
create_table :members do |t|
t.string :name
t.string :city
t.date :initiated
t.timestamps
end
end
def self.down
drop_table :members
end
end
|
Скаффолдинг создал также шесть файлов, реализующих представление, включая простую типовую таблицу стилей для управления внешним видом страницы. Файл index.html.erb управляет отображением списка всех сотрудников, а файл show.html.erb – свойств отдельного сотрудника. В файле new.html.erb описана форма для создания новой записи, в файле edit.html.erb – другая форма для редактирования записи. Файл members.html.erb является оберткой, объединяющей указанные четыре страницы. На дальнейших этапах в него можно поместить верхний и нижний колонтитулы и другие общие элементы.
Управляющее поведение, т.е. все необходимое для обработки форм ввода, модификации модели и подготовки данных для отображения, сгенерировано в файле members_controller.rb.
Создание таблицы сотрудников
Осталось чуть-чуть. Вначале необходимо создать таблицу сотрудников. В Rails существует команда rake, аналог make, которая используется в том числе для управления базой данных. В частности, процесс миграции в терминах Rails означает изменение содержимого базы данных. Для получения нужной конфигурации базы данных команда rake может производить прямую и обратную миграцию. (Так как содержимое баз данных постоянно меняется в процессе разработки, миграция позволяет воссоздать базу данных в нужном состоянии). Для миграции на самую "свежую" версию базы данных запустите команду rake db:migrate, как показано в листинге 12.
Листинг 12. Использование rake db:migrate для миграции на последнюю версию базы данных
$ rake db:migrate
== 1 CreateMembers: migrating =================================================
-- create_table(:members)
-> 0.1660s
== 1 CreateMembers: migrated (0.1668s) ========================================
|
Вы можете не поверить, но наше приложение уже готово к запуску.
Запуск приложения
Находясь в каталоге superheroes, введите команду ruby script/server. Результат приведен в листинге 13.
Листинг 13. Запуск приложения командой ruby script/server
$ ruby script/server
=> Booting WEBrick...
=> Rails application started on http://127.0.0.1:3000
=> Ctrl-C to shutdown server; call with --help for options
[2008-07-06 01:47:11] INFO WEBrick 1.3.1
[2008-07-06 01:47:11] INFO ruby 1.8.6 (2007-09-24) [i486-linux]
[2008-07-06 01:47:11] INFO WEBrick::HTTPServer#start: pid=10298 port=3000
|
На рисунке 7 показана страница, которая появится после открытия в браузере адреса http://localhost:3000/members.
Рисунок 7. Страница с информацией о сотрудниках superheroes
Как и ожидалось, страница не содержит записей. А откуда им взяться, если их никто не добавлял? Сделаем это, щелкнув по кнопке New Member (новый сотрудник). Заполните форму данными о Человеке-пауке (как показано на рисунке 8) и нажмите Create (создать). Создайте еще несколько супергероев – элементы навигации вам в этом помогут.
Рисунок 8. Форма создания нового сотрудника
Недостатки скаффолдинга
Скаффолдинг дает хорошую отправную точку для разработки, однако у него есть и недостатки. Можно заметить, что меню выбора даты охватывает только 10 лет, хотя вам может понадобиться, например, 18 лет. Также спорно, нужен ли после добавления записи промежуточный этап – просмотр получившейся записи. Оба упомянутых недостатка легко исправляются редактированием "представления" и "поведения" сотрудника. В любом случае, Rails не изменяет своему девизу и упрощает Web-разработку, сочетая в себе принцип "модель-представление-поведение", скаффолдинг и специальные соглашения.
|