今日から文体を常体にする。
データベースに最初からデータを入れておきたい場合、Railsではrake db:seed
を使う。このタスクによりRailsアプリケーションがロードされた状態でdb/seeds.rb
に書いたコードが実行される。
シード用データを作ること自体が重い場合(例えば外部のAPIを呼ばなければいけないとか、たくさんのjsonファイルを解析しなければいけないとか)、ローカルで流したスクリプトを再度プロダクション環境で流すのは馬鹿らしいので、ローカルのデータベースをダンプしたものを使うのが賢いのだと思う。
環境は次のものを想定する。
- PostgreSQL
- Heroku
PostgreSQLではpg_dump dbname > dump.sql
やpsql 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にデプロイして、データベース周りのタスクを実行すればよい。コマンドで言うと次のコマンドとなる。
git push heroku
heroku run rake db:migrate
heroku run rake db:seed