ぴよログ

↓に移転したのでこっちは更新されません、多分。

Rails x PostgreSQL db:seed用sqlを作る

移転しました →

今日から文体を常体にする。

データベースに最初からデータを入れておきたい場合、Railsではrake db:seedを使う。このタスクによりRailsアプリケーションがロードされた状態でdb/seeds.rbに書いたコードが実行される。

シード用データを作ること自体が重い場合(例えば外部のAPIを呼ばなければいけないとか、たくさんのjsonファイルを解析しなければいけないとか)、ローカルで流したスクリプトを再度プロダクション環境で流すのは馬鹿らしいので、ローカルのデータベースをダンプしたものを使うのが賢いのだと思う。

環境は次のものを想定する。

PostgreSQLではpg_dump dbname > dump.sqlpsql dbname < dump.sqlようなコマンドを使えるが、Herokuのような環境ではそれらのコマンドを直接叩けないことも多い。

そのためsqlファイルのインポートはActiveRecord経由で行うこととする。

# db/seeds.rb
sql = open(File.join(Rails.root, "db", "seeds.sql")).read
ActiveRecord::Base.connection.execute sql

seeds.sqlというダンプファイルをリポジトリに含めてき、rake db:seedでダンプファイルをインポートをするだけ。

あとはこのコードが読めるダンプファイルを書き出せばいい。

pg_dump

pg_dumpの詳しいことは触れないが、基本的にはデータベースを指定して実行するとダンプしてくれる。

% pg_dump mydatabase > seeds.sql

このコマンドではスキーマとデータ自体が両方出力されるが、このダンプファイルは使えない。結論から言うとpg_dumpコマンドには次の2つのオプションをつける。

% pg_dump mydatabase --data-only --inserts > seeds.sql

--data-only

--data-onlyオプション(または、-aオプション)でデータのみをダンプできる。Railsではデータベースのスキーマはrakeタスクで管理するため、ダンプファイルにスキーマは不要。

--inserts

このオプションにより、ダンプファイルのフォーマットをINSERT文を使ったものにできる。指定がない場合はCOPYを使ったものになるが、ActiveRecordから実行できない。

微調整

ファイルフォーマット的にはここまでの作業で問題なくなったが、余計なデータが一種類入っている。それはschema_migrationのデータだ。

ダンプしたファイルを覗くと、INSERT INTO schema_migrations VALUES ('20140513040222');といった行があるのがわかる。この情報はrake db:migrateを実行したときにRailsが入れてくれるデータで、同じデータをINSERTするとエラーとなってしまう。そのため、これらの行を削除する必要がある。

seeds.sqlが完成したので、このファイルをリポジトリにaddしてcommitする。

あとはHerokuにデプロイして、データベース周りのタスクを実行すればよい。コマンドで言うと次のコマンドとなる。

  1. git push heroku
  2. heroku run rake db:migrate
  3. heroku run rake db:seed