Break construction objects from separate arguments

I have been working with Moose for about seven months, and Perl is a little longer, but I can’t understand how you can build several attributes in a class by simply placing one argument for each, and not on a whole hash file. I searched the documentation and the web many times site, but I either searched for the wrong words or missed something.

I adapted the design as a more general one. At the following basic setting:

package First;
use Moose;
use Second::Type1;
use Second::Type2;
has 'type1' => (
  is => 'rw',
  isa => 'Second::Type1',
  default => sub {Second::Type1->new(name => 'random')}
);

has 'type2' => (
  is => 'rw',
  isa => 'Second::Type2',
  default => sub {Second::Type2->new(name => 'random')}
);

package Second::Type1;
use Moose;
use This;
has 'name' => (
  is => 'rw',
  isa => 'Str',
  required => 1,
);
has 'this' => (
  is => 'rw',
  isa => 'This',
  default => sub {This->new()}
);
# package has more attributes, but you get the idea
__PACKAGE__->meta->make_immutable();
no Moose;
1;

package Second::Type2;
use Moose;
use That;
has 'name' => (
  is => 'rw',
  isa => 'Str',
  required => 1,
);
has 'that' => (
  is => 'rw',
  isa => 'That',
  default => sub {That->new()}
);
# package has more attributes, but you get the idea
__PACKAGE__->meta->make_immutable();
no Moose;
1;

I want to be able to build First by saying:

use First;
my $first = First->new(type1 => 'foo', type2 => 'bar');

where 'foo' is equal to the value for the attribute “name of the second”: “Type1” and “bar” is equal to the value of the attribute “name” of Second :: Type2.

, , () Moose:: Role, " BUILDARGS", Factory ( IMO ):

package Role::SingleBuildargs;

use Moose::Role;
use Factory::Second;
requires 'get_supported_args';

around BUILDARGS => sub {
my ($class, $self, %args) = @_;
my @supported_args = $self->get_supported_args;
my $factory = Factory::Second->new();
    my @errors = ();
    foreach my $arg (sort {$a cmp $b} keys %args) {
        if (grep {$_ eq $arg} @supported_args) {
            my $val = $args{$arg};
            if (!ref $val) {    # passed scalar init_arg
                print "$self (BUILDARGS): passed scalar\n";
                print "Building a Second with type '$arg' and name '$val'\n";
                $args{$arg} = $factory->create(type => $arg, name => $val)
            } elsif (ref $val eq 'HASH') {  # passed hashref init_arg
                print "$self (BUILDARGS): passed hashref:\n";
                my %init_args = %$val;
                delete $init_args{name} unless $init_args{name};
                $init_args{type} = $arg;
                $args{$arg} = $factory->create(%init_args);
            } else {    # passed another ref entirely
                print "$self (BUILDARGS): cannot handle reference of type: ", ref $val, "\n";
                die;
            }
        } else {
            push @errors, "$self - Unsupported attribute: '$arg'";
        }
    }
    if (@errors) {
        print join("\n", @errors), "\n";
        die;
    }
    return $self->$class(%args);
    };

no Moose;
1;

, First.

:

package Role::Second::TypeConstraints;
use Moose::Util::TypeConstraints

subtype 'SecondType1', as 'Second::Type1';
subtype 'SecondType2', as 'Second::Type2';
coerce 'SecondType1', from 'Str', via {Second::Type1->new(name => $_};
coerce 'SecondType2', from 'Str', via {Second::Type2->new(name => $_};

no Moose::Util::TypeConstraints;
1;

( ):

use Role::Second::TypeConstraints;
has 'type1' => (
   isa => 'SecondType1',
   coerce => 1,
);
has 'type2' => (
   isa => 'SecondType2',
   coerce => 1,
);    

, , . - , .

: ? , BUILDARGS, - ( Moose:: Util:: TypeConstraints, )? TMTOWTDI , .

EDIT: ( )

+4
2

,

  • use Moose::Util::TypeConstraints;
    

    to First, Second::Type1 Second::Type2

  • Second::Type1

    coerce 'Second::Type1'
        => from 'Str'
            => via { Second::Type1->new( name => $_ ) };
    

    Second::Type2

    coerce 'Second::Type2'
        => from 'Str'
            => via { Second::Type2->new( name => $_ ) };
    
  • type1 type2 First

    has 'type1' => (
      is      => 'rw',
      isa     => 'Second::Type1',
      default => sub { Second::Type1->new },
      coerce  => 1,
    );
    
    has 'type2' => (
      is      => 'rw',
      isa     => 'Second::Type2',
      default => sub { Second::Type2->new },
      coerce  => 1,
    );
    

First , ,

my $first = First->new(type1 => 'foo', type2 => 'bar');
+2

. MooseX::Types .

, MooseX:: Types.

package Foo;
use Moose;
use MooseX::Types -declare => [qw(MyDateTime)];
use MooseX::Types::Moose 'Int';
use DateTime;

class_type MyDateTime, { class => 'DateTime' };
coerce MyDateTime, from Int, via { DateTime->from_epoch( epoch => $_ ) };

has date => (
    is      => 'ro',
    isa     => MyDateTime,
    default => sub {time},
    coerce  => 1,
);

package main;

my $foo = Foo->new;
say 'without args: ', $foo->date;

my $bar = Foo->new( date => time - 24 * 3600 );
say 'with args:    ', $bar->date;

- :

without args: 2015-06-26T13:35:38
with args:    2015-06-25T13:35:38

, , . .

+1

All Articles