2015-02-03 5 views
2

У меня есть модуль, который отказывается загружать, если не выполняется проверка соответствия времени компиляции. Что-то вроде этого:Проверка работоспособности во время компиляции, предоставляемая ролью

package TopSecret; 
use Moose; 

die "Only Joe can use this!" unless $ENV{USER} eq 'joe'; 

1; 

Теперь я хотел бы применить подобную проверку вменяемости на несколько модулей, так что моя мысль поставить его в роли. Модуль-потребитель предоставит некоторую информацию для настройки проверки. Так что это может выглядеть примерно так:

package TopSecret; 
use Moose; 
with 'ForAuthorizedUser'; 

sub authorized_user { 'joe' } 

1; 

Проблема: как я могу осуществлять TopSecret :: authorized_user() из ForAuthorizedUser, во время компиляции? Что-то вроде «требует» authorized_user », за исключением того, что ему нужно будет проверить не только, что метод существует, но и выполнить его и проверить возвращаемое значение.

ответ

1

Я думаю, что здесь будет уместно переопределить атрибут. Вы объявляете атрибут в своей роли и отмечаете его по мере необходимости, но не предоставляете определение. Затем модуль, который потребляет роль, может предоставить значение для этого атрибута. Обратите внимание, что проверка обычно выполняется в подпрограмме BUILD().

package ForAuthorizedUser; 
use Moose::Role; 

use Carp qw(croak); # so you can see the line it fails on 

has 'authorized_user' => (
    is  => 'ro', 
    required => 1, 
); 

sub BUILD { 
    my ($self) = @_; 

    croak "Only Joe can use this!" 
     unless $self->authorized_user eq 'joe'; 
} 

1; 

Теперь в вашем модуле, который потребляет ForAuthorizedUser, вы поставляете определение атрибута:

package TopSecret; 
use Moose; 
with qw(ForAuthorizedUser); 

has '+authorized_user' => (
    default => 'joe', 
); 

__PACKAGE__->meta->make_immutable; 

В отдельном модуле вы делаете то же самое, но с другим именем (шахтной):

package TopSecret2; 
use Moose; 
with qw(ForAuthorizedUser); 

has '+authorized_user' => (
    default => 'hunter', 
); 

__PACKAGE__->meta->make_immutable; 

Тогда вы могли бы проверить это следующим образом:

use TopSecret; 
use TopSecret2; 

TopSecret->new; # lives 
TopSecret2->new # croaks Only Joe can use this! at constructor TopSecret2::new (defined at Test.pm line 35) line 36. 
+0

Nice; Мне нравится предоставлять метод BUILD в роли. Я не думаю, что этот _quite_ решает всю проблему, потому что проверка работоспособности не выполняется до создания экземпляра объекта, что может не произойти (что, если класс использует TopSecret, но только вызывает методы класса, например?) Может существовать соглашение о вызове TopSecret-> новый в любом классе с использованием TopSecret, но есть ли способ заставить роль каким-то образом заставить это? – gcbenison

+0

Я понимаю, что вы имеете в виду. Я не уверен, что есть хороший способ ограничить это. #moose на irc.perl.org может быть лучше. –

+0

Единственное, о чем я могу думать, это то, что вы предоставляете ['before'] (https://metacpan.org/pod/distribution/Moose/lib/Moose/Manual/MethodModifiers.pod#Before-and-after- Модификаторы) для каждого из ваших методов класса, который проверяет, разрешен ли пользователь. –