Catalyst-View-BasePerRequest
view release on metacpan or search on metacpan
README.mkdn view on Meta::CPAN
}
__PACKAGE__->config(
content_type=>'text/html',
status_codes=>[200]
);
__PACKAGE__->meta->make_immutable();
One way to use it in a controller:
package Example::Controller::Root;
use Moose;
use MooseX::MethodAttributes;
extends 'Catalyst::Controller';
sub root :Chained(/) PathPart('') CaptureArgs(0) { }
sub hello :Chained(root) Args(0) {
my ($self, $c) = @_;
return $c->view(Hello =>
name => 'John',
age => 53
)->http_ok;
}
__PACKAGE__->config(namespace=>'');
__PACKAGE__->meta->make_immutable;
# DESCRIPTION
**NOTE**: This is early access code. Although it's based on several other internal projects
which I have iterated over this concept for a number of years I still reserve the right
to make breaking changes as needed.
**NOTE**: You probably won't actually use this directly, it's intended to be a base framework
for building / prototyping strongly typed / per request views in [Catalyst](https://metacpan.org/pod/Catalyst). This
documentation serves as an overview of the concept. In particular please note that
this code does not address any issues around HTML / Javascript injection attacks or
provides any auto escaping. You'll need to bake those features into whatever you
build on top of this. Because of this the following documentation is light and is mostly
intended to help anyone who is planning to build something on top of this framework
rather than use it directly.
**NOTE**: This distribution's `/example` directory gives you a toy prototype using [HTML::Tags](https://metacpan.org/pod/HTML%3A%3ATags)
as the basis to a view as well as some raw examples using this code directly (again,
not recommended for anything other than learning).
In a classic [Catalyst](https://metacpan.org/pod/Catalyst) application with server side templates, the canonical approach
is to use a 'view' as a sort of handler for an underlying template system (such as
[Template::Toolkit](https://metacpan.org/pod/Template%3A%3AToolkit) or [Xslate](https://metacpan.org/pod/Xslate)) and to send data to this template by populating
the stash. These views are very lean, and in general don't provide much in the way
of view logic processing; they generally are just a thin proxy for the underlying
templating system.
This approach has the upside of being very simple to understand and in general works
ok with a simple websites. There are however downsides as your site becomes more
complex. First of all the stash as a means to pass data from the Controller to the
template can be fragile. For example just making a simple typo in the stash key
can break your templates in ways that might not be easy to figure out. Also your
template can't enforce its requirements very easily (and it's not easy for someone
working in the controller to know exactly what things need to go into the stash in
order for the template to function as desired.) The view itself has no way of
providing view / display oriented logic; generally that logic ends up creeping back up
into the controller in ways that break the notion of MVC's separation of concerns.
Lastly the controller doesn't have a defined API with the view. All it can ask the view
is 'go ahead and process yourself using the current context' and all it gets back from
the view is a string response. If the controller wishes to introspect this response
or modify it in some way prior to it being sent back to the client, you have few options
apart from using regular expression matching to try and extract the required information
or to modify the response string.
Basically the classic approach works acceptable well for a simple website but starts to
break down as your site becomes more complicated.
An alternative approach, which is explored in this distribution, is to have a defined view for
each desired response and for it to define an explicit API that the controller uses to provide the required
and optional data to the view. This defined view can further define its own methods
used to generate suitable information for display. Such an approach is more initial work
as well as learning for the website developers, but in the long term it can provide
an easier path to sustainable development and maintainence with hopefully fewer bugs
and overall site issues.
# EXAMPLE: Basic
The most minimal thing your view must provide in a `render` method. This method gets
the view object and the context (it can also receive additional arguments if this view is
being called from other views as a wrapper or parent view; more on that later).
The `render` method should return a string or array of strings suitable for the body of
the response> **NOTE** if you return an array of strings we flatten the array into a single
string since the `body` method of [Catalyst::Response](https://metacpan.org/pod/Catalyst%3A%3AResponse) can't take an array.
Here's a minimal example:
package Example::View::Hello;
use Moose;
extends 'Catalyst::View::BasePerRequest';
sub render {
my ($self, $c) = @_;
return "<p>Hello</p>";
}
__PACKAGE__->config(content_type=>'text/html');
And here's an example view with attributes:
package Example::View::HelloPerson;
use Moose;
extends 'Catalyst::View::BasePerRequest';
has name => (is=>'ro', required=>1);
( run in 1.123 second using v1.01-cache-2.11-cpan-364913b4093 )