Slash Boxes
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

Journal of LTjake (4001)

Thursday July 17, 2008
08:55 AM

Component resolution in Catalyst 5.7100

[ #36941 ]

One of the things you'll see in the changelog for the next stable release of Catalyst, is a reworked component resolution system. By "component resolution" i mean, fetching components from view()/views(), model()/models(), controller()/controllers() and component().

Back in May I posted a message to the Catalyst-dev list describing some issues with the way it was currently working. Although I painted a slightly convoluted picture of doom and gloom -- it turns out that all is not lost; you were probably relying on an "undefined" behavior to begin with (kind of like assuming "keys %hash" will return things in a particular order).

For example, consider "MyApp" with two views: "Foo" and "Bar." Now, when you call "$c->view()" (i.e. with no arguments) what gets returned? Well, it depends. :) If you have none of the appropriate config (default_view) or stash variables (current_view, current_view_instance) set, then it's pretty much random.

If you write a test for the above, and see that "MyApp::View::Bar" is returned -- don't count on that test working in 5.7100 (the message I posted to the list has the technical details as to why). Though the test *may* continue to work, the above scenario will throw a pretty large warning:

Calling $c->view() will return a random view unless you specify one of:
* $c->config->{default_view} # the name of the default view to use
* $c->stash->{current_view} # the name of the view to use for this request
* $c->stash->{current_view_instance} # the instance of the view to use for this request
NB: in version 5.80, the "random" behavior will not work at all.

(FYI, if your application only has one view, calling "$c->view()" is considered "acceptable" and will spare you the warnings.)

A similar warning is thrown for $c->model(). $c->controller() with no arguments will continue to return the controller for the dispatched action. $c->component (sans args) will also stay the same, returning a sorted list of all component names.

Another issue I discovered while re-working the code was a failed reliance on the "regex" fallback.

Consider another "MyApp" with two views "Foo::Bar" and "Foo::Baz". What does "$c->view('Foo')" return? We've maintained backwards compatibility on this one -- it will return all matching views (order unknown). It is important to note that this returns an array, so list context is important. We've added a warning for this scenario as well:

Relying on the regexp fallback behavior for component resolution is unreliable and unsafe.
If you really want to search, pass in a regexp as the argument.

As noted above, if you truly were just searching for views, pass it a regex ("$c->view(qr{Foo})") and it will act as expected.

So, if you think you might be affected by these particular issues, test out the dev release! Don't say I didn't warn you. :)

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
More | Login | Reply
Loading... please wait.
  • This is great news. I was bitten by the regex fallback a year ago when I had a typo in my model name and Catalyst picked a related model instead. The two models were similar enough that I didn't notice for quite a while.

  • Oops, I tested this and found four accidental violations in my code: 3 x $c->view() and one case of model('DB::session') where I meant model('DB::sessions')

    Please, could you add the $name to the warning message? I had to fire up the debugger to figure out which model was causing the actual warning in my code.

    Otherwise, I'm getting a perfect success with my biggest app using SVN rev 8135 in [] (aka 5.7099_02)

    • SVN revision 8138 adds a new line about the value supplied. 5.70/trunk also has a couple more fixes for regexp fallback and ACCEPT_CONTEXT from component().

      Thanks a lot for testing this out!