Ruby on Rails
Миграции ActiveRecord
Поиск…
параметры
Тип столбца | Описание |
---|---|
:primary_key | Основной ключ |
:string | Более короткий тип данных строки. Позволяет установить limit для максимального количества символов. |
:text | Более длинное количество текста. Разрешает limit для максимального количества байтов. |
:integer | Integer. Разрешает limit для максимального количества байтов. |
:bigint | Большее целое число |
:float | терка |
:decimal | Десятичное число с переменной точностью. Позволяет настроить precision и scale . |
:numeric | Позволяет настроить precision и scale . |
:datetime | Объект DateTime для дат / времени. |
:time | Объект времени для времени. |
:date | Объект даты для дат. |
:binary | Двоичные данные. Разрешает limit для максимального количества байтов. |
:boolean | логический |
замечания
Большинство файлов миграции находятся в каталоге
db/migrate/
. Они идентифицируются по метке времени UTC в начале имени файла:YYYYMMDDHHMMSS_create_products.rb
.Команда
rails generate
может быть сокращена доrails g
.Если a
:type
не передается в поле, по умолчанию используется строка.
Запуск определенной миграции
Чтобы выполнить определенную миграцию вверх или вниз, используйте db:migrate:up
или db:migrate:down
.
Выполнить конкретную миграцию:
rake db:migrate:up VERSION=20090408054555
rails db:migrate:up VERSION=20090408054555
Вниз по определенной миграции:
rake db:migrate:down VERSION=20090408054555
rails db:migrate:down VERSION=20090408054555
Номер версии в приведенных выше командах - это числовой префикс в имени файла миграции. Например, чтобы перейти на миграцию 20160515085959_add_name_to_users.rb
, вы должны использовать 20160515085959
в качестве номера версии.
Создать таблицу соединений
Чтобы создать таблицу соединений между students
и courses
, выполните команду:
$ rails g migration CreateJoinTableStudentCourse student course
Это приведет к следующей миграции:
class CreateJoinTableStudentCourse < ActiveRecord::Migration[5.0]
def change
create_join_table :students, :courses do |t|
# t.index [:student_id, :course_id]
# t.index [:course_id, :student_id]
end
end
end
Выполнение миграции в разных средах
Чтобы выполнить миграцию в test
среде, запустите эту команду оболочки:
rake db:migrate RAILS_ENV=test
Начиная с Rails 5.0, вы можете использовать rails
вместо rake
:
rails db:migrate RAILS_ENV=test
Добавить новый столбец в таблицу
Чтобы добавить новое name
столбца в таблицу users
, выполните команду:
rails generate migration AddNameToUsers name
Это создает следующую миграцию:
class AddNameToUsers < ActiveRecord::Migration[5.0]
def change
add_column :users, :name, :string
end
end
Когда имя миграции имеет вид AddXXXToTABLE_NAME
за которым следует список столбцов с типами данных, сгенерированная миграция будет содержать соответствующие инструкции add_column
.
Добавить новый столбец с индексом
Чтобы добавить новое индексированное email
столбца в таблицу users
, выполните команду:
rails generate migration AddEmailToUsers email:string:index
Это приведет к следующей миграции:
class AddEmailToUsers < ActiveRecord::Migration[5.0]
def change
add_column :users, :email, :string
add_index :users, :email
end
end
Удалить существующий столбец из таблицы
Чтобы удалить существующее name
столбца из таблицы users
, выполните команду:
rails generate migration RemoveNameFromUsers name:string
Это приведет к следующей миграции:
class RemoveNameFromUsers < ActiveRecord::Migration[5.0]
def change
remove_column :users, :name, :string
end
end
Когда имя миграции имеет вид RemoveXXXFromYYY
за которым следует список столбцов с типами данных, тогда сгенерированная миграция будет содержать соответствующие инструкции remove_column
.
Хотя не обязательно указывать тип данных (например :string
) в качестве параметра remove_column
, настоятельно рекомендуется. Если тип данных не указан, то миграция не будет обратимой.
Добавить столбец ссылки в таблицу
Чтобы добавить ссылку на team
в таблицу users
, выполните следующую команду:
$ rails generate migration AddTeamRefToUsers team:references
Это создает следующую миграцию:
class AddTeamRefToUsers < ActiveRecord::Migration[5.0]
def change
add_reference :users, :team, foreign_key: true
end
end
Эта миграция создаст столбец team_id
в таблице users
.
Если вы хотите добавить соответствующий index
и foreign_key
в добавленный столбец, измените команду на rails generate migration AddTeamRefToUsers team:references:index
чтобы rails generate migration AddTeamRefToUsers team:references:index
. Это приведет к следующей миграции:
class AddTeamRefToUsers < ActiveRecord::Migration
def change
add_reference :users, :team, index: true
add_foreign_key :users, :teams
end
end
Если вы хотите указать свой ссылочный столбец, отличный от того, что генерирует Rails автоматически, добавьте следующее в свою миграцию: (Например: вы можете позвонить User
который создал Post
качестве Author
в таблице Post
)
class AddAuthorRefToPosts < ActiveRecord::Migration
def change
add_reference :posts, :author, references: :users, index: true
end
end
Создать новую таблицу
Чтобы создать новую таблицу users
с name
столбца и salary
, выполните команду:
rails generate migration CreateUsers name:string salary:decimal
Это приведет к следующей миграции:
class CreateUsers < ActiveRecord::Migration[5.0]
def change
create_table :users do |t|
t.string :name
t.decimal :salary
end
end
end
Когда имя миграции имеет вид CreateXXX
за которым следует список столбцов с типами данных, тогда будет создана миграция, которая создает таблицу XXX
с указанными столбцами.
Добавление нескольких столбцов в таблицу
Чтобы добавить несколько столбцов в таблицу, разделите field:type
пары с пробелами при использовании команды rails generate migration
.
Общий синтаксис:
rails generate migration NAME [field[:type][:index] field[:type][:index]] [options]
Например, следующее добавит поля name
, salary
и email
в таблицу users
:
rails generate migration AddDetailsToUsers name:string salary:decimal email:string
Что генерирует следующую миграцию:
class AddDetailsToUsers < ActiveRecord::Migration[5.0]
def change
add_column :users, :name, :string
add_column :users, :salary, :decimal
add_column :users, :email, :string
end
end
Выполнение миграций
Команда запуска:
rake db:migrate
rails db:migrate
При указании целевой версии будут выполняться требуемые миграции (вверх, вниз, изменение) до тех пор, пока она не достигнет указанной версии. Здесь version number
- это числовой префикс в имени файла миграции.
rake db:migrate VERSION=20080906120000
rails db:migrate VERSION=20080906120000
Откат миграции
rollback
последней миграции, либо путем возврата метода change
либо путем использования метода down
. Команда запуска:
rake db:rollback
rails db:rollback
Откат последних трех миграций
rake db:rollback STEP=3
rails db:rollback STEP=3
STEP
предоставляет количество возвращаемых миграций.
Откат всех миграций
rake db:rollback VERSION=0
rails db:rollback VERSION=0
Изменение таблиц
Если вы создали таблицу с неправильной схемой, тогда самый простой способ изменить столбцы и их свойства - change_table
. Просмотрите следующий пример:
change_table :orders do |t|
t.remove :ordered_at # removes column ordered_at
t.string :skew_number # adds a new column
t.index :skew_number #creates an index
t.rename :location, :state #renames location column to state
end
Вышеуказанная миграция изменяет orders
таблиц. Ниже приведены пошаговые описания изменений:
-
t.remove :ordered_at
удаляет столбецordered_at
изorders
таблицы. -
t.string :skew_number
добавляет новый столбец типа string с именемskew_number
в таблицеorders
. -
t.index :skew_number
добавляет индекс в столбецskew_number
в таблицеorders
. -
t.rename :location, :state
переименовываетlocation
столбца вorders
таблицы вstate
.
Добавить уникальный столбец в таблицу
Чтобы добавить новое уникальное email
для users
, выполните следующую команду:
rails generate migration AddEmailToUsers email:string:uniq
Это создаст следующую миграцию:
class AddEmailToUsers < ActiveRecord::Migration[5.0]
def change
add_column :users, :email, :string
add_index :users, :email, unique: true
end
end
Изменить тип существующего столбца
Чтобы изменить существующий столбец в Rails с переносом, выполните следующую команду:
rails g migration change_column_in_table
Это создаст новый файл миграции в каталоге db/migration
(если он еще не существует), который будет содержать файл с префиксом timestamp и имя файла миграции, которое содержит следующее содержимое:
def change
change_column(:table_name, :column_name, :new_type)
end
Rails Guide - Изменение столбцов
Более длинный, но более безопасный метод
Вышеупомянутый код не позволяет пользователю откатиться от миграции. Вы можете избежать этой проблемы, разделив метод change
на отдельные методы up
и down
:
def up
change_column :my_table, :my_column, :new_type
end
def down
change_column :my_table, :my_column, :old_type
end
Повторные миграции
Вы можете выполнить откат, а затем снова redo
миграцию с помощью команды redo
. Это, в основном, ярлык, сочетающий rollback
и migrate
задач.
Команда запуска:
rake db:migrate:redo
rails db:migrate:redo
Вы можете использовать параметр STEP
для возврата более одной версии.
Например, чтобы вернуться 3 миграции:
rake db:migrate:redo STEP=3
rails db:migrate:redo STEP=3
Добавить столбец со значением по умолчанию
Следующий пример добавляет admin
столбца в таблицу users
и дает этому столбцу значение по умолчанию false
.
class AddDetailsToUsers < ActiveRecord::Migration[5.0]
def change
add_column :users, :admin, :boolean, default: false
end
end
Миграции со значениями по умолчанию могут занять много времени в больших таблицах, например, PostgreSQL. Это связано с тем, что каждая строка должна быть обновлена со значением по умолчанию для вновь добавленного столбца. Чтобы обойти это (и сократить время простоя во время развертывания), вы можете разделить свою миграцию на три этапа:
- Добавьте
add_column
-migration, аналогичный приведенному выше, но не задайте значение по умолчанию - Развертывание и обновление столбца в задаче rake или на консоли во время работы вашего приложения. Убедитесь, что ваше приложение уже записывает данные в этот colum для новых / обновленных строк.
- Добавьте еще одну
change_column
, которая затем изменит значение по умолчанию этого столбца на желаемое значение по умолчанию
Запретить нулевые значения
Чтобы запретить null
значения в столбцах таблицы, добавьте параметр :null
в вашу миграцию, например:
class AddPriceToProducts < ActiveRecord::Migration
def change
add_column :products, :float, null: false
end
end
Проверка статуса миграции
Мы можем проверить статус миграции, выполнив
rake db:migrate:status
rails db:migrate:status
Результат будет выглядеть так:
Status Migration ID Migration Name
--------------------------------------------------
up 20140711185212 Create documentation pages
up 20140724111844 Create nifty attachments table
up 20140724114255 Create documentation screenshots
up 20160213170731 Create owners
up 20160218214551 Create users
up 20160221162159 ********** NO FILE **********
up 20160222231219 ********** NO FILE **********
В поле «Статус» up
означает, что миграция выполнена и down
означает, что нам нужно выполнить миграцию.
Создать столбец hstore
Hstore
могут быть полезны для сохранения настроек. Они доступны в базах данных PostgreSQL после включения расширения.
class CreatePages < ActiveRecord::Migration[5.0]
def change
create_table :pages do |t|
enable_extension 'hstore' unless extension_enabled?('hstore')
t.hstore :settings
t.timestamps
end
end
end
Добавить самостоятельную ссылку
Самостоятельная ссылка может быть полезна для построения иерархического дерева. Это может быть достигнуто с помощью add_reference
в переносе.
class AddParentPages < ActiveRecord::Migration[5.0]
def change
add_reference :pages, :pages
end
end
Столбец внешнего ключа будет pages_id
. Если вы хотите определить имя столбца внешнего ключа, сначала нужно создать столбец и добавить ссылку после.
class AddParentPages < ActiveRecord::Migration[5.0]
def change
add_column :pages, :parent_id, :integer, null: true, index: true
add_foreign_key :pages, :pages, column: :parent_id
end
end
Создать столбец массива
Столбец array
поддерживается PostgreSQL. Rails автоматически преобразует массив PostgreSQL в массив Ruby и наоборот.
Создайте таблицу со столбцом array
:
create_table :products do |t|
t.string :name
t.text :colors, array: true, default: []
end
Добавьте столбец array
в существующую таблицу:
add_column :products, :colors, array: true, default: []
Добавьте индекс для столбца array
:
add_index :products, :colors, using: 'gin'
Добавление ограничения NOT NULL к существующим данным
Предположим, вы хотите добавить внешний ключ company_id
в таблицу users
, и вы хотите ограничить NOT NULL
. Если у вас уже есть данные у users
, вам придется сделать это несколькими шагами.
class AddCompanyIdToUsers < ActiveRecord::Migration
def up
# add the column with NULL allowed
add_column :users, :company_id, :integer
# make sure every row has a value
User.find_each do |user|
# find the appropriate company record for the user
# according to your business logic
company = Company.first
user.update!(company_id: company.id)
end
# add NOT NULL constraint
change_column_null :users, :company_id, false
end
# Migrations that manipulate data must use up/down instead of change
def down
remove_column :users, :company_id
end
end