質問: ### 前提・実現したいこと 現在1つのデータセットで Rails システムが動いているのですが 別環境で新たに同じシステムを追加することになりました なのでテーブル構造でデータセットは別にして新規にデータベースを作成したい ### 発生している問題 既存のマイグレーションは途中で手動で変更されたせいなのか一部マイグレーションに失敗します ### 試したいこと 新規にこれまでの履歴を無視したデータベース構成を作成するファイル CREATE TABLE 'users' ... みたいなのと 最低限の管理用初期データを挿入するファイル INSERT INTO 'users' ... というファイルを作って新規環境でのみ実行されるようにしたいです (既存環境でデータが初期化されたら大惨事になる) マイグレーションは db/migrate 以下の SQL コマンドリストをファイル単位でどこまで実行したか記憶して 未実行の差分だけを実行するものという認識なんですがあってますでしょうか もしその認識で正しいのであれば db/migrate 以下これまでの履歴と同じ名前で空のファイルに置き換えた状態で 1度新規サーバーにデプロイしてマイグレーション履歴を作ってしまう 今度は初期化用マイグレーションファイル 20181001....sql を中身を空にした状態で 既存のstaging, productionにデプロイして履歴を登録する そのあと履歴ファイルを戻して 20181001....sql に初期化用の中身を描いて新規サーバーにデプロイする という手順をとれば schema の中身はおなじになって別のDBの状態にできそうな気がするんですけどあってますか? もしもっと簡単に実現する方法があれば教えていただきたいです マイグレーションやデプロイ関連は先人が設定してくれた内容を使っていただけで全く知識がないので 見当外れな話をしていたらすいません
回答: **回答通りに行って問題が起こったとしても責任は持てません。 あくまでも一参考程度に収め、何かあった時に復旧ができるように 準備を欠かさないようにしてください。 大きな損失が出るのであればその手のプロフェッショナルを雇うべきです。** 追記された情報を見ていたら案外単純なことなんじゃないかと思ったのですが、 もし解釈が間違っていたらご指摘ください。 そもそも異なる環境でマイグレーションすると既存のデータベースのデータは新しい環境に入りません。 (seedsとかmigrate時に挿入してるなら話は別ですが。) マンションの設計図(migrateファイル)があり、それを建築(db:migrate)して 運用中に住人(データ)が入っていたとして、 新たに同じマンションを建築するときに、同じマンションの設計図から建築すると 見た目上は同じものができますが、そこの住人がコピーされることはないですよね? 初期レコードを挿入したいのであれば`db:seed`を使えばよいでしょう。 [用語について追記] 用語による齟齬が発生しそうなのでそのあたりを踏まえて追記します。 ### RailsにおけるDB操作について DBの作成や構造など、テーブル操作含めDBにおける操作は基本的にmigrationファイルで行うべきです。 ある処理はmigrationファイルでやってある処理はSQLコマンドでやって、のように複数の実行形式があると どれか実行し忘れるだけでバグの原因になります。 Railsでは`rails db:migrate`でファイルにある処理を一括して行ってくれるので 実行し忘れるというリスクは低いです。 また、Railsには他に初期化データを格納するseedsファイルがあるので、 最初のDB構築時に初期化データを`rails db:seed`で実行することができます。 今新規サーバで新しくDB環境を構築し、migrationファイルではなくSQLコマンドでなにか必要な処理したとします。 いずれ(新規サーバが壊れたとかで)また別な新規サーバで環境構築をするとまたSQLコマンドを打つことになりますが、 そのコマンドは確実に実行されると思いますか? SQLコマンドを打ったが何を打ったかわからない、メモしたファイルが見つからない、そもそも担当者が変わってわからないとか そういった面で実行されないリスクが高まります。 ### 環境によるDB周りについて 一般的にデータベースというとデータベース関連全体を含む広義の言葉を使用していますが、 構造は「レコード∈テーブル∈データベース」というようになっていて この構造でいうデータベースはデータの集合を意味する狭義の表現となります。 便宜上、この回答内では「DB:広義の意味」、「データベース:狭義の意味」で区別して記載します。 Railsでは`rails db:create`でデータベースの作成が行われ、環境毎に指定された名前の データベースが作成されます。 そして、`rails db:migrate`でテーブル関連の処理が記載されたファイルに従って行われます。 このmigrationファイルに記載された内容はどの環境でも同じように実行されますが、 それ以外のもの、たとえば運用中のデータ挿入、削除、更新などは環境によって変わります。 例えばAサーバで作成されたhogeデータベースにhugaというテーブルを作成したとします。 これを運用し、ユーザ登録等でデータがどんどん増えていくとしましょう。 Bサーバに同じ環境を整えようとしたとき、 Bサーバ上にもhogeデータベースが作成され、hugaテーブルがその中に作成されます。 AサーバとBサーバでは名前こそ同じデータベースですが、別々の場所にあるものなので AサーバのデータがBサーバのDBの中に入るわけではありません。 migrationファイルはあくまでも構築するための手順書で、 `rails db:migrate`は手順書を元に作り上げるだけなのです。 ### gemについて gemはRubyにおけるライブラリです。 複雑な機能を使いやすいようまとめたものだと思ってください。 コメント中に「Gemを作る」という言葉がありますが、意味合いがおかしくなってしまいますね。