Tools for ProductivityRESTful Web Services with Mojolicious and DBIx::
Class
About MeTudor Constantin● Perl Developer @ Evozon● http://programming.tudorconstantin.com/● http://stackoverflow.
com/users/459233/tudor-constantin● https://github.com/tudorconstantin● http://www.linkedin.
com/in/tudorconstantin
Content● Objectives● Solutions● Implementation● Conclusions
Objectives● Find a way to create generic, distributed DB
oriented applications● One backend, multiple frontends, same
functionality:○ web○ mobile○ desktop
● Rapid app development for the backend○ Avoid boilerplate code○ Adhere to the DRY principle○ Generate as much code as possible○ Have a predictible API
Solutions● Implement only the business logic in Perl● Expose it through an API
○ REST○ SOAP○ RPC○ WSDL
● Services Oriented Architecture
SolutionsChosen one is the REST architecture:● The simplest to implement (from server and
client perspective)● Uniform interface
○ simplifies and decouples the architecture● Stateless - each request can be treated on a
different machine○ Horizontal scalability
ImplementationRESTful routes:
GET /api/user/1
UPDATE /api/user/5
DELETE /api/user/3
ImplementationDefine Mojolicious routes:
$r->get('/api/user/:id')->to('user#show')->name('user_details');
$r->put('/api/user/:id')->to('user#update')->name('user_update');
Mojolicious routes are in a 1 to 1 correlation with the REST ones
ImplementationMethods needed to implement for each resource:● list - returns a collection of resources (list of
users)● show - return an individual resource (1
user)● create - create a new resource● delete● update
ImplementationThe above operations:● each corresponds to a DB CRUD operation
● each can get implemented in a controller method
● each can be implemented in a generic way:○ get parameters, do stuff, return json
Implementation - Overview
Implementation
sub update{ my $self = shift; my $result_rs = $self->app->model ->resultset( $self->{resource} ) ->search_rs( { id => $self->param('id') }, ); return $self->render_not_found if ( scalar( ( $result_rs->all ) ) == 0 ); $result_rs->update_all( $self->{_payload} );$result_rs->result_class('DBIx::Class::ResultClass::HashRefInflator'); my @result = $result_rs->all(); return $self->render_json( @result );}
Steps for having REST 1. Create the DB tables2. Generate the DBIx::Class models with
DBIx::Class::Schema::Loadera. add the relationships between models
3. Create the controllers which inherit from the Base controller
4. (optional) Override the desired methods (ie - customize the business logic)
5. Create the routes to Mojolicious
Conclusions● Very fast to develop
○ There are only 6 steps■ 4 of them are, or can be, automated
● Completely DRY○ define the table structure only once - when it is
created○ you write a column name only when you need to do
something special with it (validate for example)● Very easy to test
○ end to end testing can be done with simple curl operations
EndSample app (with the generic controller) can be found on github:https://github.com/tudorconstantin/expense-tracker
The generic controller:https://github.com/tudorconstantin/expense-tracker/blob/master/lib/ExpenseTracker/Controllers/Base.pm