Как я могу получить доступ к метаклассу модуля, к моей роли Американского лося относятся?

CVS только отслеживает модификацию на основе файла файлом, в то время как SVN отслеживает целую фиксацию как новый пересмотр, что означает, что легче следовать истории Вашего проекта. Добавьте то, что все современное использование программного обеспечения управления исходным кодом понятие пересмотра, таким образом, намного легче мигрировать от SVN, чем он, от CVS.

существует также атомарная проблема фиксации. В то время как я только встретился с ним однажды, возможно, что 2 человека, фиксирующие вместе в CVS, могут конфликтовать друг друга, теряя некоторые данные и помещая Ваш клиент в непоследовательное состояние. Когда обнаружено рано, эти проблемы не являются главными, потому что Ваши данные все еще там где-нибудь, но это может быть боль в напряженной среде.

И наконец, не много инструментов больше разрабатываются вокруг CVS. В то время как новые и новейшие инструменты как Мерзавец или Подвижный определенно испытывают недостаток в инструментах все же, SVN имеет основу довольно крупного приложения в любой системе.

РЕДАКТИРОВАНИЕ 2015 : Серьезно, этому ответу 7 лет теперь. Забудьте SVN, пойдите Мерзавец использования как все остальные!

7
задан Ether 18 November 2009 в 22:14
поделиться

1 ответ

Похоже, что MooseX :: Role :: Parameterized поможет:

Обычные роли могут требовать, чтобы их потребители имели определенный список имен методов. Поскольку параметризованные роли имеют прямой доступ к своему потребителю, вы можете проверить его и выдать ошибки, если потребитель не соответствует вашим потребностям. (ссылка)

Подробная информация о специализации ролей скрыта от расширяемого класса; ему даже не нужно передавать какие-либо параметры, все, что ему нужно знать, - это то, какие параметры (список полей для переноса) передать роли. Единственный ключ заключается в том, что роль должна использоваться после того, как соответствующие атрибуты были определены в классе.

Следовательно, потребляемый класс и роль определяются следующим образом:

package My::Foo;
use Moose;

my @fields = qw(attr1 attr2);

has \@fields => (
    is => 'rw', # ...
);

has 'fields' => (
    is => 'bare', isa => 'ArrayRef[Str]',
    default => sub { \@fields },
);

with 'My::Role::X' => {};

1;

package My::Role::X;
use MooseX::Role::Parameterized;

role {
    my $p = shift;

    my %args = @_;

    # this should be a Moose::Meta::Class object
    my $target_meta = $args{consumer};

    # get Class::MOP::Attribute object out of the metaclass
    my $fields_attr = $target_meta->find_attribute_by_name('fields');

    # extract the value of this attribute - should be a coderef
    my $fields_to_modify = $fields_attr->default;

    # evaluate the coderef to get the arrayref
    $fields_to_modify = &$fields_to_modify if ref $fields_to_modify eq 'CODE';

    around $_ => sub {
        # ...
    } for @$fields_to_modify;
};

1;

Дополнение : Я обнаружил, что если параметризованная роль потребляет другую параметризованную роль, тогда $ target_meta во вложенной роли фактически будет мета-классом родительской роли (isa MooseX :: Role :: Parameterized: : Meta :: Role :: Parameterized ), а не мета-класс класса-потребителя (isa Moose :: Meta :: Class ). Чтобы получить правильный мета-класс, вам необходимо явно передать его в качестве параметра. Я добавил это ко всем параметризованным ролям в качестве шаблона «передового опыта»:

package MyApp::Role::SomeRole;

use MooseX::Role::Parameterized;

# because we are used by an earlier role, meta is not actually the meta of the
# consumer, but of the higher-level parameterized role.
parameter metaclass => (
    is => 'ro', isa => 'Moose::Meta::Class',
    required => 1,
);

# ... other parameters here...

role {
    my $params = shift;
    my %args = @_;

    # isa a Moose::Meta::Class
    my $meta = $params->metaclass;

    # class name of what is consuming us, om nom nom
    my $consumer = $meta->name;

    # ... code here...

}; # end role
no Moose::Role;
1;

Приложение 2 : Я также обнаружил, что если роль применяется к экземпляру объекта , в отличие от к классу, то $ target_meta в роли будет фактически классом объекта, выполняющего потребление:

package main;
use My::Foo;
use Moose::Util;

my $foo = My::Foo->new;
Moose::Util::apply_all_roles($foo, MyApp::Role::SomeRole, { parameter => 'value' });

package MyApp::Role::SomeRole;
use MooseX::Role::Parameterized;
# ... use same code as above (in addendum 1):

role {
    my $meta = $args{consumer};
    my $consumer = $meta->name;     # fail! My::Foo does not implement the 'name' method

Следовательно, этот код необходим при извлечении метакласса в начале параметризованной роли:

role {
    my $params = shift;
    my %args = @_;

    # could be a Moose::Meta::Class, or the object consuming us
    my $meta = $args{consumer};
    $meta = $meta->meta if not $meta->isa('Moose::Meta::Class');   # <-- important!
9
ответ дан 7 December 2019 в 03:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: