Perl日記

日々の知ったことのメモなどです。Perlは最近やってないです。

MooseのBUILDARGSで

URIオブジェクト作るんだけど、プロパティとしても同じことができないかなんとかしたい。おお、何言ってるのか分からない。

package WWW::ImagePager;
use Any::Moose;
use URI;

has 'basepage' => (is=>'rw', isa=>'URI');

sub BUILDARGS {
  my ($self, %args) = @_;
  $args{basepage} = URI->new($agrs{basepage}); # ここと
  return { %args };
}

around 'basepage' => sub {
  my $orig = shift;
  my $self = shift;

  return $self->$orig() unless @_;

  return $self->$orig(URI->new(shift)); # ここが同じプロパティなのに
                                        # 同じ処理でかぶってる…
};

ただプロパティの値を途中で書き換えたいだけなのに…、えらい苦労。

use WWW::ImagePager;
my $imagepager = WWW::ImagePager->new(
  basepage => 'http://www.google.co.jp/',
);

$imagepager->basepage('http://www.yahoo.co.jp/');


うーん、is=>'rw'にしているのが問題なのかなぁ。でもここだけは書き換え可能にしたいところ。



※2011/7/5 追記
id:gfxさんからはてブコメントいただきました。いえっふーい!!

coerce使うのがいいんじゃないすかね。 e.g. https://gist.github.com/1063372

なんとぅぉー! そぉぅかー! coerceってなんかもっとこう、型チェックに使うイメージしか残ってなかったから使い方がよくわからないままモダパーで読み流してたところだったぜぃ!


さて。


書き直してみる。
とその前に、JPAの日本語資料読んでみた。(最初から読んどけって話ですよね、すみません)
Moose::Cookbook::Basics::Recipe5 Moose(0.92) - Japan Perl Association ドキュメント和訳プロジェクト


わざわざsubtypeを作る理由はなんだろうと思っていたので、丁度その回答にもなった。

ここではHTTP::Headersを直接型として利用するのではなく、サブタイプを作っています。これは、型変換はグローバルなものであるため、RequestクラスでHTTP::Headersの型変換を定義すると、同じPerlインタプリタ上でMooseを使っている「すべての」クラスで同じ型変換が定義されてしまうためです。このような名前空間の汚染は避けるのがベストプラクティス (Moose::Manual::BestPractices)です。

ほおなるほど。ここだけで使うならここだけで始末しろと。
隣の家の庭まで散らかすなと。

package WWW::ImagePager;
use Any::Moose;
use Any::Moose '::Util::TypeConstraints'; # 'subtype()', 'coerce()'

use URI;

my $subtype_uri = subtype __PACKAGE__.'::URI'
# => as 'URI';
  => as class_type('URI');

coerce $subtype_uri
  => from 'Str' => via { URI->new($_) };

has 'basepage' => (is=>'rw', isa=>$subtype_uri, required=>1, coerce=>1);

__PACKAGE__->meta->make_immutable; # return 1;

こんな感じでちゃんと動きました!
BUILDARGSもaroundもでぃふぁいあもこの目的には不用でした。
gfx!thx!