[Catalyst] Dynamic model and controller creation

Bill Moseley moseley at hank.org
Sun Jan 1 04:58:02 GMT 2012

I'm looking for examples of creating controllers and models via
configuration.  As I'm doing it now (below) I'm having to add a number of
pretty small classes that are almost entirely configuration.   It's pretty
simple as-is, but wondering if you might have a simpler approach (or doc
link) so that I can dynamically add actions and models either at runtime or
app config.

I have a very simple library I want provide a RESTful API for.  The library
has a base class, say Inventory::Service that provides a simple API with
CRUD-like metods add() and get().  This base class in not used directly,
rather subclasses exists. For example, Inventory::Service::Nut and
Inventory::Service::Bolt inherit from the base class.   There's potentially
a large number of these sub-classes.

So, I want a direct mapping "POST /service/bolt" to create and "GET
/service/bolt/<id>" to fetch the bolt, and likewise for the Nut and other

I've created a base class "MyApp::ControllerBase::Inventory" that has
generic methods thing_POST and thing_GET as per C::A::REST (that implement
the common ->add() and ->get() methods) and has an attribute "model_class".

Then I have Controller classes inheriting from this class that are simply
config setting the "model_class" attribute:

package MyApp::Controller::Service::Bolt;
use base 'MyApp::ControllerBase::Inventory;
__PACKAGE__->config(  model_class =3D> 'Inventory::Bolt',);

Which means the base class just does $c->model( $self->model_class ) to get
at the Inventory::Bolt model.

Then, likewise, I have a Model base class that uses ACCEPT_CONTEXT to
return specific instances:

package MyApp::ModelBase::Inventory;
use Moose;
use namespace::autoclean;
extends 'Catalyst::Model';

has service =3D> ( is =3D> 'rw' );  # instance of model

has service_class =3D> (
    is =3D> 'ro',
    isa =3D> 'Str',
    required =3D> 1,

# wrapping "setup_components" might be another approach
    my ( $self, $c, @args ) =3D @_;

    my $service =3D $self->service;

    unless ( $service ) {
        my $service_class =3D $self->service_class;
        Class::MOP::load_class( $service_class );

        $service =3D $service_class->new;

        # Save our instance
        $self->service( $service );

    return $service;


And then the specific model classes are simply:

package MyApp::Model::Inventory::Bolt;
use base 'MyApp::ModelBase::Inventory';
__PACKAGE__->config( service_class =3D> 'Inventory::Service::Bolt' );

Of course, after doing that a few times I'd rather use a programatic

So, what I'd like is to remove the need to create those stub Controller and
Model classes and instead use config (or maybe detection of available
subclasses at startup).

-- =

Bill Moseley
moseley at hank.org
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.scsys.co.uk/pipermail/catalyst/attachments/20120101/6ef84=

More information about the Catalyst mailing list