How to instantiate value from attribute metadata with Moose?

I am working on a serialization tool using Moose to read and write a file that conforms to a custom format. Now I am defining how to load the next element based on the default values โ€‹โ€‹for objects in the class, but it has its drawbacks. Instead, I would like to use the information in the attribute metaclass to generate a new value of the correct type. I suspect there is a way to determine what the isa constraint is and get a generator from it, but I have not seen any special methods in Moose :: Meta :: Attribute or Class :: MOP :: Attribute that could help me.

Here is a little more example. Let's say I have the following class:

package Example;
use Moose;

use My::Trait::Order;
use My::Class;

with 'My::Role::Load', 'My::Role::Save';

has 'foo' => (
    traits => [ 'Order' ],
    isa => 'Num',
    is => 'rw',
    default => 0,
    order => 1,
);

has 'bar' => (
    traits => [ 'Order' ],
    isa => 'ArrayRef[Str]',
    is => 'rw',
    default => sub { [ map { "" } 1..8 ] }
    order => 2,
);

has 'baz' => (
    traits => [ 'Order' ],
    isa => 'Custom::Class',
    is => 'rw',
    default => sub { Custom::Class->new() },
    order => 3,
);

__PACKAGE__->meta->make_immutable;
1;

( : My::Role::Load My::Role::Save . , , . )

My::Role::Load , , :

package My::Role::Load;
use Moose;    

...

sub load {
    my ($self, $path) = @_;

    foreach my $attribute ( $self->meta->get_all_attributes ) {
        if (does_role($attribute, 'My::Trait::Order') ) {
            $self->load_attribute($attribute) # do the loading
        }
    }
}

isa , -. , , - :

use 5.010_001; # need smartmatch fix.
...
sub load_attribute {
    my ($self, $attribute, $fh) = @_;
    my $value = $attribute->get_value($self); # <-- ERROR PRONE PROBLEM HERE!
    if (ref($value) && ! blessed($value)) { # get the arrayref types.
        given (ref($value)) {
            when('ARRAY') { 
                $self->load_array($attribute);
            }
            when('HASH') {
                $self->load_hash($attribute);
            }
            default {
                confess "unable to serialize ref of type '$_'";
            }
        }
    }
    else {
        when (\&blessed) {
            confess "don't know how to load it if it doesn't 'load'."
                if ! $_->can('load');
            $_->load();
        }
        default {
            $attribute->set_value($self, <$fh>);
        }
    }
}

, # <-- ERROR PRONE PROBLEM HERE!, , ! undef, . $attribute->get_value($self) , . , , Class::MOP::Attribute Moose::Meta::Attribute, , , .

, .

( : , . Moose::Meta::TypeConstraint, , .)

+3
3

, , , , , , ?

isa:

{
    package Foo;
    use Moose;

    has 'bar' => ( isa => 'Str', is => 'rw' );
}


my $foo = Foo->new;

say $foo->meta->get_attribute('bar')->type_constraint;   # => 'Str'

/I3az/

+3

, / MooseX:: Storage? . MooseX:: Storage , , ( ) Moose.

+2

, (, - , , ), , , : (isa => 'MySerializer', handles => [ qw(methods) ]).

, Moose::Meta::Class (, , ), add_attribute().

: Moose::Meta::Attribute ( , _process_options), , isa Moose::Util::TypeConstraints, , type_constraint . Moose::Meta::TypeConstraint::Class , , , is_a_type_of().

type_constraint Moose:: Meta:: Attribute. . Moose::Meta::TypeConstraint .

+1
source

Source: https://habr.com/ru/post/1726917/


All Articles