Dancer2
view release on metacpan or search on metacpan
lib/Dancer2/Manual/Cookbook.pod view on Meta::CPAN
# add in bookstore/lib/Bookstore.pm
sub _perform_search {
my ($query) = @_;
my $bookstore_schema = schema 'Bookstore';
my @results;
# search in authors
my @authors = $bookstore_schema->resultset('Author')->search({
-or => [
firstname => { like => "%$query%" },
lastname => { like => "%$query%" },
]
});
push @results, map {
{ author => join(' ', $_->firstname, $_->lastname),
books => [],
}
} @authors;
my %book_results;
# search in books
my @books = $bookstore_schema->resultset('Book')->search({
title => { like => "%$query%" },
});
foreach my $book (@books) {
my $author_name = join(' ', $book->author->firstname, $book->author->lastname);
push @{$book_results{$author_name}}, $book->title;
}
push @results, map {
{ author => $_,
books => $book_results{$_},
}
} keys %book_results;
return @results;
}
=item * Use home made schema classes
The L<DBIx::Class::MooseColumns> lets you write the DBIC schema classes
using L<Moose>. The schema classes should be put in a place that Dancer2
will find. A good place is in F<bookstore/lib/>.
Once your schema classes are in place, all you need to do is modify F<config.yml>
to specify that you want to use them, instead of the default auto-detection method:
# change in bookstore/config.yml
plugins:
DBIC:
bookstore:
schema_class: My::Bookstore::Schema
dsn: "dbi:SQLite:dbname=bookstore.db"
=back
Our bookstore lookup application can now be started using the built-in server:
# start the web application
plackup bin/app.psgi
=head1 Authentication Recipes
Writing a form for authentication is simple: we check the user credentials
on a request and decide whether to continue or redirect them to a form.
The form allows them to submit their username and password; we save that
and create a session for them so when they try the original request,
we recognize the user and allow them in.
=head2 Basic Application
The application is fairly simple. We have a route that needs authentication,
we have a route for showing the login page, and we have a route for posting
login information and creating a session.
package MyApp;
use Dancer2;
get '/' => sub {
session('user')
or redirect('/login');
template index => {};
};
get '/login' => sub {
template login => {};
};
post '/login' => sub {
my $username = query_parameters->get('username');
my $password = query_parameters->get('password');
my $redir_url = query_parameters->get('redirect_url') || '/login';
$username eq 'john' && $password eq 'correcthorsebatterystaple'
or redirect $redir_url;
session user => $username;
redirect $redir_url;
};
=head2 Tiny Authentication Helper
L<Dancer2::Plugin::Auth::Tiny> allows you to abstract away not only the
part that checks whether the session exists, but to also generate a
redirect with the right path and return URL.
We simply have to define what routes needs a login using Auth::Tiny's
C<needs> keyword.
get '/' => needs login => sub {
template index => {};
};
It creates a proper return URL using C<uri_for> and the address from which
the user arrived.
We can thus decorate all of our private routes to require authentication in
this manner. If a user does not have a session, it will automatically forward
it to I</login>, in which we would render a form for the user to send a login request.
Auth::Tiny even provides a new parameter, C<return_url>, which can be used to send
the user back to their original requested path.
( run in 1.892 second using v1.01-cache-2.11-cpan-39bf76dae61 )