4

Moose クラスの属性の Str を DBIx::Class::Row オブジェクトに変換したいと考えています。これを行うには、DBIC スキーマでルックアップを実行して行を見つける必要があります。ルックアップが失敗した場合、エラーを ArrayRef 属性にプッシュしたいと考えています。

現在、スキーマを属性としてクラスに渡しています。

強制すると、オブジェクトにアクセスできないように見えるため、エラー arrayref 属性にプッシュしたり、スキーマ オブジェクトを使用してルックアップを実行したりできません。

私が試した別の方法は、設定時に「around」を使用して属性を検索および設定することでしたが、これはもちろん、属性値がコンストラクターを介して渡されたときに呼び出されません。

これは可能ですか、または誰かが私が達成したいことを行うための代替実装を持っていますか?

4

1 に答える 1

4

属性初期化子を使用してコンストラクターに渡されたときに格納されている値をキャッチして変更できます。(ただし、属性がコンストラクターで設定されている場合にのみ実行され、それ以外のときは実行されません。)初期化子のドキュメントは、Class :: MOP::Attributeにあります。

これは、コンストラクターを介して属性が設定されている場合のみをキャッチするため、属性が設定されている他のケースをキャッチする必要があります。これは、あなたが言ったようにメソッド修飾子を使って行うことができますが、自動生成されたアクセサーをラップして、2つを1つのメソッドに組み合わせることができます。

has my_attr => (
    is => 'rw',
    isa => 'DBIx::Class::Row',
    initializer => 'my_attr',
);

# my_attr is the autogenerated accessor - we method-modify it to mutate the
# value being set, and catch cases where it is called as an initializer.

# called for reads, writes, and on initialization at construction time
around 'my_attr' => sub {
    my $orig = shift;
    my $self = shift;
    # value is not defined if being called as a reader
    # setter and attr are only defined if being called as an initializer
    my ($value, $setter, $attr) = @_;

    # the reader behaves normally
    return $self->$orig if not @_;

    # convert the string to the row object
    my $row = $self->convert_str_to_row_obj($value);

    # if called as an initializer, set the value and we're done
    return $setter->($row) if $setter;

    # otherwise, call the real writer with the new value
    $self->$orig($row);
};
于 2011-02-25T17:06:22.343 に答える