Ruby on Rails 3: Миграции в Rails 3.x
февраля 9, 2012 | Published in Ruby on Rails, Ruby on Rails 3 | 5 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
Лучшая благодарность автору — ваши комментарии и популяризация ресурса! Спасибо всем за внимание к проекту и моральную поддержку его автора. Не забывайте о нашей группе во Вконтакте: !
февраля 10, 2012 at 03:31 (#)
А зачем они нужны эти ваши миграции? Монго наше все!!!
февраля 18, 2012 at 10:14 (#)
Danil Negrienko, не позорьтесь.
июля 6, 2012 at 13:32 (#)
Цілком погоджуюсь із думкою Данилка Негієнка.
І взагалі, на мою думку. це взагалі просто
повний піу-піу.
сентября 5, 2012 at 15:12 (#)
Огромное спасибо за простые и понятные пояснения. То что нужно!
сентября 27, 2013 at 03:48 (#)
Ваш блог содержит самый разжеванный и доступный для понимания материал по рельсовым нюансам в рунете. Пожалуйста, не останавливайтесь.