Maypole
view release on metacpan or search on metacpan
lib/Maypole/Manual/Cookbook.pod view on Meta::CPAN
use Maypole::Application qw(-Debug);
=head3 Changing how URLs are parsed
You don't like the way Maypole URLs look, and want something that either
fits in with the rest of your site or hides the internal workings of the
system.
B<Solution>: So far we've been using the C</table/action/id/args> form
of a URL as though it was "the Maypole way"; well, there is no Maypole
way. Maypole is just a framework and absolutely everything about it is
overridable.
If we want to provide our own URL handling, the method to override in
the driver class is C<parse_path>. This is responsible for taking
C<$r-E<gt>path> and filling the C<table>, C<action> and C<args> slots
of the request object. Normally it does this just by splitting the path
on 'C</>' characters, but you can do it any way you want, including
getting the information from C<POST> form parameters or session variables.
For instance, suppose we want our URLs to be of the form
C<ProductDisplay.html?id=123>, we could provide a C<parse_path> method
like so:
sub parse_path {
my $r = shift;
$r->path("ProductList.html") unless $r->path;
($r->path =~ /^(.*?)([A-Z]\w+)\.html/);
$r->table(lc $1);
$r->action(lc $2);
my %query = $r->ar->args;
$self->args([ $query{id} ]);
}
This takes the path, which already has the query parameters stripped off
and parsed, and finds the table and action portions of the filename,
lower-cases them, and then grabs the C<id> from the query. Later methods
will confirm whether or not these tables and actions exist.
See the L<iBuySpy Portal|Maypole::Manual::BuySpy> for another
example of custom URL processing.
=head3 Maypole for mobile devices
You want Maypole to use different templates to display on particular
browsers.
B<Solution>: There are several ways to do this, but here's the neatest
we've found. Maypole chooses where to get its templates either by
looking at the C<template_root> config parameter or, if this is not
given, calling the C<get_template_root> method to ask the front-end to
try to work it out. We can give the front-end a little bit of help, by
putting this method in our driver class:
sub get_template_root {
my $r = shift;
my $browser = $r->headers_in->get('User-Agent');
if ($browser =~ /mobile|palm|nokia/i) {
"/home/myapp/templates/mobile";
} else {
"/home/myapp/templates/desktop";
}
}
(Maybe there's a better way to detect a mobile browser, but you get the
idea.)
=head2 Content display hacks
These hacks deal primarily with the presentation of data to the user,
modifying the F<view> template or changing the way that the results of
particular actions are displayed.
=head3 Null Action
You need an "action" which doesn't really do anything, but just formats
up a template.
B<Solution>: There are two ways to do this, depending on what precisely
you need. If you just need to display a template, C<Apache::Template>
style, with no Maypole objects in it, then you don't need to write any
code; just create your template, and it will be available in the usual
way.
If, on the other hand, you want to display some data, and what you're
essentially doing is a variant of the C<view> action, then you need to
ensure that you have an exported action, as described in the
L<templates and actions|Maypole::Manual::StandardTemplates/"C<view> and C<edit>">
chapter:
sub my_view :Exported { }
=head3 Template Switcheroo
An action doesn't have any data of its own to display, but needs to display
B<something>.
B<Solution>: This is an B<extremely> common hack. You've just issued an
action like C<beer/do_edit>, which updates the database. You don't want
to display a page that says "Record updated" or similar. Lesser
application servers would issue a redirect to have the browser request
C</beer/view/I<id>> instead, but we can actually modify the Maypole
request on the fly and, after doing the update, pretend that we were
going to C</beer/view/I<id>> all along. We do this by setting the
objects in the C<objects> slot and changing the C<template> to the
one we wanted to go to.
In this example from L<Flox|Maypole::Manual::Flox>, we've just
performed an C<accept> method on a C<Flox::Invitation> object and we
want to go back to viewing a user's page.
sub accept :Exported {
my ($self, $r) = @_;
my $invitation = $r->objects->[0];
# [... do stuff to $invitation ...]
$r->objects([$r->user]);
$r->model_class("Flox::User");
$r->template("view");
}
This hack is so common that it's expected that there'll be a neater
( run in 0.653 second using v1.01-cache-2.11-cpan-39bf76dae61 )