Ответы пользователя по тегу Perl
  • Perl, Moose, обработка атрибутов

    zdm001
    @zdm001
    has 'page'  => (is => 'rw', isa => 'Str');
    has '_page' => (is => 'rw', isa => 'Str', lazy_build => 1);
    
    sub _build__page {
        my $self = shift;
        return $self->{page} =~ s/^.+\/(.+)$/$1/r;
    }
    
    around 'page' => sub {
        my $orig = shift;
        my $self = shift;
    
        if (@_) {
            $self->$orig(@_);
            $self->_clear_page;
        }
        return $self->_page;
    };
    


    Так, как у тебя, тоже нормально.
    Ответ написан
    1 комментарий
  • Perl, Moose, обработка атрибутов

    zdm001
    @zdm001
    В билдере ошибка, надо:

    return $self->{page} =~ s/\///gr;

    модификатор r обязателен к регэкспу, чтобы вернулся результат замены, а не кол-во произведенных замен
    Ответ написан
  • Perl, Moose, обработка атрибутов

    zdm001
    @zdm001
    оптимизированный around:

    if(@_){
    $self->_clear_page;
    $self->$orig(@_); #проксируем на оригинальный метод только если значение устанавливается
    }
    return $self->_page;
    Ответ написан
    Комментировать
  • Perl, Moose, обработка атрибутов

    zdm001
    @zdm001
    Через триггер значение менять нельзя, он вызывается после установки значения. Можно только понять, было значение изменено или нет.
    Если в триггере обратиться к $self->page('xxx') — будет бесконечная рекурсия.
    Нужно так в триггере: $self->{page} = 'xxx' — это прямое обращение к аттрибуту класса в perl, минуя модификаторы методов Moose. В этом случае рекурсии не будет, т.к. триггер не вызовется второй раз сам из себя.

    Можно делать только через around, он сработает в любом случае, когда ты будешь получать значение аттрибута. Тогда в around нужно будет каждый раз делать подстановку при получении значения или завести отдельный метааттрибут, в котором хранить флаг — обработона значение или нет…

    Других путей нет, из new модификаторы не вызываются, в этом все дело.

    Можно еще так:)))
    Завести доп. аттрибут _page и в нем хранить измененное значение. Сделать его lazy_build => 1.
    Создать билдер _page:
    sub _build__page {
        my $self = shift;
        return $self->{page} =~ s/\///g; #именно так, чтобы не возникало рекурсии при вызове из around ниже
    }
    


    В around к page:
    if(@_){ #если устанавливаются параметры - очищаем _page, чтобы при следующем обращении вызвался его билдер
        $self->_clear_page;
    }
    $self->$orig(@_); #проксируем на оригинальный метод
    return $self->_page;#если мы меняем значение - будет вызван билдер для _page, его результат сохранится в _page и вернется, если не меняем вернется значение _page, которое там было раньше, второй раз код подмены для одного и того-же значения выполнятся не будет
    


    Это самый элегантный вариант.
    Ответ написан
    Комментировать
  • Perl, Moose, обработка атрибутов

    zdm001
    @zdm001
    1. сразу обработать значение аттрибута, установленное через конструктор (new), можно только в методе BUILDARGS (получаем доступ к хешу аттрибутов перед созданием объекта) или BUILD (обрабатываем аттрибуты сразу после создания объекта), модификаторы методов (before, around, trigger) не вызываются при установке аттрибута в конструкторе;
    2. можно использовать trigger (вызывается, когда устанавливается значение);
    3. можно использовать around, при каждом вызове проверять и изменять значение, если надо;
    Ответ написан