I was having difficulty tracking down a problem with a failing subtype in my
code - abstracted to the following:

/lib/Test.pm

    package Test;

    use Moose;
    use Moose::Util::TypeConstraints;

    use Module::Find qw( useall );

    # 'use's Test::View::* and returns a list of modules
    my @AVAILABLE_VIEWS = useall Test::View;

    subtype 'View'
        => as 'ClassName';

    subtype 'ViewLookup'
        => as 'HashRef[View]';

    # e.g.
    #   HTML::Table => Test::View::HTML::Table
    #
    has 'view_lookup' => (
        is => 'rw',
        isa => 'ViewLookup',
        default => sub {
            my %lookup = map {
                    substr( $_, length( __PACKAGE__ . '::View::' ) ) => $_
                } @AVAILABLE_VIEWS;
            # $lookup{ NotLoaded } = 'Test::View::NotLoaded';
            return \%lookup;
        }
    );
    1;

lib/Test/View/Text.pm

    package Test::View::Test;

    our $VERSION = '0.01';

    sub method { 1 }
    1;

lib/Test/View/HTML/Table.pm

    package Test::View::HTML::Table;

    our $VERSION = '0.01';

    sub method { 1 }

    1;


Throws:

    Attribute (view_lookup) does not pass the type constraint because:
Validation failed for 'ViewLookup' failed with value HASH(0x123aa880) at
lib/Moose/Meta/Class.pm line 193

It took a while to track for me to track down the source of my stupidity as
it wasn't entirely clear to me where the source of the problem was given the
error that Moose threw (it seems obvious now, but in my defence the original
code was more complex than the abstract sample above). It turns out I had
made a typo in the package declaration (package Test::View::*Test* rather
than package Test::View::*Text*).

So I made a stupid typo and Moose did the right thing - who'd have thought?
Well that would've been the end of it if I hadn't chanced upon mst's "You're
not good enough" presentation this morning (
http://www.shadowcat.co.uk/archive/conference-video/yapc-eu-2008/you-arent-good-enough/).
However, since I did - I'm writing to this list in an effort to take
advantage of my very Moose noobishness to help fellow Moose noobs.

Two things would've helped speed up the process of identifying my own
ineptitude:

 - being told the specific failing test rather than the 'root' subtype (i.e.
failing ClassName within ViewLookup rather than a failing ViewLookup)

 - being told why the ClassName failed (pod does mention it makes "complex
tests")

I haven't looked at the former - but here's a very tentative suggestion to
help with the latter - provides a warning before failing the ClassName
constraint.

+++ lib/Moose/Util/TypeConstraints/OptimizedConstraints.pm      2008-11-21
16:38:32.000000000 +0000
@@ -39,7 +39,14 @@
     # \*{${main::}{"Foo::"}} == \*main::Foo::

     my $pack = \*::;
+    my $pack_name;
     foreach my $part (split('::', $_[0])) {
+        $pack_name .= ($pack_name ? '::' : '') . $part;
+        if ( !exists ${$$pack}{"${part}::"} ) {
+            warn  "[warn] ClassName constraint failed for ($_[0])\n".
+                  "[warn]   - not in symbol table (did you \"use
$pack_name\"?)\n";
+            return 0;
+        }
         return 0 unless exists ${$$pack}{"${part}::"};
         $pack = \*{${$$pack}{"${part}::"}};
     }
@@ -55,7 +62,10 @@
         next if substr($_, -2, 2) eq '::';
         return 1 if defined *{${$$pack}{$_}}{CODE};
     }
-
+
+    warn  "[warn] ClassName constraint failed for ($_[0])\n".
+          "[warn]   - class has no VERSION, ISA or CODE defined (typo in
package statement?)\n";
+
     # fail
     return 0;
 }

Now produces:

  [warn] ClassName constraint failed for (Test::View::Text)
  [warn]   - class has no VERSION, ISA or CODE defined (typo in package
statement?)
  Attribute (view_lookup) does not pass the type constraint because:
Validation failed for 'ViewLookup' failed with value HASH(0xb2a4e90) at
lib/Moose/Meta/Class.pm line 193

And if you fix the typo an uncomment the 'Unloaded' line, you get:

  [warn] ClassName constraint failed for (Test::View::NotLoaded)
  [warn]   - not in symbol table (did you "use Test::View::NotLoaded"?)
  Attribute (view_lookup) does not pass the type constraint because:
Validation failed for 'ViewLookup' failed with value HASH(0x7337ac0) at
lib/Moose/Meta/Class.pm line 193

I appreciate that not everyone wants to have those warnings thrown to STDERR
but since Moose::Util::TypeConstraints::OptimizedConstraints::ClassName
returns 0 or 1 rather than raises exceptions I wasn't sure what was best (is
there a global Moose warning/logging policy?)


Cheers,

Ian



-- 
Dr Ian Sillitoe
CATH Team -- http://cathdb.info

Reply via email to