显示由rails中的挂起迁移生成的SQL,而不更新数据库

Mas*_*ant 11 database rake ruby-on-rails

我想有一种方法来生成实际的sql(即:如果我粘贴到mysql控制台,它会工作)将由rake db:migrate生成,而不实际更新目标数据库.

rake db:migrate:status可以很好地显示给定数据库的哪些迁移正在等待,但我还没有找到一种方法来获取实际生成的SQL.

有任何想法吗?

Sem*_*jon 8

非常有趣的问题!我发现了这种方式:

  1. 假设您的迁移位于文件中db/migrate/20160102210050_create_items.rb并被调用CreateItems
  2. 转到Rails控制台并加载迁移文件:

    rails c
    require './db/migrate/20160102210050_create_items'
    
    Run Code Online (Sandbox Code Playgroud)
  3. 打开事务,在提交之前运行迁移和回滚事务:)

    ActiveRecord::Base.connection.transaction do
      CreateItems.new.migrate :up
      raise ActiveRecord::Rollback
    end
    
    Run Code Online (Sandbox Code Playgroud)

如果要在回滚时检查SQL,只需CreateItems.new.migrate :down在步骤3上调用.SQL将在数据库上执行和测试,但未提交 - 因此您可以在不受影响的情况下验证迁移.

  • 您还可以使用“rails c --sandbox”,那么您不需要任何事务,也不需要任何回滚:只需使用“CreateItems.new.migrate :up”,Rails 将在关闭控制台时自动回滚 (2认同)
  • 这仅适用于支持事务 DDL 的 RDMBS。 (2认同)

Bor*_*aMa 3

这可以通过对数据库适配器进行猴子修补来完成。此示例适用于 MySQL。

为“fake db:migrate”创建一个 rake 任务:

desc "Prints all SQL to be executed during pending migrations"
task :fake_db_migrate => :environment do

  module ActiveRecord
    module ConnectionAdapters
      class AbstractMysqlAdapter < AbstractAdapter

        alias_method :real_execute, :execute

        def execute(sql, name = nil)
          if sql =~ /^SHOW/ || sql =~ /^SELECT.*FROM.*schema_migrations/ || sql =~ /^SELECT.*information_schema/m
            real_execute(sql, name)
          else
            puts sql
          end
        end

      end
    end
  end

  Rake::Task["db:migrate"].invoke
end
Run Code Online (Sandbox Code Playgroud)

rake 任务execute对连接适配器中的方法进行猴子修补,以便在实际运行迁移之前打印 SQL,而不是执行 SQL。但是,我们仍然需要执行任务使用的一些内部 SQLdb:migrate来获取数据库架构并找出哪些迁移正在挂起。这就是real_execute调用的作用。

测试

现在假设我们有一个待处理的迁移db/migrate/20160211212415_create_some_table.rb

class CreateSomeTable < ActiveRecord::Migration
  def change
    create_table :some_table do |t|
      t.string :string_column, null: false, default: 'ok'
      t.timestamps
    end
  end
end

$ rake db:migrate:status
...
down    20160211212415  Create some table
Run Code Online (Sandbox Code Playgroud)

现在,让我们运行我们的假迁移任务:

$ rake fake_db_migrate
== 20160211212415 CreateSomeTable: migrating ==================================
-- create_table(:some_table)
CREATE TABLE `some_table` (`id` int(11) auto_increment PRIMARY KEY, `string_column` varchar(255) DEFAULT 'ok' NOT NULL, `created_at` datetime, `updated_at` datetime) ENGINE=InnoDB
   -> 0.0009s
== 20160211212415 CreateSomeTable: migrated (0.0010s) =========================

BEGIN
INSERT INTO `schema_migrations` (`version`) VALUES ('20160211212415')
COMMIT
Run Code Online (Sandbox Code Playgroud)

迁移状态尚未更改,即迁移仍处于待处理状态:

$ rake db:migrate:status
...
down    20160211212415  Create some table
Run Code Online (Sandbox Code Playgroud)

使用 gem 在 Rails 4.2.3 上进行测试mysql2