Подтвердить что ты не робот

Как пропустить неудачные миграции? (rake db: migrate)

Я не могу найти вариант или что-нибудь, что позволяет мне пропускать миграции.

Я знаю, о чем вы думаете: "вам никогда не придется это делать..."

Мне нужно пропустить миграцию, которая вносит изменения в определенные записи пользователя, которых нет в моей базе данных разработки. Я не хочу менять миграцию, потому что это не часть источника, с которым я должен работать. Есть ли способ пропустить миграцию или пропустить неудачные миграции?

Спасибо заранее!

4b9b3361

Ответ 1

Я думаю, что вы должны исправить, что оскорбительные миграции будут менее хрупкими, я бы предположил, что достаточно пары инструкций if и, возможно, rescue.

Но если исправление миграции действительно не является вариантом, вы можете подделать его различными способами. Прежде всего, вы можете просто прокомментировать методы миграции, запустите rake db:migrate, а затем раскомментируйте (или верните) оскорбительную миграцию.

Вы также можете подделать его внутри базы данных, но этот вид придира не рекомендуется, если вы не знаете, что делаете, и вы не возражаете, чтобы вручную исправлять ситуацию, когда вы (неизбежно) совершаете ошибку. В вашей базе данных есть таблица schema_migrations, которая имеет один столбец varchar(255) с именем version; эта таблица используется db:migrate для отслеживания того, какие миграции были применены. Все, что вам нужно сделать, - INSERT, соответствующее значение version и rake db:migrate будет считать, что миграция выполнена. Найдите файл миграции:

db/migrate/99999999999999_XXXX.rb

затем зайдите в свою базу данных и скажите:

insert into schema_migrations (version) values ('99999999999999');

где 99999999999999 - это, конечно, номер из имени файла миграции. Затем запуск rake db:migrate должен пропустить эту миграцию.

Я бы пошел со вторым вариантом до третьего, я только включил опцию "hack schema_versions" для полноты.

Ответ 2

У меня была проблема, когда у меня была миграция, чтобы добавить уже существующую таблицу, поэтому в моем случае мне тоже пришлось пропустить эту миграцию, потому что я получал ошибку

SQLite3::SQLException: table "posts" already exists: CREATE TABLE "posts"

Я просто прокомментировал содержимое метода create table, выполнил миграцию, а затем раскомментировал его. Это своего рода ручной способ обойти это, но это сработало. См. Ниже:

class CreatePosts < ActiveRecord::Migration
  def change
    # create_table :posts do |t|
    #   t.string :title
    #   t.text :message
    #   t.string :attachment
    #   t.integer :user_id
    #   t.boolean :comment
    #   t.integer :phase_id

    #   t.timestamps
    # end
  end
end

Ответ 3

Это хороший способ сделать это для разовых ошибок.

db:migrate:up VERSION=my_version

Это приведет к одному конкретному действию миграции "вверх". (Если вам это нужно, просто измените "вверх" на "вниз".) Таким образом, вы можете либо запустить будущую миграцию, которая заставит старшую (что вам нужно пропустить) работать, либо просто запустить каждый миграция перед ним выборочно.

Я также считаю, что вы можете переделать миграцию следующим образом:

rake db:migrate:redo VERSION=my_version

Я не пробовал этот метод лично, поэтому YMMV.

Ответ 4

Если вам нужно это сделать, ваши миграции приложений будут испорчены!

Вставляет все отсутствующие миграции:

def insert(xxx)
  ActiveRecord::Base.connection.execute("insert into schema_migrations (version) values (#{xxx})") rescue nil
end

files = Dir.glob("db/migrate/*")
files.collect { |f| f.split("/").last.split("_").first }.map { |n| insert(n) }

Ответ 5

Вместо того, чтобы пропустить перенос, вы можете сделать свой переход умным, добавив к нему некоторый IF, чтобы вы могли проверить "конкретных пользователей"

Ответ 6

иногда необходимо повторно заполнить таблицу schema_migrations определенно корректными миграциями. ТОЛЬКО ДЛЯ ЭТОЙ ЦЕЛИ Я создал этот метод

def self.insert_missing_migrations(stop_migration=nil)
  files = Dir.glob("db/migrate/*")
  timestamps = files.collect{|f| f.split("/").last.split("_").first}
  only_n_first_migrations = timestamps.split(stop_migration).first

  only_n_first_migrations.each do |version|
    sql = "insert into `schema_migrations` (`version`) values (#{version})"
    ActiveRecord::Base.connection.execute(sql) rescue nil
  end
end

вы можете скопировать его в любую желаемую модель и использовать ее с консоли

YourModel.insert_missing_migrations("xxxxxxxxxxxxxx")

(или как-то еще)

где "xxxxxxxxxxxxxx" - это отметка времени миграции, перед которой вы хотите остановить вставку (вы можете оставить ее пустой)

!!! используйте его, только если вы абсолютно понимаете, какой результат вы получите!!!

Ответ 7

Чтобы пропустить все отложенные миграции, запустите это в своем терминале:

echo "a = [" $(rails db:migrate:status | grep "down" | grep -o '[0-9]\{1,\}' | tr '\n' ', ') "];def insert(b);ActiveRecord::Base.connection.execute(\"insert into schema_migrations (version) values (#{b})\") rescue nil;end;a.map { |b| insert(b)}" | xclip

(Для macOS используйте pbcopy вместо xclip)

Затем CTRL-V результат внутри консоли рельсов:

a = [ 20180927120600,20180927120700 ];def insert(b);ActiveRecord::Base.connection.execute("insert into schema_migrations (version) values (#{b})") rescue nil;end;a.map { |b| insert(b)}

И нажмите ENTER.

Вы можете изменить список миграций, которые хотите пропустить, удалив их из массива a перед выполнением строки.