Announcing MooX::Press

This is an old article. Some links may be broken. Some of the information may no longer be correct. Opinions expressed in this article may no longer be held.

MooX::Press is a quick way of building a bunch of Moo roles and classes in one use statement.

The most basic example would be:

  package MyApp {
    use MooX::Press class => ['Foo', 'Bar'];
  }
  
  my $thing1 = MyApp::Foo->new();
  my $thing2 = MyApp->new_foo();   # alternative constructor

But do-nothing classes with a constructor and nothing else aren’t very exciting. Let’s define a class with some subclasses which have attributes and roles and methods and stuff.

  package MyApp::Zoo;
  use MooX::Press (
    role => [
      'Aquatic' => {
        can => [
          swim => sub { print "swimming\n" },
        ],
      },
      'Flight',
    ],
    class => [
      'Animal' => {
        has => [qw( $name $colour $age )],
        subclass => [
          'Fish' => {
            with => 'Aquatic',
            subclass => [qw( Shark Ray )],
          },
          'Bird' => { with => 'Flight' },
          'Mammal' => {
            subclass => [
              qw( Panda Goat ),
              'Kangaroo' => { can => [ jump => sub { ... } ] },
              'Dolphin'  => { with => 'Aquatic' },
              'Bat'      => { with => 'Flight' },
            ],
          },
        ],
      },
    ],
  );

The above code just defined the following roles:

  • MyApp::Zoo::Aquatic
  • MyApp::Zoo::Flight

And the following classes:

  • MyApp::Zoo::Animal
  • MyApp::Zoo::Fish
  • MyApp::Zoo::Shark
  • MyApp::Zoo::Ray
  • MyApp::Zoo::Bird
  • MyApp::Zoo::Mammal
  • MyApp::Zoo::Panda
  • MyApp::Zoo::Goat
  • MyApp::Zoo::Kangaroo
  • MyApp::Zoo::Dolphin
  • MyApp::Zoo::Bat

All with the appropriate attributes and roles applied to them.

Also, it defined a package called MyApp::Zoo::Types with class and role type constraints already set up.

So you can do:

  use Moo;
  use MyApp::Zoo::Types qw(Kangaroo);
  
  has mascot => (is => 'ro', isa => Kangaroo);

Or:

  use MyApp::Zoo::Types qw(is_Kangaroo);
  
  $thing->jump if is_Kangaroo($thing);

Here’s some more code using our zoo classes…

  use MyApp::Zoo ();
  
  my $lenny = MyApp::Zoo->new_shark(name => 'Lenny');
  $lenny->isa('MyApp::Zoo::Shark');    # true
  $lenny->isa('MyApp::Zoo::Fish');     # true
  $lenny->isa('MyApp::Zoo::Animal');   # true
  $lenny->does('MyApp::Zoo::Aquatic'); # true
  $lenny->can('swim');                 # true
  
  package MyApp::Zoo::Enclosure::Tank {
    use Moo;
    use Types::Standard qw(ArrayRef);
    use MyApp::Zoo::Types qw(Aquatic);
    has animals => (
      is  => 'rw',
      isa => ArrayRef[Aquatic],
    );
  }
  
  my $tank = MyApp::Zoo::Enclosure::Tank->new(
    animals => [ $lenny ],
  );

MooX::Press is on CPAN.