[Catalyst] Problem with Catalyst::Engine::component()

Bernhard Graf catalyst at augensalat.de
Fri Aug 26 09:45:37 CEST 2005


Cheers,

yesterday I spent some hours tracking an error in my CatApp.
Finally I spotted Catalyst::Engine::component() as the point of failure.
This method looks like this:

sub component {
    my $c = shift;

    if (@_) {

        my $name = shift;

        if ( my $component = $c->components->{$name} ) {
            return $component;
        }

        else {
            for my $component ( keys %{ $c->components } ) {
                return $c->components->{$component} if $component =~ /$name/i;
            }
        }
    }

    return sort keys %{ $c->components };
}

What this does is:
If $c->component('MyApp::M::Shop') can't find a component called
"MyApp::M::Shop" it will either happily return the component
"MyApp::M::ShopItem" provided we also have this among our components
or else return an array of the component keys which probably will result
in a numerical value since we typically call this method in a scalar
context.

Of course I see the doc saying
<cite>
Regex search for a component.

    $c->comp('mymodel')->do_stuff;
</cite>

but is this really the intended behaviour?


But wait ... now it gets really weired:
Actually there /was/ a component called "MyApp::M::Shop", but the line
	if ( my $component = $c->components->{$name} ) {
evaluated to false!!!
That's probably because MyApp::M::Shop->isa('Class::DBI') and
	package Class::DBI;
	[...]
	use overload [...]
	bool => sub { not shift->_undefined_primary }, [...]
which seems to evaluate to false for all my CDBI based classes in
boolean context (don't know why, but I don't feel like digging in the
CDBI sources).

And indeed $c->component('MyApp::M::Shop') gave me the component for
"MyApp::M::ShopItem", because this came at first when looping through
the component keys.

So if the answer to my question above is "no" and to fix handling of
CDBI based components I'd suggest (which abolishes regex search):

sub component {
    my $c = shift;

    if (@_) {
        my $comp = $c->components->{shift};
        # using define() takes overload boolean => false into account
        return defined($comp) ? $comp : ();
    }

    return sort keys %{ $c->components };
}

If regex component search is really needed by someone, it can be done in
the application itself like:
	my $name = 'mymodel';
	my $comp;
	foreach my $key ($c->component) {
	  $comp = $c->component($key), last
	    if $key =~ /$name/i;
	}

-- 
Bernhard Graf



More information about the Catalyst mailing list