Catalystのclassとinstance
CatalystをデバッグOnで起動したときに最初の方にでてくる
.-------------------------------------------------------------------+----------. | Class | Type | +-------------------------------------------------------------------+----------+ | Traba::Model::DBISweet | class | | Traba::Model::Trackbacks | class | | Traba::Model::URLBL | instance | | Traba::View::RSS | instance | | Traba::View::TT | instance | '-------------------------------------------------------------------+----------'
これの右側のTypeがあるんだけど、この欄のclassかinstanceになるかは、Catalystの起動時のsetup_componentsで判定される。
判定に使われるのは、COMPONENTというクラスメソッド。ちなみに、上は暦トラバのもの。
Catalyst::Componentにはそれが実装されてる。中身的には、configをまとめてコンストラクタのnewを呼び出すというコード。
sub COMPONENT {
my ( $self, $c ) = @_;
# Temporary fix, some components does not pass context to constructor
my $arguments = ( ref( $_[-1] ) eq 'HASH' ) ? $_[-1] : {};
if ( my $new = $self->NEXT::COMPONENT( $c, $arguments ) ) {
return $new;
}
else {
if ( my $new = $self->new( $c, $arguments ) ) {
return $new;
}
else {
my $class = ref $self || $self;
my $new = { %{ $self->config }, %{$arguments} };
return bless $new, $class;
}
}
}
ということで、Catalyst::ComponentをベースとするModel/Viewは(おかしい事をしないかぎり)必ずinstanceになる。
上のリストにある、Traba::Model::URLBLはTrackbackスパムのチェックをするクラスで、id:miyagawaのKwiki::URLBLを参考にして、以下のような感じで実装されている。
package Traba::Model::URLBL;
use strict;
use warnings;
use base 'Catalyst::Model';
use NEXT;
use Net::DNS::Resolver;
use URI;
sub new {
my($class, $c, $config) = @_;
my $self = $class->NEXT::new($c,$config);
$config->{urlbl_dns} ||= [qw/sc.surbl.org bsb.spamlookup.net rbl.bulkfeeds.jp/];
$self->config($config);
return $self;
}
sub is_blocked {
my($self, $url) = @_;
my $uri = URI->new($url);
my $domain = $uri->host;
$domain =~ s/^www\.//;
my $res = Net::DNS::Resolver->new;
for my $dns (@{$self->config->{urlbl_dns}}){
my $q = $res->search("$domain.$dns");
return 1 if $q && $q->answer;
}
return;
}
1;