2013-12-19 8 views
0

У меня есть Moose :: Role, который содержит сетевой клиент в качестве атрибута:Изменения атрибуты :: Роли лосей во время выполнения

package Widget; 
use Moose::Role; 

has 'network_thingy' => (
    isa => Maybe[ThingyClient], 
); 

И, конечно, у меня есть несколько конкретных Музы классов, которые используют это должность:

package BlueWidget; 
use Moose; 
with 'Widget'; 

Теперь речь идет о функциональном тестировании виджетов. У нас есть возможность создавать объекты ThingyServer, и было бы намного быстрее и в целом превосходно напрямую использовать объекты ThingyServer вместо вращения демона и подключения ThingyClient к нему по сети. Так как ThingyClient & ThingyServer удобно имеет те же самые методы, это должно быть легко возможным. Но, конечно, Moose требует, чтобы я использовал ThingyClient, когда тест в конечном итоге конструирует BlueWidget.

Я провел некоторое исследование и наткнулся на документацию Moose :: Meta. Отлично! Так вот тестовый код:

my $metarole = Moose::Meta::Role->initialize('Widget'); 

// first remove the old attribute 
$metarole->remove_attribute('network_thingy'); 

Я собирался добавить новый атрибут, но я думал, что проверить состояние класса роли & первым. Теперь, если я сброшу $ metarole, он выглядит великолепно. Нет атрибута network_thingy. Но если я построить класс BlueWidget, или просто пик внутри метакласса ...

$metaclass = Moose::Meta::Class->initialize('BlueWidget'); 
diag Dumper ($metaclass); 

... Конечно же network_thingy все еще там. Это совсем не то, чего я ожидал. Как я могу изменить/удалить/заменить атрибут роли Widget во время выполнения?

ответ

2

Когда класс использует роль, атрибуты скопировали из роли в класс. Если вы затем измените атрибут в роли, то копия в классе не будет затронута.

Таким образом, вам нужно будет пройти через классы, которые использовали эту роль, и изменить атрибут в каждом классе. Существует метод consumers в Moose :: Meta :: Role, который может помочь вам получить список классов, которые поглотили эту роль, однако он охватывает только классы, которые имеют . потребляет эту роль, а не, скажем, подклассы этих.

Если классы были сделаны неизменными (__PACKAGE__->meta->make_immutable), вам нужно будет снова их изменить, прежде чем изменять атрибут.

В целом, возможно, лучше всего изменить модуль ролей (т. Е. Отредактировать файл); не пытайтесь настроить атрибут во время выполнения. Может быть, установить isa в ограничение типа duck_type?

Смежные вопросы