■2011-06-08
* [Perl] ORM的なものでLEFT JOINしたカラムの値をRowオブエジュクトにまとめる
タイトルが意味不明ですが。DBIx::Skinnyなどを使っててhas-manyな関係のデータをLEFT JOINしたりします。するとまあJOINで掛け合わせた分、Rowオブジェクトが複数個返ります。
# 著者authorと著作bookがhas-manyな関係だとして
# SELECT a.id, b.id AS book_id, b.title AS title
# FROM author a JOIN book b ON a.id = b.author_id
# WHERE ...
... なんか色々あって
my $itr = $skinny->search_by_sql(...);
# この$itrを回すとbook_idとtitle以外
# (つまりid)は同じデータ
while ( my $author = $itr->next ) {
# $author->id, $author->book_id, $author->title
# 同じ 別 別
}
で、has-manyな部分はリストにまとめて、Rowオブジェクトはプライマリキー分だけ欲しいと思うことがあります。
# こんな感じになると嬉しい
$author = $itr->first;
my $books = $author->{ books };
for my $book ( @$books ) {
# $book->{ id }, $book->{ title }
}
そういうモジュールがCPANにないかと探したのですが見つからなかったので自作して使ってました。で、この部分の機能をDBIx::JoinedColumnsAggregatorという名前で切り出してみました。aggregate_joined_columnsという関数がエクスポートされますのでイテレータ(リストリファレンスでもよいよ)とオプションを渡します。
use DBIx::JoinedColumnsAggregator;
# ...
my $itr = $skinny->search_by_sql(...);
my $authors = aggregate_joined_columns( $itr, {
pk => ['id'],
tags => {
books => ['book_id','title'],
},
} );
my $author = $authors->[0];
my $books = $author->{ books };
# ...
プライマリキー毎に代表されたRowオブジェクトだけを返します。そして各Rowオブジェクトに、まとめあげたリストをつっこみます(デフォルトでtagsで指定したキーのハッシュエントリに保存されますが、setterオプションにsubrefを渡せば任意に変更可)。DBIx::SkinnyやTengで使うのを念頭に置いてますが、普通にDBI等でも使えます。
use DBI;
use DBIx::JoinedColumnsAggregator;
my $dbh = DBI->connect( 'dbi:SQLite:your_data', '', '' );
my $sth = $dbh->prepare( ... );
$sth->execute();
my $list = aggregate_joined_columns( $sth, {
pk => ['id'],
tags => {
books => ['book_id','title'],
},
access_style => 'hash',
next_method => 'fetchrow_hashref',
} );
■2011-06-27
* [Perl][近況] Hachioji.pm #6
先週末は7回目のHachioji.pmでした。今回は遅刻しないはずだったのですが……なぜか遅刻しました、すいません。一次会はみんなでカレーを呑む。なんでもHachioji.pmはPMなのにPerlの話が全然ないじゃないかという匿名のクレームがきたとか。なんか私はPerl担当らしいので今後はもう少しPerlの話をするようにしてみます。でも今回のLTはPerlの話を少しやったよ! 二次会はいつものタイ料理屋さんでLT。テーマは「省エネ・エコ」。
umeyukiさん:東京電力の「おトクなナイト」の紹介。昼3割増、夜7割引の電気料金割引サービスですって! 夜型人間にはお勧めかも。
mgikenさん:プログラムは夜やってるから節電気にしないよ! はじめてのGANCアプリ。それとGANCの勉強会やりたいなと。
toku_bassさん:エコのためLTなし
partynight12thさん:エコだからLTなし
yasakawaさん:LTないのがエコ。職場扇風機も止めたよ。えー
ytnobodyさん:バッドノウハウはエコの母。Web::Scraperは便利。でもモジュールいっぱい使っててエコじゃない。→正規表現(regexp)でいいじゃん。
nekoyaさん:URI::Escapeは重いからURI::Escape::XSいいよ!
okamuuuさん:プログラミングはエコ。MVVMモデルのフレームワークknockout.jsの紹介。
shinpei_cmykさん:DBサーバのお引っ越しをどうする?という問い。nekoyaさんからレプリケーションでよくね?という提案。
hide_o_55さん:PerlでGroongaをゴニョゴニョするためのラッパー、App::Groonga::Wrapper。
norry_gogoさん:エコなソフトウェア開発の三本柱:バージョン管理、テスティング、自動化!
uzullaさん:UPSと自動車のバッテリーで停電対策。Firefoxはエコ。PHPにビルトインwebサーバが入る。Cloud9 IDEでwebブラウザエディッタ。gitも使えるよ。
hirobanexさん:今回のテーマの言い出しっぺ。なんだけど残念ながら参加できず。ということでPerlモジュールFurlから学ぶ省エネコーディングを事前に書いてくださいました。
私の発表は「私の省エネ術」。「LTやらないのが省エネ」→「でも誰でも真っ先に思い付くので実行したら負けかな 」というわけで、「LT発表しない」×「LT発表する」のAcme合体を成し遂げました。
具体的にはA4の紙を16分割した小片に2枚当たりくじをいれます。参加者に引いてもらいます。当たった人が私の代わりにLTを行います。nekoyaさんが「省エネカレー」について、hide_o_55さんが「高尾山と天狗」について私の代わりに大いに語る権利を見事獲得しました。本当にごめんなさい!
あと夏に向けてのプレゼント「クーラーを使わず夏を涼しくする方法」も紹介しました。
# cooler.pl
use strict;
use File::Remove qw(remove);
# @boxに1個だけ大事なディレクトリを入れておこう
my @box = qw(
/home/foobar/src
/home/foobar/dummy
/tmp/foobar
/usr/dodemoii/foobar
/usr /mydummy/path
);
remove( \1, $box[ rand(@box) ] );
cronかなんかで1時間に1回まわしてれば、ヒヤヒヤするよ!
というわけで次回はいよいよTakao.mt(Hachioji.pm #7)。高尾マウンテンかつミーティング。青空ハッカソンあり(有志のみ)、青空輪読勉強会あり(有志のみ)、青空LTあり(有志のみ)で夕方はビールという素敵なイベントです! 高尾の山でエンジョイ!

