Ruby on Rails 3: Миграции в Rails 3.x
февраля 9, 2012 | Published in Ruby on Rails, Ruby on Rails 3 | 2 Comments
RubyDev — ваш друг в изучении Ruby и Rails!
Миграции — это очень удобный инструмент для управления структурой базы данных без использования SQL.
Как работают миграции?
Миграции — это обыкновенные классы, которые наследуются от ActiveRecord::Migration, описывают структуру базы данных и хранятся в директории db/migrate/ вашего проекта. При использовании генератора scaffold или генератора моделей автоматически будет создан и класс миграции для создания соответствующей модели таблицы.
$ rails g model Post title:string content:text
В результате помимо создания самой модели будет создан еще и файл миграции следующего содержимого:
#db/migrate/20120126202608_create_posts.rb
class CreatePosts < ActiveRecord::Migration
def change
create_table :posts do |t|
t.string :title
t.text :content
t.timestamps
end
end
end
В предыдущих версиях Rails использовались методы self.up и self.down для соответственно выполнения и отката миграции. В Rails 3.1, как показано выше используется один единственный метод change вместо self.up и self.down. Методы up и down также доступны, но в большинстве случаев достаточно метода change.
Для выполнения миграций необходимо выполнить команду:
$ rake db:migrate
Запуск этой команды выполнит все имеющиеся миграции, что ранее не были выполнены.
Структуру базы данных и последнюю выполненную миграцию можно увидеть в файле:
#/db/schema.rb
ActiveRecord::Schema.define(:version => 20120126202608) do
create_table "posts", :force => true do |t|
t.string "title"
t.text "content"
t.datetime "created_at"
t.datetime "updated_at"
end
end
Обратите внимание на версию миграции (версия представляет собой дату создания миграции) в файле schema.rb и имя файла миграции — теперь вам должно стать понятно, как ActiveRecord знает какие миграции необходимо выполнять по команде rake db:migrate. Запись версии в schema.rb происходит вместе с записью изменений структуры базы данных после выполнения миграции. При следующем запуске команды rake db:migrate будут выполняться только более поздние миграции.
Что умеют миграции?
Миграции умеют создавать и удалять таблицы базы данных, добавлять новые столбцы в таблицу, переименовывать и удалять столбцы, заполнять таблицы определенными данными (например при добавлении нового столбца к существующей таблице).
Как миграции определяют структуру таблицы?
Миграции работают очень просто — вы определяете в файле миграции метод change, а в его контексте используете специальные методы для описания структуры таблицы или выполнения с таблицей определенный версий. По сути, запуск миграции — это выполнение метода change.
#db/migrate/20120126202608_create_posts.rb
class CreatePosts < ActiveRecord::Migration
def change
create_table :posts do |t|
t.string :title
t.text :content
t.timestamps
end
end
end
В примере выше метод create_table используется, как не сложно догадаться, для создания новой таблицы. Первым аргументом метод create_table принимает имя таблицы, вторым — блок кода в контексте которого описывается структуру таблицы. Переменную t можно назвать объектом таблицы, методы string, text, integer, boolean и другие позволяют создавать столбцы (поля) соответствующего типа. Например, код, что представлен выше создает таблицу с 5 полями: id, title, content, created_at, updated_at.
Столбец id создается по умолчанию и потому мы не определяем его в нашем файле миграции. Столбцы title и content используются соответственно для хранния данных типа string (стока до 255 символов) и text (строка неограниченного размера). Столбцы created_at и updated_at создаются вместе от использования всего одного метода t.timestamps и используются для хранения даты добавления новой записи в таблицу и даты ее обновления.
Как работать с таблицами?
Создание таблицы, как говорилось выше выполняется методом create_table в блоке передаваемом которому определяется структура таблицы.
Для удаления таблицы используется метод drop_table(<имя таблицы>), например:
drop_table :users
Для переименования таблицы используется метод rename_table(<старое имя>, <новое имя>):
rename_table(:users, :warriors)
Какие бывают поля (столбцы) у таблицы?
ActiveRecord предоставляет несколько иные типы данных в сравнении с предоставляемыми базами данных, но это только иллюзия созданная для удобства работы программиста. Например string заменяет VARCHAR(225), а text все возможные LONG_TEXT и т.д. То же касается и integer и других типов. Ниже приведена таблица типов ActiveRecord, их описание и соответствие типам SQL.
Соответствие типов данных Rails типам популярных БД
| Rails | mysql | postgresql | sqlite |
|---|---|---|---|
| :binary | blob | bytea | blob |
| :boolean | tinyint(1) | boolean | boolean |
| :date | date | date | date |
| :datetime | datetime | timestamp | datetime |
| :decimal | decimal | decimal | decimal |
| :float | float | float | float |
| :integer | int(11) | integer | integer |
| :string | varchar(255) | varchar(255) | varchar(255) |
| :text | text | text | text |
| :time | time | time | datetime |
| :timestamp | datetime | timestamp | datetime |
Как добавить, изменить, переименовать или удалить столбцы в существующей таблице?
Добавление, изменение, переименование и удаление столбцов в таблице выполняется соответствующими 4 методами: add_column, change_column, rename_column, remove_column.
add_column(<имя таблицы>, <имя столбца>, <тип данных, например string или integer>, <опции, например значение по умолчанию>)
rename_column(<имя таблицы>, <имя столбца>, <новое имя столбца>)
change_column(<имя таблицы>, <имя столбца>, <тип данных, например string или integer>, <опции, например значение по умолчанию>)
remove_column(<имя таблицы>, <список столбцов, которые нужно удалить>)
Примеры:
add_column(:users, :level, :integer, {:default => 0, :null => false})
remove_column(:users, :level)
rename_column(:users, :level, :rank)
change_column(:users, :rank, :string, {:default => "soldier"})
Как работать с индексами и зачем они?
По умолчанию в каждой таблице имеется поле id которое служит для хранения уникального итерируемого идентификатора записи. Этот идентификатор служит для того, чтобы мы могли обратиться к определенной записи в таблице и только к ней. Идентификатор (он же индекс) можно сравнить с номером и серией паспорта, например.
Помимо id нам бывает необходимо добавить некоторые другие индексы, которые состояли бы из одного или нескольких полей. Эти дополнительные индексы необходимы для оптимизации базы данных и их стоит создавать только при достаточно большом количестве записей и реальной необходимости в поиске по ним так как большое количество индексов также замедляет работу. Решение о создании индекса для определенного поля похоже на хождение по веревке, когда нужно быть аккуратным чтобы не свалиться ни в одну из крайностей: отказ от индексов или их создания с избытком. Индексы базы данных можно сравнить с предметным указателем в книге. Без предметного указателя вам бы пришлось листать всю книгу целиком, а с ним вам достаточно найти нужный термин и сразу же перейти к чтению нужной страницы.
Добавление индексов производится также в файле миграций, иначе зачем бы я об этом говорил в этой статье? Создание индекса происходит через вызов метода add_index, а его удаление через метод remove_index:
add_index(<имя таблицы>, [<имя или список имен столбцов>], {<опции: name, order, unique>})
Примеры:
add_index(:users, [:name, :last_name], {:name => :index_fullname, :order => {:name => :desc}, :unique => false})
remove_index(:users, :name => :index_fullname)
remove_index(:users, :column => :credit_card_number)
Как в миграции выполнить SQL?
Rails позволяет вам помимо использования слоя абстракции над SQL использовать сам SQL для этого существует один простой метод execute в который следует в качестве аргумента передать строку SQL запроса. На практике execute используется достаточно редко в мелких и средних проектах, а вот в крупных он находит свое применение достаточно часто так как за счет использования SQL позволяет с пользой применять некоторые особенности используемого сервера баз данных.
Пример:
execute("DROP TABLE users;")
Как запустить миграцию или сделать откат изменений выполненных миграцией?
Как говорилось в самом начале статьи, для выполнения миграций необходимо использовать специальную Rake-задачу:
$ rake db:migrate
Эта задача выполнит все миграции, что ранее не были выполнены.
Для того, чтобы сделать откат миграций существует другая команда:
$ rake db:rollback STEP=3
В примере выше мы выполняем откат трех последних миграций, а ниже приведен пример отката до определенной версии:
$ rake db:rollback VERSION=X
В примере выше X — это версия миграции, например 20120126162916.
Как создать миграцию?
Для создания миграции следует использовать специальный генератор:
$ rails g[enerate] migration AddCreditCardIdToUsers
invoke active_record
create db/migrate/20120209155207_add_credit_card_id_to_users.rb
Лучшая благодарность автору — ваши комментарии и популяризация ресурса! Спасибо всем за внимание к проекту и моральную поддержку его автора. Не забывайте о нашей группе во Вконтакте: http://vk.com/rubydevclub!

февраля 10, 2012 at 03:31 (#)
А зачем они нужны эти ваши миграции? Монго наше все!!!
февраля 18, 2012 at 10:14 (#)
Danil Negrienko, не позорьтесь.