Я хотел написать документ обо всем, что я нашел полезным при изучении рельсов, поскольку это относится к миграции. От создания миграции до написания обратимого кода в методе изменения.
ПРИМЕЧАНИЕ Если у вас нет mysql и он вам не нужен. Это нормально. Продолжайте двигаться. Если вы не укажете -d mysql, то rails будет использовать встроенный sqlite. Ничего не меняется.
Как начать работу с mysql и создать проект с базой данных
# Generate a rails project called possible using mysql rails new possible -d mysql # OR using sqlite rails new possible
Обновите файл возможных/config/database.yml, указав свое имя пользователя и пароль. Если вы используете sqlite, делать нечего.
# Generate your databases rails db:create Created database 'possible_development' Created database 'possible_test'
db:create берет базы данных, описанные в файле database.yml, и создает их для вас.
Как сгенерировать Migration.
rails generate migration Car Running via Spring preloader in process 58104 invoke active_record create db/migrate/20190622100711_car.rb # short hand rails g migration Car
При создании миграции. Держите имена в единственном числе. Миграция не создаст модель. Обратите внимание на имя. Имя миграции состоит из метки времени, подчеркивания и имени. Вот как рельсы отслеживают, выполнялась ли конкретная миграция. В этом уроке мы будем часто использовать идентификатор временной метки.
Запустите миграцию
rails db:migrate == 20190622101002 Car: migrating ============================================== == 20190622101002 Car: migrated (0.0000s) =====================================
Бам, мы только что запустили пустую миграцию. Позвоним в статус
rails db:migrate:status database: possible_development Status Migration ID Migration Name -------------------------------------------------- up 20190622101002 Car
Запомни это имя сверху. Отметка времени подчеркивания и имени. Здесь в игру вступает метка времени. Давайте создадим еще одну миграцию.
# Create the motorcycle migration rails g migration Motorcycle Running via Spring preloader in process 58787 invoke active_record create db/migrate/20190622101829_motorcycle.rb # Check the Migration Status rails db:migrate:status database: possible_development Status Migration ID Migration Name -------------------------------------------------- up 20190622101002 Car down 20190622101829 Motorcycle
Из db:migrate:status я вижу, что я еще не выполнил эту конкретную миграцию. Вот что я собираюсь сделать.
- Я запущу db:migrate для переноса новой миграции.
- Потом проверю статус.
- Я удалю только миграцию автомобиля и снова проверю статус.
# 1 rails db:migrate == 20190622101829 Motorcycle: migrating ======================================= == 20190622101829 Motorcycle: migrated (0.0000s) ============================== # 2 rails db:migrate:status database: possible_development Status Migration ID Migration Name -------------------------------------------------- up 20190622101002 Car up 20190622101829 Motorcycle #3 rails db:migrate:down VERSION=20190622101002 == 20190622101002 Car: reverting ============================================== == 20190622101002 Car: reverted (0.0096s) ===================================== rails db:migrate:status database: possible_development Status Migration ID Migration Name -------------------------------------------------- down 20190622101002 Car up 20190622101829 Motorcycle
Проверьте это. Я смог выполнить одну миграцию, используя :down и VERSION = отметку времени миграции.
Автомобиль в том виде, в котором он сейчас находится, — довольно хромая миграция. У него только… Ну, ничего. давайте добавим таблицу с несколькими столбцами. Rails не генерирует таблицу автоматически при создании миграции. Так как миграция может быть много вещей. В отличие от модели.
ПРИМЕЧАНИЕ. Обычно добавление/удаление/изменение чего-либо в миграции состоит из создания новой миграции. Что мы и сделаем позже. Ради примеров. Я отредактирую миграцию автомобиля, чтобы добавить в нее несколько полей. Затем мы запустим все наши миграции и снова запустим их вперед.
# Generate the table class Car < ActiveRecord::Migration[5.2] def change create_table :cars do |t| # code goes here end end end
Давайте создадим несколько столбцов.
- Создайте столбец с именем «модель», который представляет собой строку с ограничением в 25 символов. (Долгий путь)
- Создайте столбец с именем «Vin», который представляет собой целое число с ограничением в 17 символов и не может быть нулевым (сокращенный способ).
- Убедитесь, что в таблицу добавлено время обновления и создания.
class Car < ActiveRecord::Migration[5.2] def change create_table :cars do |t| t.column "model", :string, :limit => 25 # long way t.integer "vin", :null => false # short way t.timestamps end end end
t.column указывает на создание столбца. Имя этого столбца и тип данных, которые он будет содержать. Rails знает, что вы пытаетесь создать столбец. На самом деле вы можете сократить это. t.integer просто создает столбец типа integer. это позволяет вам отказаться от типа, как показано выше.
Теперь у нас есть некоторый контекст для нашей миграции автомобилей. давайте продолжим и запустим миграцию. Я могу просто использовать rails db:migrate для запуска всех миграций в неактивном состоянии, что, если вы помните выше. Мы отказались от миграции автомобилей.
rails db:migrate == 20190622101002 Car: migrating ============================================== -- create_table(:cars) -> 0.0429s == 20190622101002 Car: migrated (0.0429s) =====================================
ПРИМЕЧАНИЕ. Я хочу уделить секунду и поговорить о функции изменения в миграции, которую мы только что выполнили. Более новый метод «изменения». Что отлично работает для наших простых миграций, может не работать для более сложных миграций. На самом деле я предпочитаю указывать вверх и вниз. Итак, для нашей миграции мотоциклов. Мы собираемся изменить миграцию мотоцикла, чтобы использовать функции вверх и вниз. Затем мы добавим два поля. Модель и vin с нулевой проверкой.
class Motorcycle < ActiveRecord::Migration[5.2] def up create_table :motorcycles do |t| t.string 'modal' t.integer 'vin' t.timestamps end end def down drop_table :motorcycles end end
Теперь мы четко определили наши методы up и down. Как я упоминал ранее. Change знает, как удалить таблицу. Это часть конвенции rails. Вверх и вниз — это то, что происходит за кулисами с методом изменения.
Давайте запустим наши миграции.
rails db:migrate
Что случилось? Ничего такого!
рельсы БД: миграция: статус
database: possible_development Status Migration ID Migration Name -------------------------------------------------- up 20190622101002 Car up 20190622101829 Motorcycle
Наши миграции уже запущены. При изменении миграции вы всегда должны создавать новую миграцию, которая изменяет работу предыдущей миграции. Наши миграции были пусты. Так что никаких конфликтов для нас нет. Мы можем откатить наши миграции, что просто ничего не делает. Если бы я создал таблицы и отредактировал файл migration. Скорее всего, они потерпят неудачу. Вот почему я создаю новую миграцию, чтобы внести изменения в существующий код миграции.
Давайте опустим их и поднимем обратно.
rails db:migrate:down VERSION=20190622101829 rails db:migrate:down VERSION=20190622101002 rails db:migrate
На данный момент у нас есть две миграции, каждая из которых состоит из modal и vin. Я показал вам два разных способа написания миграции. Вверх/вниз и изменить. Это не отвечает на вопрос. Что происходит в сложных ситуациях, когда изменения не могут легко понять, как понизить миграцию? На помощь приходит обратимый код. Таким образом, мы можем настроить наши методы up и down внутри метода change. Не волнуйтесь, это настолько сложно, насколько это возможно. Так что, если вы все еще со мной. Так держать.
class Car < ActiveRecord::Migration[5.2] def change reversible do |dir| dir.up do create_table :cars do |t| puts "creating table with name and vin t.column "first_name", :string, :limit => 25 # long way t.integer "vin", :null => false # short way t.timestamps end end dir.down do puts "Dropping the table cars" drop_table :cars puts "Dropping succeeded" end end end end
Вот как мы настраиваем метод изменения, чтобы иметь обратимый вверх и вниз код. Большинство из нас никогда не коснутся такого типа кода, но приятно знать, что он существует. Давайте продолжим, отбросим нашу миграцию и пересоберем ее, просто чтобы убедиться, что все это все еще работает. О, и поздоровайтесь с нашими путевыми заявлениями.
# CHECK STATUS rails db:migrate:status database: possible_development Status Migration ID Migration Name -------------------------------------------------- up 20190622101002 Car up 20190622101829 Motorcycle BRING DOWN rails db:migrate:down VERSION=20190622101002 == 20190622101002 Car: reverting ============================================== Dropping the table cars -- drop_table(:cars) -> 0.0106s Dropping succeeded == 20190622101002 Car: reverted (0.0197s) ===================================== # BRING UP rails db:migrate:up VERSION=20190622101002 == 20190622101002 Car: migrating ============================================== -- create_table(:cars) creating table with name and vin -> 0.0457s == 20190622101002 Car: migrated (0.0458s) =====================================
Это было много, что я знаю. Если вы когда-нибудь напишете миграцию, сложную для рельсов, чтобы выяснить, как вернуться. Теперь вы знаете, как писать настраиваемый код повышения и понижения при миграции изменений. Повезло тебе! Ну и еще, с добавлением операторов puts.
Давайте создадим еще две миграции, которые изменят существующие таблицы. Это правильный способ изменить миграцию. Никогда не редактируйте существующую миграцию, чтобы изменить ее, если только вам это действительно не нужно.
rails g migration AddColumnsToCars Running via Spring preloader in process 60434 invoke active_record create db/migrate/20190622111101_add_columns_to_cars.rb rails g migration ChangeColumnsOnMotorcycles Running via Spring preloader in process 60448 invoke active_record create db/migrate/20190622111105_change_columns_on_motorcycles.rb
Поменяем колонки в машинах.
class AddColumnsToCars < ActiveRecord::Migration[5.2] def change add_column :cars, :tires, :string add_column('cars', 'tireNumber', 'integer') end end
Это, конечно, не исчерпывающий список того, что вы можете делать с существующей таблицей. Хотя вот один.
create_table, add_column, add_index, add_foreign_key, add_reference, add_timestamps, rename_table, rename_column, rename_index drop_table, remove_column, remove_index, remove_foreign_key, remove_reference, remove_timestamps.
Идем дальше, теперь мы добавили столбец с помощью символов и добавили столбец с помощью строк. Вы можете видеть, что не имеет значения, как вы это делаете. Это то же самое. Я сделал это только для того, чтобы показать, что вы можете использовать символы и/или строки.
Давайте запустим эту миграцию, чтобы убедиться, что она работает. Мы всегда должны делать паузы, чтобы часто запускать наши миграции. Гораздо проще устранить неполадки с одной миграцией, чем потом.
rails db:migrate:status database: possible_development Status Migration ID Migration Name -------------------------------------------------- up 20190622101002 Car up 20190622101829 Motorcycle down 20190622111101 Add columns to cars down 20190622111105 Change columns on motorcycles
У меня две миграции. Я просто хочу управлять машинами прямо сейчас. Я еще не менял мотоцикл. Итак, давайте запустим его и нацелимся на отметку времени миграции.
rails db:migrate:up VERSION=20190622111101 == 20190622111101 AddColumnsToCars: migrating ================================= -- add_column(:cars, :tires, :string) -> 0.0402s -- add_column("cars", "tireNumber", "integer") -> 0.0111s == 20190622111101 AddColumnsToCars: migrated (0.0515s) ========================
Существует гораздо лучший способ создания миграций, которые требуют гораздо меньше работы. Это включает в себя указание их в командной строке. Это не сложно, и я приведу пример. Давайте сделаем это сейчас с мотоциклами.
rails g migration AddColsToMotorcycles tires:integer shocks:string # THIS GENERATES A MIGRATION FOR US WITH THE COLUMNS AND WE DON'T HAVE TO TYPE THEM. class AddColsToMotorcycles < ActiveRecord::Migration[5.2] def change add_column :motorcycles, :tires, :integer add_column :motorcycles, :shocks, :string end end
Это все, что потребовалось. Это было намного меньше работы, не так ли? Существует бесконечное количество способов генерировать вещи через командную строку в рельсах. Я не буду вдаваться в подробности здесь, но, пожалуйста, посмотрите документацию по рельсам, чтобы узнать больше о миграциях.
Вот и все, надеюсь вы что-то узнали или вспомнили что-то полезное, если покажете ставьте лайк или делитесь.