Rails: マイグレーションを実行せずにマイグレーションのSQLを表示する(翻訳)

概要 原著者の許諾を得て翻訳・公開いたします。 英語記事: Viewing migration SQL without running the migration 原文公開日: 2018/01/10 著者: Tom Copeland Rails: マイグレーションを実行せずにマイグレーションのSQLを表示する(翻訳) 「マイグレーションを実行しないでSQLを取る方法はありますか?」という質問を何度か目にしたことがあります。芸のない回答としては、質問の「マイグレーションを実行しないで」を無視してマイグレーションを実行し、ログファイルをgrepしてSQL出力を取り出し、db:rollbackを実行せよというのが考えられます。しかしこれはズルですし手間もかかります。もっとマシな方法はないものでしょうか。 私の最初のアプローチは、ActiveRecordスタックの相当深いところでメソッド呼び出しをインターセプトし、欲しいマイグレーションの場合は実行せずにSQLを出力するというものでした。私はPostgreSQLを使っているので、ActiveRecord::ConnectionAdapters::PostgreSQLAdapter#executeメソッドをインターセプトしてみたいと思います。以下はプロキシです。 module MyTweak def execute(sql, name=nil) if caller.detect {|x| x =~ /20171010151334/ } && sql !~ /SHOW TIME ZONE/ puts sql else super end end end しかし実際にこれを使ってみるとお世辞にも美しいとは言えませんでした。コンソールでこのコード変更を適用し、マイグレーションを明示的に呼び出さないといけません。 class ActiveRecord::ConnectionAdapters::PostgreSQLAdapter prepend MyTweak end require “#{Rails.root}/db/migrate/20171010151334_add_wing_count_to_jets” AddWingCountToJets.new.change サンプルの出力結果をいくつかGistに置きました。しかし見てのとおり、この方法は相当イケてないうえに何というか苦痛です。 StackOverflowのこのスレでもっとよいアプローチをいくつか見つけました。1つ目の回答はalias_methodでActiveRecord::ConnectionAdapters::AbstractMysqlAdapter#executeを再定義していますが、私が上のMyTweakでやったことと大差はなく、特定のメソッドをショートさせてSQLを出力しています。しかし本当の改善は、fake_db_migrateというRakeタスクを定義してモンキーパッチを当ててからdb:migrateを実行するという方法でした。これならハードコードも不要ですし、どんなマイグレーションでも動きます。 … Continue reading Rails: マイグレーションを実行せずにマイグレーションのSQLを表示する(翻訳)