RubyもRailsも非常なる初心者によるRails雑感です。いろいろといい手を知っている人は教えてください(あくまでレールに乗れない、RubyもRailsも初心者である、という条件を加味して読んでください)。
既存データベースとの連携
複数スキーマをレールに乗ったまま扱うのは非常に困難があるようです。
Railsのデータベース設定は、development/test/productionと3つのデータベースを設定できるようになっています。
rakeというJavaでいうant/Djangoでいうmanage.pyのようなコマンドを実行すると、引数無しの場合はAll Testが走ります。All Testが走る際に、rakeはdevelopment環境のスキーマをtest環境にコピーしようと試みます。これは、「開発環境のデータベースにはよけいなデータが含まれていて、テストがしにくい」という問題と「開発環境とテスト環境のデータベースを分けると、管理が大変」という二つの問題をクリアするための動作だと推測することができます。予期しないデータが含まれていると通らないテストというものに疑問がないことはありませんが。。
しかし、Rails本や世の中のRailsブログを見ても、「スキーマをコピーする」という行為が何を意味するのかが記述されていません。実際に何をしてくれるのか。何度かトライしてみたところ次の表のような感じでした(本当はもっときちんと検証したい。でもRadRailsでデバッガがキャッチされないエラーを吐くもんだから時間がない)。
DBオブジェクト テスト環境へのコピー テーブル ダンプして、Create?
文字セマンティクスをchar設定しているUTF8のOracleデータベースの場合、きちんと開発環境のカラムサイズの4倍のサイズで非char設定してくれます。
ただし、4倍した際にvarchar2の最大値4000を超えるようなカラムが対象の場合は、ひそかに4000に設定します(エラーとはなりません)。
シーケンス テーブル名から自動で作成(開発環境のものは無視)
シノニム なにもしないけど、条件次第でデータを消す
ビュー なにもしない
たまに、存在するオブジェクト名ですというエラーをデータベースが返してくるので、既にテスト環境にコピー済みのオブジェクトをどこかで管理している可能性があります。また、fixtureというテストで利用するデータをテストで定義してある場合には、対象のテーブルのデータを全部削除します(条件無しのDELETE文)。
対象のテーブルデータを全部消してしまうので、スキーマ違いのテーブルをシノニムで対処してしまうとシノニムの参照先のデータが消されてしまいます。よって、テスト環境には手動でテーブルを作成、fixtureでデータを投入する必要があります。(開発環境のデータを使いたくてテスト環境を全部シノニムにしたら開発環境のデータが全部消されます。きっと)
ビューは更新が可能なものでなければ、シノニムをテスト環境で利用しても問題なさそうですが、テーブルのシノニムが利用できないので、やはり手動で開発環境と同期をとる必要があるでしょう。
スキーマが複数あり、かつ一部が既存のスキーマである場合は、Railsでレールに乗ることはできません。海外でも正規化された既存データベースとの相性の悪さは話題になっているようです。
規模が大きくなければなんとか対応が可能な範囲だと判断しましたが、テスト環境ではなく、開発環境でテストさせてくれてもいいんじゃないかとは思います。
DRYというかActiveRecordについて
Railsというと、ActiveRecordが有名で、プラスScaffoldで「データベースが変わっても全然問題ないよー。CRUD簡単だよー」というイメージがあります。
確かにスクリーンキャストを見たりしても、そんな雰囲気があります。
しかし、実際はモデルごとにバリデータを定義します。せっかく変数を書かず空っぽなActiveRecordの継承クラスに、書いていない変数名を指定してバリデータを定義します。
必須バリデータと、最大長指定バリデータを一つのカラムに対して指定するがあるとすると、書いていない変数名を2行に書く必要があります。
結局書くのであれば、DjangoやTurboGearsのようにモデルに変数(カラム)の型を指定する方がスマートな気がしますが。本番環境のmigrate用の記述もDRYとしては?