ラベル Class::DBI の投稿を表示しています。 すべての投稿を表示
ラベル Class::DBI の投稿を表示しています。 すべての投稿を表示

2005年9月12日月曜日

Class::DBI 3.0.1の中身は0.96

MFPMのRecent MailでClass::DBIが3.0.1にバージョンアップしたことを知りました。

search.cpan.org: Tony Bowden / Class-DBI-3.0.1

早速何が変わったのかChangesを見てみると、、

>

3.0.1 UNRELEASED

- Code is identical to 0.96
- New section added to documentation on Release Philosophy
- Replace eq_set with is_deeply in t/04 to work around Test::More bug

3.0.0 UNRELEASED

- IDENTICAL to 0.96. Only difference is version renumbering.
<

ということで、中身は0.96と同じで、バージョンを付け直しただけみたいです。
これから大きなバージョンアップを行う下準備というところでしょうか。



2005年8月17日水曜日

Class::DBI::Sweet

CDBIのメーリングリストを眺めていたら、複数のテーブルにまたがった検索なんかをClass::DBI::Sweetを使えば簡単にできるよみたいな投稿があったので、マニュアルを眺めてみましたが結構いろいろできそう。
ざっと見た感じ

-Class::DBI::PagerのようなData::Pageを利用したページング
-Class::DBI::Plguin::CountSearchでできるようなカウント検索
-SQL::Abstractを使った複雑な検索
-JOINを使った検索
-retrieve_allでorder_by
-キャッシング機能

といったようにかゆいところに手が届く機能が満載です。
それぞれの機能は個別のプラグインとしてだいたいCPANにアップされてますが、これひとつですべて住むってのは便利かも。




2005年8月1日月曜日

Class::DBIの開発が大変なことになっている模様。。

Class::DBIの作者が最近立ち上げたメーリングリストを削除、さらに、アーカイブとWikiも削除してしまったそうです。
そろそろ1.0のリリースかなんて思っていたので、かなりの衝撃です。。
今後の動向に注目です。

via:Class::DBI の開発でトラブル: blog.bulknews.net



2005年7月8日金曜日

Class::DBI::Plugin::Factory

昨日書いたselectトリガを使ったClass::DBIのFactoryパターンLost-SeasonのkatoさんがClass::DBIのプラグインにしてらっしゃいます。仕事はやっ!

ちなみに、Class::DBIのFactoryの実装方法について、インスタンス生成専門のFactoryクラスを別に作るという方法も考えたんですが、この実装方法だと、retrieve_allやsearchなどのリスト取得系の検索メソッドでインスタンスのリストを取得する際にサブクラスのインスタンスを生成ってところまでは感知できないので、やめにしました。


2005年7月7日木曜日

selectトリガを使ったClass::DBIのFactoryパターン

以前からClass::DBIでFactoryパターンを使えたらなーと思ってました。
たとえば、有料、無料、VIPのように複数の会員タイプがあるような会員サイトを作る場合、Class::DBIを継承したMyService::MemberがFactoryとなり、会員のタイプによって、MyService::Member::Basic, MyService::Member::Free, MyService::Member::VIPというようなサブクラスのインスタンスを作成するというようなイメージです。
さらにFactoryクラスでMyService::Member->retrieve_allとかすると、適切なサブクラスのインスタンスのリストがとれると最高です。

そんなことができないかなーとClass::DBIのドキュメントやソースを眺めていたんですが、Class::DBIに組み込まれているselectトリガを使えば実現できそうだったので、試してみました。
selectトリガはインスタンス生成時に必ず呼ばれているので、ここで会員のタイプを判別し、サブクラスにreblessしてやります。ソースコードはこんな感じです。このコードそのままではないですが、実際に同じようなコードを書いて試してみたところ、うまく動いているようです。

***MyService::Member - Factory
>

package MyService::Member
use base qw(Class::DBI);

require MyService::Member::Basic
require MyService::Member::Free
require MyService::Member::VIP

__PACKAGE__->set_db('Main', @datasource);
__PACKAGE__->table('member');
__PACKAGE__->columns(Primary => qw(member_id));
__PACKAGE__->columns(Essential => qw(member_type name age));

# select トリガにrebless用のメソッドをセット
__PACKAGE__->add_trigger( select => \&_rebless );

# サブクラスにrebless
sub _rebless {
my $self = shift;
#会員タイプ(member_type)でreblesするサブクラスを選択
my $class = 'MyService::Member::Basic';
if ($self->member_type eq 'Free'){
$class = 'MyService::Member::Free';
} elsif($self->member_type eq 'VIP'){
$class = 'MyService::Member::VIP';
}
bless $self, $class;
}

# abstract method
sub is_free {}
sub monthly_cost {}
<

*** MyService::Member::Basic - 一般会員
>

package MyService::Member::Basic;
use strict;
use base qw(MyService::Member);

sub is_free { 0 } # 無料ではない
sub monthly_cost { 500 } # 月額500円
<

*** MyService::Member::Free - 無料会員
>

package MyService::Member::Free;
use strict;
use base qw(MyService::Member);

sub is_free { 1 } # 無料
sub monthly_cost { 0 } # 月額0円
<

*** MyService::Member::VIP - VIP会員
>

package MyService::Member::VIP;
use strict;
use base qw(MyService::Member);

sub is_free { 0 } # 無料ではない
sub monthly_cost { 250 } # VIPは月額250円
<



2004年12月27日月曜日

Class::DBIとApache::ReloadでInternal Server Error

mod_perlで動作するアプリケーションを開発する場合、更新されたモジュールをリロードしてくれるApache::Reloadのようなモジュールを利用するのが一般的だと思いますが、Apache::Reloadが有効になっている状態でClass::DBIを継承したモジュールを更新すると以下のようなエラーメッセージをはいてInternal Server Errorになるという現象に悩んでました。

>

[Sun Dec 26 20:06:02 2004] [error] Can't use an undefined value as a HASH reference
at /usr/local/perl-5.8.5/lib/site_perl/5.8.5/Class/DBI/Relationship/HasMany.pm line 51.\n
Compilation failed in require at /usr/local/perl-5.8.5/lib/site_perl/5.8.5/Apache/Reload.pm line 140.\n

<

そこで少し調べてみると、Re: Apache::Reload and CDBI won't play togetherに次のような記述が。

>
Class::DBI prevents you from overwriting already declared methods. To
fix this, you would need to hack Apache::Reload to clear the symbol
table of your package just before reloading it, or hack Class::DBI to
ignore overwriting subs.
<

Class::DBIはすでに宣言されているメソッドの上書きをさせないのが原因で、これを回避するには、リロードされる前にシンボルテーブルをクリアするようにApache::Reloadをhackするか、上書きを無視するようにClass::DBIをhackしろということのようです。

そこで今回は開発環境でしか使わないApache::Reloadをhackし、パッチを書いてみました。(Class::DBIに比べてApache::Reloadはコードの量が少ないのでhackが簡単。)

>

--- Reload.pm.orig 2004-12-26 19:35:31.000000000 +0900
+++ Reload.pm 2004-12-26 20:22:40.000000000 +0900
@@ -122,6 +122,14 @@
}

if ($mtime > $Stat{$file}) {
+ my $package = $key;
+ $package =~ s/\//::/g;
+ $package =~ s/\.pm$//;
+ if ( UNIVERSAL::isa($package, 'Class::DBI') ){
+ no strict 'refs';
+ warn "Apache::Reload: clear the symbol table of $package\n" if $DEBUG;
+ %{"$package\::"} = ();
+ }
delete $INC{$key};
# warn "Reloading $key\n";
if (my $symref = $UndefFields{$key}) {
<