Создание модели и таблицы товаров
Вернемся к рис. 5.3, где схематически было изображено основное содержимое
таблицы товаров. Настало время воплотить эту схему в реальность. Нам нужно
создать таблицу базы данных и Rails-модель, позволяющую приложению использовать
эту таблицу.
Теперь нам нужно решить вопрос о том, как определить структуру таблицы.
Стоит ли для этого воспользоваться инструкциями низкоуровневого языка определения
данных (Data Definition Language, DDL), такими как create table и ей
подобные? Может быть, существует какой-нибудь высокоуровневый способ, облегчающий
в дальнейшем внесение изменений в схему данных? Конечно же, и не
один! Существует множество вариантов на выбор.
Для создания и корректировки схем многие предпочитают пользоваться инструментами,
работающими в диалоговом режиме. К примеру, такое средство,
как phpMyAdmin, позволяет обслуживать базу данных MySQL с использованием
веб-форм. Казалось бы, что может быть лучше — вводишь данные в форму,
и за тебя выполняется вся необходимая работа. Но за удобства приходится
платить: история вносимых изменений не сохраняется, и они становятся необратимыми.
Возникают трудности и с развертыванием приложения: следует помнить, что
одни и те же изменения нужно иметь и в разработочной, и в рабочей базе данных
(не секрет, что напортить чаще всего удается именно при внесении корректив
в рабочую схему).
К счастью, Rails предоставляет нам свою золотую середину: определение миграции
базы данных. Каждая миграция представляет те изменения базы, которые
вы собираетесь осуществить, выраженные в исходном файле в терминах, не связанных
с конкретной базой данных. Эти изменения могут обновлять как схему
базы данных, так и данные ее таблиц. Миграции используются не только для обновления
базы данных, но и для ее отката к прежнему состоянию. Миграциям посвящена
целая глава, поэтому сейчас мы будем лишь пользоваться ею, при этом
особо не вдаваясь в детали.
А как же создаются миграции? Пока вы обдумываете этот вопрос, мы по привычке
хотим создать таблицу базы данных одновременно с созданием модели,
в которой она представлена. Для этого в Rails есть изящный и весьма краткий
путь. Когда вы используете генератор для создания новой модели, Rails автоматически
создает миграцию, которую можно использовать для создания соответствующей
таблицы. (Далее мы увидим, что Rails также облегчает реализацию
самих миграций.)
Итак, продолжим и создадим модель и миграцию для нашей таблицы товаров.
Заметьте, что слово в приведенной ниже командной строке используется в форме
единственного числа — product. В Rails модель автоматически настраивается на
отображение таблицы базы данных, чье имя во множественной форме совпадает
с наименованием класса моделей. В данном случае нам требуется модель под
названием Product, поэтому Rails связывает ее с таблицей по имени products.
(А как же модель сможет найти эту таблицу? Мы указали ей место поиска, когда
определяли содержимое раздела development в config/database.yml.)
depot> ruby script/generate model product
exists app/models/
exists test/unit/
exists test/fixtures/
create app/models/product.rb
create test/uni t/product_test.rb
create test/fixtures/products.yml
create db/migrate
create db/mi grate/001_create_products.rb
Генератор создает целый набор файлов, но нас интересуют только два из них:
это файл модели product.rb и файл миграции 001_create_products.rb. Сначала рассмотрим
файл миграции.
Имя файла миграции состоит из префикса, представляющего собой очередной
номер (001), собственно имени (create_products) и расширения (.rb, поскольку это
Ruby-программа). Добавим к содержимому файла код, создающий таблицу в базе
данных. Перейдите в каталог db/migrate и откройте файл 001_create_products.rb. Вы
увидите два Ruby-метода.
class CreateProducts < ActiveRecord::Migration
def self.up
create_table :products do |t|
# t.column :name, :string
end
end
def self.down
drop_table :products
end
end
Метод up используется, когда миграция применяется к базе данных. Именно
в него и надо поместить код, определяющий структуру нашей таблицы. Метод
down нейтрализует действие метода up: он запускается, когда база данных возвращается
к предыдущей версии.
Вы можете убедиться в том, что Rails уже добавила код, который создает и уничтожает
таблицу с использованием этих двух методов. Теперь нам нужно сообщить
миграции о тех столбцах, которые мы хотим получить в таблице.
Отредактируйте файл так, чтобы он приобрел следующий вид:
Листинг файла db/migrate/001_create_products.rb
class CreateProducts < ActiveRecord::Migration
def self.up
create_table :products do |t|
t.column : t i t l e , :string
t.column rdescription, :text
t.column :image_url, :string
end
end
def self.down
drop_table :products
end
end
Содержимое файла очень похоже на недоработанный фрагмент DDL, который
мы могли бы напрямую применить к базе данных, но на самом деле это код Ruby.
Там, где можно было бы набрать create table в MySQL или Oracle, мы видим
create_ table в файле миграции. В методе up определяются три столбца для
таблицы products. Ну что, вы убедились в том, что Ruby действительно замечательный
язык?
А теперь мы заставим Rails применить данную миграцию к нашей базе данных,
предназначенной для разработки. Для этого используется команда rake. Эта
команда — надежный помощник, который всегда под рукой: вы приказываете ей
выполнить определенную задачу, и она ее исправно выполняет. В данном случае
мы приказали rake реализовать любую миграцию, которая еще не применялась
к нашей базе данных.
depot> rake db:migrate
(in /Users/dave/work/depot)
== CreateProducts: migrating ===================================
-- create_table(:products)
-> 0.0625s
== CreateProducts: migrated (0.0656s) ==========================
rake так и делает: она выискивает все ранее не применявшиеся к базе данных
миграции и приводит их в действие. В данном случае к базе данных, определенной
в разделе development: файла database.yml1, добавляется таблица products.
Как rake узнает, какую миграцию применять к базе данных, а какую нет? Взглянем
на нашу схему после применения миграции. В ней вы найдете таблицу под
названием schema_i nf о, которая используется для отслеживания номера версии