---- MooseX::Tour Jonathan Rockway http://blog.jrock.us/ jon@jrock.us ---- MooseX ---- MooseX * Extends Moose ---- MooseX * Extends Moose * Not for modules that merely use Moose ---- MooseX::Types * first, modules that use it ---- MooseX::Types::Path::Class package Class; use Moose; use MooseX::Types::Path::Class qw(File Dir); has 'config' => ( is => 'ro', isa => File, coerce => 1, required => 1, ); ---- MooseX::Types::Path::Class my $class = Class->new( config => '/foo/bar' ); say "config: ", $class->config->slurp; ---- MooseX::Types::* ---- MooseX::Types::* MooseX::Types::UUID MooseX::Types::URI MooseX::Types::DateTime MooseX::Types::Set::Object MooseX::Types::Authen::Passphrase .... ---- MooseX::Types make your own types package My::Type; use MooseX::Types -declare => [qw/Foo/]; use MooseX::Types::Moose 'Str'; subtype Foo, => as Str, => where { /^(?:foo|bar|baz)$/ }; ---- MooseX::Types use your types package Class; use Moose; use My::Type qw(Foo); has foo => ( is => 'ro', isa => Foo ); ---- MooseX::Traits ---- MooseX::Traits Classes with plugins package Whatever; use Moose; with 'Plug::In', 'Plug::Out'; ---- MooseX::Traits that way is hard that way doesn't "scale" ---- MooseX::Traits package Whatever; use Moose; with 'MooseX::Traits'; That's it! ---- MooseX::Traits my $custom = Whatever->new_with_traits( traits => [qw/Plug::In/], ); my $more_custom = Whatever->new_with_traits( traits => [qw/Foo Bar Canned::Air/], remaining_air => 98, ); ---- MooseX::StrictConstructor ---- MooseX::StrictConstructor Problem: package Foo; use Moose; has 'bar' => ( is => 'ro' ); Foo->new( bra => 'yes' ); # works ok! ---- MooseX::StrictConstructor Solution! package Foo; use Moose; use MooseX::StrictConstructor; has 'bar' => ( is => 'ro' ); Foo->new( bra => 'yes' ); # dies a horrible flaming death Not an init_arg? DEATH. ---- MooseX::Params::Validate I love type constraints ---- MooseX::Params::Validate I love type constraints I love methods ---- MooseX::Params::Validate package Class; use Moose; use MooseX::Params::Validate; # ... sub foo { my ($self, %args) = validate(\@_, bar => { isa => 'Int', default => '42' }, ); return $args{bar}; # 42 } ---- MooseX::Params::Validate It's like Params::Validate So there is also validatep ---- MooseX::Method::Signatures Method Signatures (*Schwern's talk later) ---- Method::Signatures method foo ($bar){ return $self->oh_hai($bar); } Yes, this is real Perl! NOT A SOURCE FILTER! ---- MooseX::Method::Signatures Combine Params::Validate and Method::Signatures use MooseX::Method::Signatures; method say_hello (Str $who = 'world'){ say $self->hello_msg, $message; } ---- method greet (Str :$who, Str :$what){ .... } $class->greet( who => 'jrockway', what => 'Hello' ); Perl6 now! :) ---- MooseX::LogDispatch ---- MooseX::LogDispatch Add logging to Moose classes package Class; use Moose; with 'MooseX::LogDispatch::Levels'; sub method { my $self = shift; $self->debug('Called method'); } ---- package Class; use Moose; with 'MooseX::LogDispatch'; sub method { my $self = shift; $self->logger->debug('Called method'); } ---- MooseX::LogDispatch Configure like Log4Perl Log::Dispatch::Config Temp hack, use IoC! Class->new( logger => ... ); ---- MooseX::Param ---- MooseX::Param package Class; with 'MooseX::Param' ---- package Class; with 'MooseX::Param' my $c = Class->new( params => { foo => 'bar' } ); $c->param('foo'); # bar $c->param( baz => 'quux' ); $c->param(); # foo, baz ---- MooseX::Getopt Command-line ... classes? ---- MooseX::Getopt package Script; use Moose; with 'MooseX::Getopt'; has 'greeting' => ( is => 'ro', isa => 'Str', required => 1, ); sub run { say $self->greeting, ', world!' } ---- use Script; Script->new_with_options->run; ---- MooseX::Getopt Knows about other types Path::Class::* ---- MooseX::Clone ---- MooseX::Clone Clone Moose classes Control cloning (shallow by default) package Class; use Moose; with 'MooseX::Clone'; has 'list' => ( is => 'ro' isa => 'ArrayRef', traits => ['Clone'], ); Class->new( ... )->clone ---- MooseX::Clone Fine-grained control Copy NoClone Clone (delegates, DWIM) ---- MooseX::YAML read object graph use MooseX::YAML qw(Load -xs); my $object = Load($yaml) ---- --- !My::Module &1 key: "value" self: *1 ---- MooseX::YAML takes care of BUILD, etc. ---- MooseX::AttributeHelpers (MXAH) ---- MooseX::AttributeHelpers (MXAH) package Class; use Moose; use MooseX::AttributeHelpers; has 'array' => ( metaclass => 'Collection::Array', is => 'ro', isa => 'ArrayRef', required => 1, provides => { push => 'add_to_array', pop => 'pop_from_array', }, ); ---- MooseX::AttributeHelpers Collection::List Collection::Array Collection::ImmutableHash Collection::Hash String Counter Bool ---- Array push pop shift unshift get set clear delete ---- Hash get set clear delete exists keys values ---- Counter inc dec set reset ---- String append prepend replace match chop chomp inc ---- Boolean set unset toggle not ---- Moose::Autobox Should be MooseX ---- Moose::Autobox use Moose::Autobox; "Hello, world"->uc # HELLO, WORLD [ 1 .. 10 ]->map(sub { $_ * $_ })->join(', '); # 1, 4, 9, ... ---- Scalar String Number Hash Array Code ---- Hash { foo => 1, bar => 2 }->hslice(['foo']) # { foo => 1 } ---- MooseX::Storage read/write Moose classes (to disk/net) ---- MooseX::Storage stages pack (object -> hash) [unpack] freeze (hash -> string) [thaw] store (string -> disk) load (disk -> object) ---- MooseX::Storage package Class; use Moose; use MooseX::Storage; our $VERSION = '0.01'; Storage( format => 'JSON', io => 'File' ); has ...; ---- MooseX use or die ---- Questions?