
Вагон-ресторан
БОРИС ВОЛЬФСОН
BORISVOLFSON@GMAIL.COM
HTTP://SPLENDOT.COM
РАССКАЗ О НАБИРАЮЩЕМ ПОПУЛЯРНОСТЬ ВЕБ-ФРЕЙМВОРКЕ RUBY ON RAILS
«СТРЕЛОЙ ГОРЯЩИЙ ПОЕЗД РЕЖЕТ ТЕМНОТУ…», РАНО ИЛИ ПОЗДНО С ГОЛОВОЙ НАКРЫВАЮЩЕЙ ЛЮБОГО ВЕБ-РАЗРАБОТЧИКА, КОТОРОМУ ДОЛГИМИ МЕСЯЦАМИ ПРИХОДИТСЯ КОРПЕТЬ НАД БОЛЬШИМИ ПРОЕКТАМИ. ОН УЖЕ НЕНАВИДИТ БАЗЫ ДАННЫХ, ЯЗЫК РАЗМЕТКИ И ЯЗЫК ПРОГРАММИРОВАНИЯ, НА КОТОРОМ ВЕДЕТСЯ ПРОЕКТ. НО К ТЕБЕ НА ПОМОЩЬ СПЕШИТ ПОИСТИНЕ РЕВОЛЮЦИОННЫЙ ФРЕЙМВОРК (КАРКАС) ДЛЯ РАЗРАБОТКИ ВЕБ-ПРИЛОЖЕНИЙ – RUBY ON RAILS
Японский язык.
Ты хотел когда-нибудь выучить японский язык? Мне это удалось, причем я не потратил на это много времени – таким языком для меня стал Ruby. Юкихиро Мацумото (Matz) разработал язык программирования, который назвал Ruby, что в переводе с буржуйского означает «Рубин». Название указывает на Perl, который, как известно, «Жемчужина» языков программирования. Но японского «лингвиста» и фаната объектно-ориентированного программирования ни один из существовавших тогда языков не устроил, поэтому он решил создать свой. Подробности можно прочитать во врезке.
Раби встает на рельсы
Ruby on Rails – это объектно-ориентированный фреймворк для создания веб-приложений, который позволяет сократить время разработки в десятки раз! Звучит захватывающе, неправда ли? Чтобы понять, за счет чего производительность труда программиста так вырастает, надо начать с архитектуры этого каркаса, которая представляет собой реализацию паттерна программирования
MVC (Model – View – Controller, Модель – Представление – Контроллер). Также к плюсам «рельс» можно отнести их бесплатность и наличие исходных кодов в стандартной поставке.
Общие принципы
Достаточно написать два-три веб-приложения, и ты начинаешь понимать, что у них много общего. Эти общие части хотелось бы выделить во
фреймворк, что и сделали создатели RoR. Поэтому «рельсы» полностью определяют архитектуру приложения. Это достаточно удобно, так как вместо создания архитектуры программист пишет логику программы, которая, безусловно, важнее для конечного пользователя.
Метапрограммирование
Нравится мне приставка «мета», она придает словам эдакий загадочный смысл. Метапрограммирование – это создание программ, которые в качестве данных (как входных, так и выходных) используют программы и даже самих себя. В результате работы такого ПО на выходе может получиться другая программа. Аналогичный механизм, схожий с макросами,
Раби использует для связи классов и базы данных.
Соглашения вместо конфигурации
Это один из моих любимых принципов, так как он позволяет свести настройку приложения к минимуму (фактически надо только настроить подключение к базе данных). Проводить какие-либо конфигурационные работы требуется только в совершенно нестандартных случаях, с которыми тебе не придется столкнуться.
Привет, мир!
Установку языка программирования и фреймворка я описывать не буду, потому что она представляет собой обычное «Далее… Далее… Готово» с минимальными усилиями. Лучше сразу взять и создать культовую программу.
Для этого в командной строке пишем (Пуск-> Выполнить-> cmd) “rails disks”, предварительно перейдя в папку, где будут храниться наши проекты. Оказывается, «рельсы» – это не только
фреймворк, но и набор полезных скриптов, так что после выполнения предыдущей команды у тебя появится папка с необходимой структурой. Зайдем в эту папку и все дальнейшие команды будем производить из нее. Больше всего нас будет интересовать подпапка app. Создадим контроллер для простейшего приложения, воспользовавшись скриптом: “ruby script\generate controller TestRuby”. Он создаст файл controllers\test_ruby_controller.rb. Теперь изменим его содержание на следующее:
«Привет, мир!» на Раби с RoR
class TestRubyController < ApplicationController
def index
render_text "Hello, world"
end
def another
render_text "Another page!"
end
end
Теперь нужно запустить веб-сервер. Проще всего использовать встроенный веб-сервер WEBrick (в народе «кирпич»): «ruby script\server». Теперь заходим по адресу http://127.0.0.1:3000/TestRuby и видим приветствие нашей программы, его же мы увидим, зайдя по адресу http://127.0.0.1:3000/TestRuby/index. Чтобы понять, как
RoR выбирает метод и класс для обработки того или иного адреса, зайдем на http://127.0.0.1:3000/TestRuby/another и припомним одни из основных принципов RoR: «никаких конфигураций, только соглашения».
База данных
Ладно, хватит уже играть в игрушки, давай будем использовать базу данных, хотя это тоже будет легко и приятно. Для начала в папке config подредактируем файл, который описывает различные режимы соединения с БД:
Конфигурирование подключения к базе данных
development:
- adapter: mysql
- database: disks
- username: root
password:
test:
- adapter: mysql
- database: disks
- username: root
password:
production:
- adapter: mysql
- database: disks
- username: root
password:
Саму базу желательно создать до описываемых действий. Имя пользователя root и пустой пароль нужно будет обязательно сменить. Саму задачу я выбрал простую: мы сделаем сайт, где будет храниться информация о CD-дисках, которые имеются у нас в наличии. Сначала сделаем таблицу для дисков:
Создание таблицы «Диски»
CREATE TABLE `disks` (
`id` tinyint(4) NOT NULL auto_increment,
`title` varchar(255) NOT NULL default '',
`description` text,
PRIMARY KEY (`id`)
) TYPE=MyISAM;
Я бы порекомендовал создавать таблицу и работать с базой при помощи визуального средства проектирования. Думаю, поля особых пояснений не требуют. Заметь, что к данному моменту мы не написали ни единой строчки кода. Теперь создадим модель и контроллер для нашей таблицы:
Создание модели и контроллера
ruby script\generate model Disk
ruby script\generate controller Disk
Далее я не буду упоминать, что необходимо создавать модели, контроллеры и представления, так как это будет ясно из контекста и по названию файлов и классов. У нас имеется модель, которая точно отражает то, что хранится в базе данных, и шаблон обработки пользовательских действий. Теперь подправим файл
controllers\disk_controller.rb:
Используем скаффолдинг
class DiskController < ApplicationController
scaffold: disk
end
Теперь можем идти по адресу http://127.0.0.1:3000/Disk/new, где увидим форму для заполнения данных о диске. После создания нескольких дисков можно посмотреть их список здесь: http://127.0.0.1:3000/Disk/list.
Вот так вот, всего одна строчка кода оживила нашу программу!
Шаблоны-представления
Не знаю, как читателям, а мне не очень нравится стандартный дизайн и нерусские слова, поэтому попробуем это исправить. Определим, какие данные должен получать шаблон:
Передаем в шаблон список дисков
class DiskController < ApplicationController
scaffold :disk
def list
@disks = Disk.find_all
end
end
Затем пишем сам шаблон, который больше похож на обычный HTML-файл:
Шаблон для списка дисков
<html>
<head>
<title>Список дисков</title>
</head>
<body>
<h1>Список дисков</h1>
<table border="1">
<tr>
<th>Название</th>
<th>Исполнитель</th>
<th>Дата выпуска</th>
</tr>
<% @disks.each do |disk| %>
<tr>
<td><%= link_to disk.title, :action => "show", :id => disk.id %></td>
<td><%= disk.artist %></td>
<td><%= disk.date %></td>
</tr>
<% end %>
</table>
<p><%= link_to "Внести новый альбом", :action => "new" %></p>
</body>
</html>
Для начала поясню конструкцию <% @disks.each do |disk| %> - это «встроенный» Раби-код, который перебирает все диски и присваивает поочередно все значения переменной disk, которая затем выводится на экран. И еще один краткий комментарий по поводу функции: link_to – это функция для создания ссылок. Если ты заметил, у меня появилось новое поле artist – исполнитель: я просто внес изменения в базу данных, а Раби сделал остальное!
Связь таблиц
Хотелось бы продемонстрировать, как RoR работает со связанными таблицами. Каждому альбому мы присвоим жанр:
Таблица для хранения жанров
CREATE TABLE `genres` (
`id` tinyint(4) NOT NULL auto_increment,
`title` varchar(255) NOT NULL default '',
PRIMARY KEY (`id`),
UNIQUE KEY `title` (`title`)
) TYPE=MyISAM;
Чтобы создать связь таблиц, нам надо поработать с моделями:
Файл disk.rb
class Disk < ActiveRecord::Base
belongs_to :genre
end
Файл genre.rb
class Genre < ActiveRecord::Base
has_many :disk
end
Таким простым способом мы выразили отношение один-ко-многим. Думаю, что запись может понять любой, кто владеет английским или является программистом.
Редактирование диска
Завершающим этапом будет создание формы для редактирования информации о диске. Хотелось бы видеть список жанров с возможностью выбора, для этого сначала правим контроллер:
Пересылка в шаблон дополнительных данных при редактировании
class DiskController < ApplicationController
scaffold :disk
def list
@disks = Disk.find_all
end
def edit
@disk = Disk.find(@params["id"])
@genres = Genre.find_all
end
end
Займемся самим шаблоном, который будет построен по тем же правилам, что и предыдущий:
Шаблон для редактирования диска
<html>
<head>
<title>Редактирование диска</title>
</head>
<body>
<h1>Редактирование диска</h1>
<form action="../update/<%= @disk.id %>" method="POST"">
<input id="disk_id" name="disk[id]" size="30" type="hidden" value="<%= @disk.id %>" />
<p><b>Название</b><br>
<input id="disk_title" name="disk[title]" size="30" type="text" value="<%= @disk.title %>" />
</p>
<p><b>Исполнитель</b><br>
<input id="disk_artist" name="disk[artist]" size="30" type="text" value="<%= @disk.artist %>" />
</p>
<p><b>Описание</b><br>
<textarea id="disk_description" name="disk[description]"><%= @disk.description %></textarea>
</p>
<p><b>Жанр:</b><br>
<select name="disk[genre_id]">
<% @genres.each do |genre| %>
<option value="<%= genre.id %>"
<%= ' selected' if genre.id == @disk.genre_id %>>
<%= genre.title %>
</option>
<% end %>
</select></p>
<input type="submit" value="Update" />
</form>
<a href="/disk/show/<%= @disk.id %>"> Show </a> | <a href="/disk/list">Back</a>
</body>
Все, основная часть работы завершена, перейдем к вольной программе. Я бы начал с нормализации нашей маленькой базы данных.
На закуску
Что стоит отметить? У меня на исполнение описанного выше приложения ушло около 30 минут. Это при том, что я постоянно делал скрины и конспектировал действия и результаты. Еще один плюс - мы не работали с SQL напрямую: я приводил код только для того, чтобы ты увидел структуру данных. Кода мы писали совсем мало, большая часть – это шаблоны, которые делаются один раз!
О продвинутых возможностях Ruby on Rails я постараюсь рассказать в следующих статьях, включая модные нынче Ajax-технологии.
ПЕРЕВОД ПИСЬМА МАЦА В СПИСОК РАССЫЛКИ RUBY-TALK. ПИСЬМО ДАТИРОВАНО 4 ИЮНЯ 1999 ГОДА
RUBY РОДИЛСЯ 23 ФЕВРАЛЯ 1993 ГОДА. В ТОТ ДЕНЬ Я БЕСЕДОВАЛ СО СВОИМ КОЛЛЕГОЙ О ВОЗМОЖНОСТИ СУЩЕСТВОВАНИЯ ОБЪЕКТНО-ОРИЕНТИРОВАННОГО СКРИПТОВОГО ЯЗЫКА. Я ЗНАЛ PERL (PERL4, А НЕ PERL5), НО ОН МНЕ НЕ НРАВИЛСЯ - БЫЛ В НЕМ НЕКИЙ ПРИВКУС ИГРУШЕЧНОГО ЯЗЫКА (ОН ЕСТЬ И ДО СИХ ПОР). А ОБЪЕКТНО-ОРИЕНТИРОВАННЫЙ ИНТЕРПРЕТИРУЕМЫЙ ЯЗЫК КАЗАЛСЯ МНОГООБЕЩАЮЩИМ. В ТО ВРЕМЯ Я ЗНАЛ PYTHON. НО ОН ТОЖЕ МЕНЯ НЕ УСТРАИВАЛ, ТАК КАК Я НЕ СЧИТАЛ ЕГО НАСТОЯЩИМ ОБЪЕКТНО-ОРИЕНТИРОВАННЫМ ЯЗЫКОМ. ЕГО OO-СВОЙСТВА КАЗАЛИСЬ НАДСТРОЙКОЙ НАД ЯЗЫКОМ. МНЕ, КАК ЯЗЫКОВОМУ МАНЬЯКУ И ФАНАТУ ОБЪЕКТНО-ОРИЕНТИРОВАННОГО ПРОГРАММИРОВАНИЯ С ПЯТНАДЦАТИЛЕТНИМ СТАЖЕМ, ОЧЕНЬ-ОЧЕНЬ ХОТЕЛОСЬ, ЧТОБЫ СУЩЕСТВОВАЛ ИСТИННО ОБЪЕКТНО-ОРИЕНТИРОВАННЫЙ, ПРОСТОЙ В ИСПОЛЬЗОВАНИИ ЯЗЫК. Я ПЫТАЛСЯ НАЙТИ ТАКОЙ ЯЗЫК, НО ЕГО НЕ БЫЛО. ТОГДА Я РЕШИЛ ЕГО СОЗДАТЬ. ПРОШЛО НЕСКОЛЬКО МЕСЯЦЕВ, ПРЕЖДЕ ЧЕМ ИНТЕРПРЕТАТОР ЗАРАБОТАЛ. Я ДОБАВИЛ В МОЙ ЯЗЫК ТО, ЧТО МНЕ ХОТЕЛОСЬ - ИТЕРАТОРЫ, ОБРАБОТКУ ИСКЛЮЧЕНИЙ, АВТОМАТИЧЕСКУЮ СБОРКУ МУСОРА. ЗАТЕМ Я РЕОРГАНИЗОВАЛ СВОЙСТВА PERL'А И РЕАЛИЗОВАЛ ИХ КАК БИБЛИОТЕКУ КЛАССОВ. В ДЕКАБРЕ 1995 ГОДА Я ОПУБЛИКОВАЛ RUBY 0.95 В ЯПОНСКИХ НОВОСТНЫХ ГРУППАХ. С ТЕХ ПОР ПОЯВИЛИСЬ САЙТЫ, СПИСКИ РАССЫЛОК. В СПИСКАХ РАССЫЛОК ПРОИСХОДЯТ ЖАРКИЕ ДИСКУССИИ. САМЫЙ СТАРЫЙ, RUBY-LIST, СЕЙЧАС СОДЕРЖИТ 14789 ПИСЕМ.
ПАТТЕРН ПРОГРАММИРОВАНИЯ MVC
ШАБЛОН ПРОЕКТИРОВАНИЯ MVC РАЗДЕЛЯЕТ ДАННЫЕ, ПРЕДСТАВЛЕНИЕ И ОБРАБОТКУ ДЕЙСТВИЙ ПОЛЬЗОВАТЕЛЯ НА ТРИ РАЗЛИЧНЫХ ЧАСТИ:
- МОДЕЛЬ ПРЕДОСТАВЛЯЕТ ДАННЫЕ И ИЗМЕНЯЕТ СВОЕ СОСТОЯНИЕ;
- ОТВЕЧАЕТ ЗА ОТОБРАЖЕНИЕ ИНФОРМАЦИИ;
- ПОЛУЧАЕТ СОБЫТИЯ ОТ ПОЛЬЗОВАТЕЛЯ И ИНТЕРПРЕТИРУЕТ ИХ, ИЗВЕЩАЯ МОДЕЛЬ О НЕОБХОДИМОСТИ ДЕЙСТВИЙ.
ГЛАВНЫМ ПЛЮСОМ ТАКОГО РАЗДЕЛЕНИЯ ЯВЛЯЕТСЯ ТО, ЧТО МОДЕЛЬ НЕ ЗАВИСИТ НИ ОТ ПРЕДСТАВЛЕНИЯ, НИ ОТ КОНТРОЛЛЕРА И ПОЭТОМУ ЕЕ МОЖНО ИЗМЕНЯТЬ НЕЗАВИСИМО ОТ НИХ.
РЕАЛИЗАЦИЯ MVC В RUBY ON RAILS
ТИП: Текст с названиями, можно разбить на три врезки и раскидать по тексту.
[модель] – это сердце всего приложения, она предоставляет остальным компонентам доступ к данным в объектно-ориентированной форме. Она также осуществляет манипуляцию с данными в БД и реализует логику работы приложения. В RoR для автоматической работы с базами данных достаточно создать наследника от класса ActiveRecord::Base, а все необходимые атрибуты создаст за вас среда.
[представление] реализует интерфейс пользователя, отображая данные, полученные от контроллера, и передает контроллеры запросы пользователя. В Ruby on Rails представление реализуется при помощи шаблонов RHTML, которые представляют собой обычные HTML-файлы с примесью Раби.
[контроллер] отвечает за взаимодействие с пользователем. Контроллеры реализуются как классы-наследники от ActionController::Base и тесно связаны с адресом, на который зашел пользователь. Например, при переходе на страницу “book/list”, будет вызван метод list класса BookController, а в качестве шаблона выступит представление list.rhtml из соответствующий папки.
ДЕРЕВО ПАПОК ROR
CONTROLLERS – МЕСТО ХРАНЕНИЕ КОНТРОЛЛЕРОВ
VIEWS – ПАПКА ДЛЯ ШАБЛОНОВ-ПРЕДСТАВЛЕНИЙ
MODELS – ПАПКА ДЛЯ ХРАНЕНИЯ МОДЕЛЕЙ
HELPERS – ПАПКА ДЛЯ ВСПОМОГАТЕЛЬНЫХ КЛАССОВ
www.ruby-lang.org/ - сайт языка Раби
http://www.rubyonrails.org/ - родной сайт Ruby on Rails – здесь есть все: от файлов для скачивания до презентаций
http://www.rubyonrails.ru/ - русский сайт «рельсов», пока еще не такой большой, как его заокеанский сородич
http://sabanin.ru/ - блог человека, действительно очень увлеченного Раби. На сайте есть уникальные переводные материалы
http://ru.wikibooks.org/wiki/Ruby - вики-учебник по Раби
http://rubyforge.org/ - хранилище проектов, написанных на Раби
ПРИНЦИП DRY (DON’T REPEAT YOURSELF – НЕ ПОВТОРЯЙСЯ!) ПОЗВОЛЯЕТ ИЗБЕЖАТЬ ДУБЛИРОВАНИЯ
WEBRICK – ВСТРОЕННЫЙ СЕРВЕР RUBY, ХОТЬ ОН И МЕДЛЕННЫЙ, ЗАТО СТАНДАРТНЫЙ И ВСЕГДА ЕСТЬ
RUBY МОЖЕТ РАБОТАТЬ ЧЕРЕЗ APACHE, ДЛЯ ЭТОГО НЕОБХОДИМО УСТАНОВИТЬ MOD_RUBY
Содержание Вперед на стр. 073-060-2
|