2012-10-09
Kappa の飼い方(Kappa という ORM の話) その6 Row オブジェクトのカスタマイズ
こんばんはこんばんは。
YAPC::Asiaも無事に終了しましたねー。
さて、YAPC でお話させていただいた、 Perl と SQL のいろいろ は公式サイトにプレゼン資料・動画ともどもアップされております!見たかったけど見逃した方はチェックすべし!(自分は恥ずかしくて動画みてないけどな!)
(※ここまでテンプレ)
Kappa という ORM の話。今日は Row オブジェクトのカスタマイズについてです。
目次
- その1 開発の背景のお話
- その2 インストールとかのお話
- その3 基本操作
- その4 select 系いろいろ
- その5 Row オブジェクトの基本
- その6 Row オブジェクトのカスタマイズ
- その7 テーブルクラスとそのカスタマイズ
- その8 雑多な話
- その9 SQL をテーブルクラスに置く
事前準備
テーブルを作っておきましょう。そういえば、SQLite には memory というエンジンがあります。(ファイル名を「:memory:」とする。) 終了時にデータが勝手に消えてくれるので、テストとかお試し用ならこっちのほうがいいかもしれませんね。
今回は2テーブル作ります。なお、設定上、1探偵1トイズという制限は無いと思われる(複数持っても良いと思われる) のですが、説明が面倒くさくなるので細かいことは気にしないで。
あ、ちなみに、トイズっていうのは、探偵(または怪盗)が持っているある種の超能力のことです。今回は名称のみデータとして持つことにします。
スキーマは分かりますよね? detective.toys_id = toys.id で結合します。
データも入れましょう。今回からテーブル構造変わった上、メモリ上にテーブルを作っているため、 前回入れた人もデータを入れる必要があります。
Row オブジェクトのカスタマイズの前に
アプリを作成する場合、どのようなソフトウェア構成にしていますか?
Web アプリでフレームワークを使っている場合は、フレームワークの規約にしたがうのが良いでしょう。 そうでない場合は、CPAN モジュールと同じレイアウトにしておくのがおすすめです。(なお、Web Application Framework を使う 場合も、大抵の場合 CPAN レイアウトになっているはずです。)
CPAN レイアウトを作るには、pmsetup とか Module::Starter とか Module::Setup とかそのへんのツールを使えば簡単にできます。 僕は Module::Setup を使っています。
さて、CPAN レイアウトを取っていると、プロジェクト(アプリケーション)で使うライブラリは lib というディレクトリに入れているかと 思います。カスタマイズした、Row オブジェクトも lib 配下に置くことになります。
Row オブジェクトの命名規則は、たとえばプロジェクト名が MyProj だとしたら、「MyProj::DB::Row::テーブル名」 みたいな感じにすると分かりやすくて よいのではないか、と思います。命名規則は、いつかまた解説すると思います。
カスタマイズ方法
では実際に Row オブジェクトのカスタマイズをします。プロジェクト名は仮に MilkyHolmes としておきましょうか。detective テーブルの Row オブジェクト を拡張します。
ファイル名でいうと、lib/MilkyHolmes/DB/Row/detective.pm。 パッケージ名でいうと、MilkyHolmes::DB::Row::detective となります。お気に入りの開発ツール (僕は emacs を使っています)で、ファイルを開きましょう。
Kappa は FK とかをみて、つながっているテーブルのデータを引っ張る機能とかがありません。(まあ今回の例では FK 張ってませんが) ですので、Row オブジェクトを拡張して、detective の Row オブジェクトから toys の name(トイズの名前)を引く、 toys_name というメソッドを付けてみましょう。
Row オブジェクトの db メソッドを呼ぶと、Kappa (呼び出し元)のオブジェクトが取れるのでした。 これを用いて、toys テーブルの行を取得し、toys.name の値を返しています。(なお、Kappa には透過キャッシュとかないので、 処理が重くなったり、重そうだったら必要に応じてキャッシュを入れる必要があります。)
カスタマイズした Row オブジェクトの使い方
このままでは、定義した Row オブジェクトを使うことができません。Kappa に Row オブジェクトがどこにあるかを教えてあげる 必要があります。Kappa の new にオプションとして、row_namespace というオプションをわたします。
こうすることで、Row オブジェクトの定義が 「MilkyHolmes::DB::Row::テーブル名」 にあることが Kappa さんに伝わります。
共通の Row オブジェクト
テーブルに依存せず、すべての Row オブジェクトに共通の処理を定義したい場合もあるかと思います。 Kappa は Row オブジェクトの定義を、
- 「row_namespace::テーブル名」 で定義された、テーブル名ごとの Row オブジェクト
- row_namespace
- Kappa::Row (基本機能)
の順に検索します。ですので、共通処理は row_namespace におきます。今回の例だと、 MilkyHolmes::DB::Row(ファイル名だと lib/MilkyHolmes/DB/Row.pm )におきます。たとえば CSVの出力ができるような csv_output というメソッドを付けてみましょう。
カスタマイズした Row オブジェクト(detective テーブルのもの)からも使えるように、親クラスを変更しておきます。
サンプル
動作するサンプルを作成しました。 bin ディレクトリの customized_row_object.pl が今回のサンプルです。lib/MilkyHolmes/Row 配下も実装してありますので、確認してみてください。
まとめ
今回は Row オブジェクトのカスタマイズ方法について解説しました。次回はテーブルクラスの拡張方法について解説します。 なんとなく、読者の方が Teng とか Skinny とか使っているのを想定して、先に Row オブジェクトについて解説しましたが、 実は Kappa においては、テーブルクラスのほうが重要です。(と、僕は考えています)
ではでは。また次回。