Day 8. Some notes on ACCEPT_CONTEXT, with and without antlers.

Today we'll show you how to avoid spaghetti controllers with ACCEPT_CONTEXT. It's tempting to stuff lots of business logic in your Controller, while usually this belongs in your Model. Although at first it seems like more effort to go to the trouble of setting up the model correctly, as your application grows, taking care of design like this rapidly pays dividends.

If you need access to a database schema or two in a model, or if you need to be able to access path_to or something else that belongs in $c, you'll want to use this technique. First we'll show how to do this without Moose, then with Moose.

Without Moose

Here's an example that gives us access to $c->path_to:

  __PACKAGE__->mk_accessors(qw/path_to/);

 sub ACCEPT_CONTEXT {
     my ($self, $c ) = @_;
     $self = bless({ %$self,
                     path_to => $c->path_to(''),
                 }, ref($self));
     return $self;
 }




Or if we wanted two different database schemas accessible from two different Catalyst::Models:

 __PACKAGE__->mk_accessors(qw(schema1 schema2));

 sub ACCEPT_CONTEXT {
     my ( $self, $c, @extra_arguments ) = @_;
     $self = bless({ %$self,
                     schema1  => $c->model('My::Schema1')->schema,
                     schema2 => $c->model('My::Schema2')->schema,
         }, ref($self));
     return $self;
 }

Now when you have a subroutine in your model, you can access the relevant bit of $c with C$self->path_to, $self->schema1 or whatever you named your accessor. This avoids polluting your model with the bits of the context object that you don't need, makes your code more maintainable, and avoids some nasty gotchas that have to do with variable scope.

Doing the same with Moose

Catalyst 5.8 will use the Moose meta-object system, so it makes sense to use Moose to handle these issues for you.

The code is pretty similar:

 use Moose;

 sub ACCEPT_CONTEXT {
     my ($self, $c ) = @_;
     my $new = $self->meta->clone_object($self, path_to => $c->path_to(''));
     return $new;
 }

The meta method above is a benefit of Moose (actually Class::MOP). Although this example isn't much clearer with Moose than without, for the most part Moose greatly increases the read- and write-ability of your code. See the Moose::Cookbook for many examples.

AUTHORS

Kieren Diment <zarquon@cpan.org> Robert 'phaylon' Sedlacek <rs@474.at>