rake db:create と createdb.bat

新しい Railsアプリケーションを作った際、データベースはどうやって作ろうか。折角 rake db:create (と、db:drop) があるので使いたいのだが、手元の環境ではエラーになる

C:/Program Files/ruby-1.8/bin/rake: No such file or directory - createdb "<アプリケーション名>_development" -E utf8

手元の Windows機に PostgreSQL(クライアント)を入れてないから当たり前なんだが、createdb がないわけだ。
なら、所要のデータベースサーバまで出かけていって createdb, dropdb するのを作ってしまおう。下記二つのバッチファイルを、パスも通っていることだし、rails の bin ディレクトリに作成する。
createdb.bat

"c:\Program Files\PuTTY\plink.exe" <DBホスト名> createdb %*

dropdb.bat

"c:\Program Files\PuTTY\plink.exe" <DBホスト名> dropdb %*

これで、rake db:create と、db:drop 共に動くようになる。
ここで plink.exe は、sshクライアントソフト PuTTY 付属の遠隔コマンドソフト。

db:create (db:drop) とローカルDB

動くようになったから良いのだけど、DBホストは config\database.yml にも書いているのでどうしたもんかな。と、調べて行くと、この二つの Rakeタスクが想定するのはローカルホストでの DB操作のようだ。

C:\Documents and Settings\[云々]>rake -T db:create
(in C:/Documents and Settings/[云々])
rake db:create      # Create the database defined in config/database.yml for the current RAILS_ENV
rake db:create:all  # Create all the local databases defined in config/database.yml

C:\Documents and Settings\[云々]>rake --tasks db:drop
(in C:/Documents and Settings/[云々])
rake db:drop      # Drops the database for the current RAILS_ENV
rake db:drop:all  # Drops all the local databases defined in config/database.yml

説明に local と明記されてるのは :all系のものだけど、
C:\Program Files\ruby-1.8\lib\ruby\gems\1.8\gems\rails-2.0.2\lib\tasks\databases.rake を見る限りでは、db:create, db:drop もローカルデータベースしか想定していない。
しかし、今扱っている手元の環境では、データベースは近在の PostgreSQLサーバを見に行くように想定している。config\database.yml には host:項設定してあるのだからちょっと見てくれてもいいのに。
config\database.yml の host: 設定を活かすようにするとしたらこんな感じかな。やらないけど。

  1. 上記 databases.rake の修正
    • :all系は儘でいいとおもう
    • :create と :drop は config['host'] を見るようにする
      • host項がなければ儘、あれば「-h <ホスト名>」オプションも追加
      • :create と :drop で修正すべき場所がちょっと違うのに注意。:create は自信のタスク定義のなか、:drop はそこで使ってる drop_database(config)プライベートメソッド。
    • その辺のメソッドの書き方のリファクタリングもした方がいいのだろうか。
    • 何れにせよ、postgresqlアダプターの場合ですね。
  2. バッチファイルは同じベースネームの .rb を呼ぶ(ruby で実行する)様にする、引数を引き継ぐ。
    • "%~dp0ruby.exe" "%~dpn0.rb" %*
    • こんな感じ。rails.bat と違って、拡張子無しの rubyファイルにしないのは、拡張子なしのファイルがあると、rake task がそっちを呼んでしまうから (そしてなにかのエラーになる、Exec format error)
  3. その .rbファイル
    1. 引数にホスト指定があるかどうか識別 (optparse 使う ?)
    2. なければローカルで
    3. あったらそのホストに、plik.exe なり、或いは Ruby自身のリモート機能で出かけていって所用の DB操作する