DBIC/Skinnyユーザ向けにDBIx::Skinny::Cookbookを書いてみた
メニー・クルシミマス!(挨拶
O/Rマッパも、好きなものをひとつだけ使っている分には便利でよいのですが、仕事で使わざるをえないO/Rマッパの数が増えていくにつれて、細々とした書き方の違いや挙動の違いに頭を悩ませることが増えていきます。スキーマの書き方、コネクトの仕方、クエリの組み立て方、値の取り出し方、あるいはクエリの飛ぶタイミングやキャッシュのされ方。愛用しているものならともかく、たまにしか使わないものまでいちいち覚えていられませんよね。
そんなときの助けになりそうなのが、DBIx::Cookbookです。これは、基本的にはDBIx::Classに付属のクックブックをベースに、特定の観点から見たO/Rマッパの流儀を――もう少し具体的にいうと、たとえば複雑なクエリを構築するときのやり方などを、DBICだけでなくほかのO/Rマッパのやり方も並べて紹介することで、その差を理解してもらったり移行や読み替えの手助けになることを期待して書かれたもの――なのですが、考え方には好感が持てるものの、実際にはDBIC以外の選択肢についてはほとんどフォローされていませんし(DBIx::SkinnyとRose::DBについては全件抽出のやり方が紹介されていますが、それ以外の機能についてはまったく記述がありません)、DBICについても標準添付のクックブックに書かれているものに比べるといかにも見劣りがします。また、MySQLデータベースへの接続情報はテンプレートを利用してモジュール内部に埋め込まれてしまうため、セキュリティ的にも難ありと言わざるをえませんし、現状はMANIFESTファイルに不足があるため、CPANインストーラからでは正常にインストールできないようになっています(試してみるにはgithubのリポジトリから最新版をcloneしてくる必要があります)。MySQLのサンプルデータベースとして使われているSakilaデータベースのデータやスキーマを再利用している点など、見るべきところも少なくないのですが、細々としたところでいくつも難があり、正直なところ、いまのままではおすすめしづらいし、パッチを送るより書き直した方が早そうでしたので、ひとまず仕組みの部分だけでも改善しようと、代替のモジュールを書いてみました。
DBIx::Skinny::Cookbookという名のそれは、いまのところgithubにしかありませんし、時間の都合でこれを書いている時点では複雑なクエリの組み方の一例しか紹介できていないのですが、DBIx::Cookbookから引き継いだ以下のような特徴があります。
- クックブックには同じ処理を行うためのコードがO/Rマッパごとに並べられるようになっています(現状ではDBICとSkinnyのみの対応ですが、ユーティリティモジュールを用意することでほかのモジュールにも対応できるようにしてあります)。
- クックブックに掲載したコードはそのままテストコードとして実行され、同じ項目のコードについては同じ挙動になることがコード的に確認できるようにしてあります。
- ただし、コマンドを実行するのに必要な枝葉末節については省略できるようにしてあります(実行時に適宜ユーティリティモジュールから不足しているコードを補完できるようにしてあります)。
- DBIx::Cookbookは実行可能なクックブックとして、コマンド経由で実行すると出力結果がダンプされるようになっているのですが、これについても(まだ実装していませんが)将来的には同等のものを用意するつもりです。
論より証拠というわけで、ひとまず動作確認のために書いた複雑なクエリを組み立てるコード例を掲載します。orの処理の仕方が微妙に異なっている点など、よく見比べてみてくださいませ(テストを実行すると、これに列抽出のコードなどを追加すると同じ結果を返してくることが確認できます)。
=head2 complex where =over 4 =item DBIx::Skinny =for Skinny my $rs = $db->resultset({ select => '*', from => 'dist', }); $rs->add_complex_where([ or => [ and => [ { name => { like => 'DBIx%' } }, { version => { like => '%7%' } }, ], ], { name => 'Test-UseAllModules' } ]); $rs->order({ column => 'name' }); =item DBIx::Class =for DBIC my $rs = $db->resultset('Dist')->search({ -or => [ -and => [ name => { like => 'DBIx%' }, version => { like => '%7%' }, ], name => 'Test-UseAllModules', ] }, { order_by => 'name', }); =back
将来的には、DBIx::Cookbook(ないしそれの大本になったのであろうDBIx::Class::Manual::Cookbook)にあって対応可能な項目をカバーできたらCPANにあげよう(というか、どなたかに譲って、あげていただこう)と思っていますが、SkinnyやDBICをお使いのみなさん、あるいはTengをはじめとするほかのO/Rマッパをお使いのみなさんでも、これは自分たちのO/Rマッパではこのように書く、というスニペットを提供していただけるようでしたら、ぜひgithubの該当リポジトリにpull requestなどいただければさいわいです。また、その他の要望等ありましたらirc.perl.orgの#dbix-skinnyチャンネルなどでお知らせください。