Ruby on Rails 3: Миграции в Rails 3.x

февраля 9, 2012  |  Published in Ruby on Rails, Ruby on Rails 3  |  5 Comments

ruby on rails tutorialRubyDev — ваш друг в изучении 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

 

Лучшая благодарность автору — ваши комментарии и популяризация ресурса! Спасибо всем за внимание к проекту и моральную поддержку его автора. Не забывайте о нашей группе во Вконтакте: !

Tags: , , , , ,

Responses

  1. says:

    февраля 10, 2012 at 03:31 (#)

    А зачем они нужны эти ваши миграции? Монго наше все!!!

  2. Dizlv says:

    февраля 18, 2012 at 10:14 (#)

    Danil Negrienko, не позорьтесь.

  3. Василько Черезпарканногузадерищенко says:

    июля 6, 2012 at 13:32 (#)

    Цілком погоджуюсь із думкою Данилка Негієнка.
    І взагалі, на мою думку. це взагалі просто
    повний піу-піу.

  4. Алона says:

    сентября 5, 2012 at 15:12 (#)

    Огромное спасибо за простые и понятные пояснения. То что нужно!

  5. textballade says:

    сентября 27, 2013 at 03:48 (#)

    Ваш блог содержит самый разжеванный и доступный для понимания материал по рельсовым нюансам в рунете. Пожалуйста, не останавливайтесь.

Leave a Response

Для подсветки кода используйте BB - коды: [language]...[/language], где language может быть: ruby, javascript, css, html.