Разыменование файла в памяти, хранящегося в атрибуте Moose - PullRequest
2 голосов
/ 05 сентября 2011

Ниже приведен отрывок из некоторого кода, с которым я экспериментирую:

has buffer     => ( is => 'rw', isa => 'ScalarRef' );
has old_stdout => ( is => 'rw', isa => 'FileHandle' );

sub capture {
    my $self = shift;
    my $old_stdout;
    my $buffer;

    open $old_stdout, '>&', STDOUT
        or croak 'Cannot duplicate filehandle';

    close STDOUT;

    open STDOUT, '>', \$buffer
        or croak 'Cannot open filehandle';

    $self->old_stdout( $old_stdout );
    $self->buffer( \$buffer );
}

sub reset {
    my $self = shift;

    open STDOUT, '>&', $self->old_stdout
        or croak 'Cannot reset STDOUT';
}

В другом месте:

my $stdout = Capture->new();
print "Some output\n";
$stdout->reset();

print $stdout->buffer();
# SCALAR(0x#######)

print ${$stdout->buffer()};
# Some output

Я попытался обмануть, установив атрибут hashref напрямую - он работает, но мне не нравится это делать:

    open STDOUT, '>', \$self->{buffer}
        or croak 'Cannot open filehandle';

Я думаю, что мне здесь не хватает чего-то фундаментального. Как мне сохранить $buffer (файл в памяти) в качестве атрибута Moose, чтобы я мог получить его позже, не обращаясь к вызывающему объекту?

Обновление

Я добавил модификатор метода around, который добивается цели:

around 'buffer' => sub {
    my $orig = shift;
    my $self = shift;
    return ${$self->$orig} unless @_;
    $self->$orig( @_ );
};

... но это все еще кажется грязным. Есть ли лучший способ?

Ответы [ 2 ]

1 голос
/ 06 сентября 2011

Не меняйте значение buffer (как вы сделали с around), создайте новый метод доступа.

has buffer_ref => (
   ...
   handles => {
      buffer => sub {
         my $self = shift;
         if (@_) {
            ${ $self->buffer_ref }  = $_[0];
         } else {
            return ${ $self->buffer_ref };
         }
      },
   },
);
1 голос
/ 05 сентября 2011

Один из вариантов - сделать оба атрибута (buffer и old_stdout) закрытыми, добавив подчеркивание, а затем добавив простой метод для доступа к буферу извне:

sub buffer {
    my $self = shift;
    return ${$self->_buffer}
}

Выглядит также, что выпытается реализовать дубликат для Capture :: Tiny или аналогичного модуля.

...