質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

1回答

512閲覧

新規データベースでシステムのコピーを作りたい

退会済みユーザー

退会済みユーザー

総合スコア0

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

0クリップ

投稿2018/10/01 08:12

編集2022/01/12 10:55

前提・実現したいこと

現在1つのデータセットで Rails システムが動いているのですが
別環境で新たに同じシステムを追加することになりました

なのでテーブル構造でデータセットは別にして新規にデータベースを作成したい

発生している問題

既存のマイグレーションは途中で手動で変更されたせいなのか一部マイグレーションに失敗します

###試したいこと

新規にこれまでの履歴を無視したデータベース構成を作成するファイル
CREATE TABLE 'users' ...
みたいなのと
最低限の管理用初期データを挿入するファイル
INSERT INTO 'users' ...
というファイルを作って新規環境でのみ実行されるようにしたいです
(既存環境でデータが初期化されたら大惨事になる)

マイグレーションは db/migrate 以下の SQL コマンドリストをファイル単位でどこまで実行したか記憶して
未実行の差分だけを実行するものという認識なんですがあってますでしょうか

もしその認識で正しいのであれば
db/migrate 以下これまでの履歴と同じ名前で空のファイルに置き換えた状態で
1度新規サーバーにデプロイしてマイグレーション履歴を作ってしまう
今度は初期化用マイグレーションファイル 20181001....sql を中身を空にした状態で
既存のstaging, productionにデプロイして履歴を登録する
そのあと履歴ファイルを戻して 20181001....sql に初期化用の中身を描いて新規サーバーにデプロイする

という手順をとれば schema の中身はおなじになって別のDBの状態にできそうな気がするんですけどあってますか?

もしもっと簡単に実現する方法があれば教えていただきたいです

マイグレーションやデプロイ関連は先人が設定してくれた内容を使っていただけで全く知識がないので
見当外れな話をしていたらすいません

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dice142

2018/10/01 11:05

「新しく空のテーブル構成」とは既存のテーブルと同名で何も入っていない状態ということでしょうか?イメージがつかないのでダミーでいいので例があると把握しやすいです。
退会済みユーザー

退会済みユーザー

2018/10/02 01:16

そうです テーブル自体はユーザ情報やロール情報ぐらいですがカラムをどんどん追加してきた感じです
dice142

2018/10/02 01:58

イメージが掴めないので現在どういう状態で、移行後はどういう感じになるのか追記していただけると助かります。
guest

回答1

0

回答通りに行って問題が起こったとしても責任は持てません。
あくまでも一参考程度に収め、何かあった時に復旧ができるように
準備を欠かさないようにしてください。
大きな損失が出るのであればその手のプロフェッショナルを雇うべきです。

追記された情報を見ていたら案外単純なことなんじゃないかと思ったのですが、
もし解釈が間違っていたらご指摘ください。

そもそも異なる環境でマイグレーションすると既存のデータベースのデータは新しい環境に入りません。
(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を作る」という言葉がありますが、意味合いがおかしくなってしまいますね。

投稿2018/10/02 06:13

編集2018/10/03 09:14
dice142

総合スコア5158

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/10/02 06:31

db:seed というのがあるんですね db:migrate しかうったことがなくてそのへんの知識も不足しているので調べてみます 回答ありがとうございます
退会済みユーザー

退会済みユーザー

2018/10/03 02:46 編集

マイグレーション関連のドキュメントを読んでみたんですが migrate と seed の違いがよくわからなかったです 必ず初期化データ挿入処理を実行してしまうのであれば今回の場合かえってまずいような気がしました あとデプロイには Capistorano という Gem が使われていて デプロイコマンドを変更するのであれば Capistorano の仕組みも理解する必要があるので かえって大変になりそうな気がするのですがマイグレーションファイルのやりくりだけでは実現不可能でしょうか
dice142

2018/10/03 02:41

データベース構成後の初期データという認識だったのでseedをあげましたが、 初期データという位置づけでなければmigrateファイルでインサートも可能です。 productionのみの初期データであれば「seed-fu」というgemで 使い分けができそうなので、そちらを活用してみてはどうでしょうか?
退会済みユーザー

退会済みユーザー

2018/10/03 02:51

何度もレスいただいてありがとうございます seed-fu というのもはじめてきくので調べてみます
退会済みユーザー

退会済みユーザー

2018/10/03 03:01

初期化処理を ruby でかけるのですね しかも既存のDBから自動で生成できるのはいいですね ただすでに初期化用の処理自体はSQLファイルを作ってしまったので ruby で書き直すのはかえって手間な気がします あと自分が一番知りたいのは「どうやって初期データを作るか」ではなく 「どうやって既存環境で実行せずに新規環境だけで実行するか」という点なのです Rails さわりはじめて間もないので見当外れな話をしていたら申し訳ありません
dice142

2018/10/03 03:13

> 初期化処理を ruby でかけるのですね 最初に提案したseedも同じものです。 それを環境毎に実行ファイルを変えれるようにしたgemがseed-fuです。 ただ、既存の環境と新規環境がどちらもproductionならファイルを分ける必要がないですが、 初期データなので既存環境では実行しないものなので大丈夫かと。 > ただすでに初期化用の処理自体はSQLファイルを作ってしまったので > ruby で書き直すのはかえって手間な気がします そもそもrailsでシステムを構築しているのでしたらSQLファイルを別途作るメリットがない気がします。 > 自分が一番知りたいのは「どうやって初期データを作るか」ではなく > 「どうやって既存環境で実行せずに新規環境だけで実行するか」という点なのです 既存環境では既に運用されてるので初期データを入れる必要がないので、 初期データを作って新規環境で DB構築→初期データ投入 を行えば良いのではないですか? migrateファイルは環境毎に分けるものではないと私は思っているので むしろそちらで行う方が既存環境と新規環境で分けるのが難しいと思います。 その点初期データなら運用済みの環境に入れるものではないので、 初期データという形はあながち間違っていないと思いますが。
退会済みユーザー

退会済みユーザー

2018/10/03 04:00 編集

マイグレーションにうまく記述すればデプロイコマンドを叩いたときに新規サーバー(初期データがない状態であれば)自動的に初期化ルーチンだけが実行されるというイメージだったのですが マイグレーションに記述するのではなく単に新規サーバーでSQLコマンドをたたくなりジェムを作るなりでデータベースを作ってしまえばマイグレーションは気にしなくていいということでしょうか デプロイの中に db:migrate が含まれているみたいでデータベースにカラムを追加するときは db/migrate/ に create_column をかいたファイルを追加してコミットというルールになってるんですが 逆に新規サーバーにデプロイすると既存の履歴がすべて実行されてしまう気がするのですが… イマイチよくわかっていなくてすいません 既存環境に影響を与えるため安易に試すこともできないのできちんと理解してから実行したいのです マイグレーション履歴は production, staging で個別にもっているのでコミットの中の履歴は消してしまっても問題ないのでしょうか…
dice142

2018/10/03 08:22

長くなるので回答に追記しましたが、用語等の使い方に齟齬が発生する可能性があるので、 一度追記内容をご覧いただけますでしょうか? その上で不明な点があれば(齟齬の発生を気にせず)お聞きいただければと思います。
退会済みユーザー

退会済みユーザー

2018/10/03 08:58

すいません Gem というのもよくわかっていなくて bundle install をすると Gem がいろいろインストールされるので 初期化処理をまとめたものと勝手に思っていましたがただのライブラリだったのですね… >初期データを作って新規環境で DB構築→初期データ投入 を行えば良いのではないですか? この部分を具体的にどうすればいいのかがわからないのです >DBの作成や構造など、テーブル操作含めDBにおける操作は基本的にmigrationファイルで行うべきです ということは初期化のためのマイグレーションファイルをSQLではなく ruby で作り直し、 開発リポジトリにはいれないで新規サーバーの db/migrate 以下にだけおいて rake db:migrate コマンドをうってDB構築→初期データ投入を行えばいいのでしょうか いずれにしろデプロイ時に開発リポジトリの db/migrate 以下に既存のマイグレーションファイルが有ると実行してしまうので、新規サーバーでだけ実行しないようにするには開発リポジトリ内のマイグレーションファイルを消すか、デプロイプロセスでターゲットを識別して手順をかえるためにCapistoranoに手を加えるしかないんでしょうか…
dice142

2018/10/03 09:10

> >初期データを作って新規環境で DB構築→初期データ投入 を行えば良いのではないですか? > この部分を具体的にどうすればいいのかがわからないのです DB環境の構築はmigrationファイルで、初期データ投入はseedファイルで行えるはずです。 > ということは初期化のためのマイグレーションファイルをSQLではなく ruby で作り直し、 > 開発リポジトリにはいれないで新規サーバーの db/migrate 以下にだけおいて rake db:migrate コマンドをうってDB構築→初期データ投入を行えばいいのでしょうか すみません、初期データのためのということであればseedファイルで作る方が適切かと思います。 seedファイルは`db/`に置き、`db:seed`で行うことになります。 > いずれにしろデプロイ時に開発リポジトリの db/migrate 以下に既存のマイグレーションファイルが有ると実行してしまうので、新規サーバーでだけ実行しないようにするには開発リポジトリ内のマイグレーションファイルを消すか、デプロイプロセスでターゲットを識別して手順をかえるためにCapistoranoに手を加えるしかないんでしょうか… 上記の回答の通り、初期データはseedファイルになるので既存サーバには影響しないと思われます。 ※既存サーバの環境や設定によっては影響が出る場合があります。  設定を見返したりDBのバックアップなど対処を忘れないようにしてください。
退会済みユーザー

退会済みユーザー

2018/10/03 09:21

>既存サーバには影響しない ではなく新規サーバーに既存のマイグレーションが実行されてしまう気がするのですが大丈夫なんでしょうか… 今開発リポジトリの db/migrate 以下にカラムを追加するマイグレーションファイルを置いてデプロイするとそれが反映されるので… すでに動作している既存環境のマイグレーション履歴が開発リポジトリの db/migrate 以下にあるので、新規サーバーにdb:seedで初期設定を行った後、プログラムの修正などでデプロイを行うと既存のマイグレーション履歴をすべて行ってしまわないか心配で これは自社のデプロイ環境が特殊で普通は migrate ディレクトリはリポジトリに含めないものなんでしょうか
dice142

2018/10/03 09:27

> ではなく新規サーバーに既存のマイグレーションが実行されてしまう気がするのですが大丈夫なんでしょうか… 既存のmigrationファイルが実行されないと同じテーブル環境が構成されません。 もしかして既存のmigrationファイルの中に、新規サーバで入れたくないデータをinsertしているものがあるという意味なのでしょうか? > プログラムの修正などでデプロイを行うと既存のマイグレーション履歴をすべて行ってしまわないか心配で このあたりがよくわかりません。 migrationファイルは別環境でも同じDB環境を構築できるようにするものなのですが、新規サーバで行われるとまずいmigrationファイルが有るということなのでしょうか? > 自社のデプロイ環境が特殊で普通は migrate ディレクトリはリポジトリに含めないものなんでしょうか いいえ、普通はどの環境でも同じDB環境を構築できるようにリポジトリに含めます。
退会済みユーザー

退会済みユーザー

2018/10/05 02:56

>もしかして既存のmigrationファイルの中に、新規サーバで入れたくないデータをinsertしているものがあるという意味なのでしょうか? db:seed のなかに初期構築用の create_table をかいたとして いままでのマイグレーションの中にも当然どこかに create_table ってあるはずですよね 2度実行されるのはまずくないんでしょうか create_table だったら単に already exist で失敗するだけだと思うのですが drop して create しなおすみたいなマイグレーションがあった場合まずいですよね いずれにしろ seed.rb だけで今と同じ MySQL のスキーマが完成するのであれば既存のマイグレーションを実行するのはさけたほうがいい気がするのですが superuser みたいな管理ユーザをインサートしてたりするとデータが重複したり上書きしたりするかもしれないし…
dice142

2018/10/05 04:11

seedの使い方を誤解していらっしゃるようです。 seedはテーブルの構築ではなく、データの挿入での利用になります。 migrationファイルと同じものを書くのではなく、migrationでDB構築が終わったあとに初期データを入れる手順としてseedを使います。
退会済みユーザー

退会済みユーザー

2018/10/05 04:18

つまりスキーマの構築には既存のマイグレーションを使う ということでしょうか そうなると >発生している問題 既存のマイグレーションは途中で手動で変更されたせいなのか一部マイグレーションに失敗します の問題があり既存のマイグレーションを流用できない事情があるのです なので既存のスキーマないしはMySQL自体から同じスキーマを構築することが必要になるのです>< これも固有事情になるのですよね…  申しわけありません
dice142

2018/10/05 09:09

あー、そうですね。 途中でマイグレーションが失敗する場合は ファイル自体を直すか、質問者様の仰るようにダンプして復旧になりそうですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問