Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
RESTful Web Serviceswith Mojolicious and DBIx::Class
About me●   Tudor Constantin●   Perl Developer @ Evozon●   http://programming.tudorconstantin.com/●   http://stackoverflow...
Content●   Sample app overview - Expense Tracker●   (Short) Intro to RESTful Web Services●   DBIx::Class●   Mojolicious●  ...
Sample app ExpenseTrackerVERY simple application - but usable (insert expenses, assign categories andsee reports)●   Five ...
Intro to RESTful WebServicesREST - REpresentational State Transfer ● concept introduced in 2000 by Roy Fielding in his aca...
DBIx::Class●   An abstraction for working with DBs●   More than an ORM (Object Relational Mapper) - It knows how to work o...
Mojolicious●   Microframework inspired by Sinatra (Ruby)●   Components of interest (for this app)     ○ Router     ○ Contr...
Routing in MojoliciousIn app context (ie - the startup routine):my $r = $self->routes;#sample route named login for GET - ...
Generic Controller for CRUDOperations●   Each resource needs a controller responsible for it●   Each of those controllers ...
Sample op - update userIn child controller (ExpenseTracker::Controller::User)=head update sample of overriding a default u...
Sample op - update userIn base controller ExpenseTracker::Controllers::Base - the one thatExpenseTracker::Controllers::Use...
Steps for getting RESTfulroutes/operations●   Generate the DBIx::Class model based on the DB table, with DBIx::    Class::...
The EndFork the sample app and play with it:https://github.com/tudorconstantin/expense-tracker
Upcoming SlideShare
Loading in …5
×

RESTful web services

2,256 views

Published on

Published in: Technology
  • Be the first to comment

  • Be the first to like this

RESTful web services

  1. 1. RESTful Web Serviceswith Mojolicious and DBIx::Class
  2. 2. About me● Tudor 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● twitter: @tudorconstantin● gmail: tudorconstantin at gmail dot com
  3. 3. Content● Sample app overview - Expense Tracker● (Short) Intro to RESTful Web Services● DBIx::Class● Mojolicious● Routing in Mojo● Generic Mojo Controller for CRUD operations● Sample operation - update user● Steps for getting RESTful routes/operations for a table in DB
  4. 4. Sample app ExpenseTrackerVERY simple application - but usable (insert expenses, assign categories andsee reports)● Five tables ○ users ○ currencies ○ categories ○ operations ○ operations_categories● Relationships ○ 1 user has many categories ○ 1 user has many operations ○ 1 category has many sub categories ○ 1 category has many operations ○ 1 operation has many categories ○ 1 operation has a currency1 operation belongs to a user
  5. 5. Intro to RESTful WebServicesREST - REpresentational State Transfer ● concept introduced in 2000 by Roy Fielding in his academic dissertation, "Architectural Styles and the Design of Network-based Software Architectures"Main ideas for REST:● Resources are accessible through unique URLs: ○ /user/23 ○ /operations● Use HTTP methods explicitly ○ GET - for Read ○ POST - for Create ○ PUT - for Update ○ DELETE - for Delete● Be stateless ○ the server does not know nor cares about the state of the client application● Transfer Representations of resources (HTML, JSON, XML, etc)
  6. 6. DBIx::Class● An abstraction for working with DBs● More than an ORM (Object Relational Mapper) - It knows how to work on Result Sets● Components - simplified overview: ○ DBIx::Class::Schema - connection to DB ○ DBIx::Class::ResultSet - a query used for fetching a set of results ○ DBIx::Class::Row - objects returned from DBIx::Class::ResultSets using the create, find, next and all methods● Sample usage: my @rows = ExpenseTracker::Models->connect( $config->{database}->{ $mode }->{dsn}, $config->{database}->{ $mode }->{user}, $config->{database}->{ $mode }->{password}, ) # DBIx::Class::Schema ->resultset( ExpenseTracker::Models::Result::User ) # DBIx::Class::ResultSet ->search_rs( { id => 10 }, ) # DBIx::Class::ResultSet - only users with id = 10 ->all(); # The collection of DBIx::Class::Row instances
  7. 7. Mojolicious● Microframework inspired by Sinatra (Ruby)● Components of interest (for this app) ○ Router ○ Controller● Not (quite) interested in: ○ Views (since we render mainly json)● Not provided at all: ○ Models (we plug in and use DBIx::Class)
  8. 8. Routing in MojoliciousIn app context (ie - the startup routine):my $r = $self->routes;#sample route named login for GET - executing method login from controller ExpenseTracker::Controllers::Login$r->get(/login)->to(login#login)->name(login);Shortcut, generic routing:$params->{app_routes}->add_shortcut(resource => sub { my ($r, $name ) = @_; # Generate route for "/$name" - Controller is ExpenseTracker::Controller::camelize($name) my $resource = $r->route( "/$name" )->to("$name#"); # Handle POST requests - will hit the create method in controller $resource->post->to(#create)->name("create_$name"); # Handle GET requests - lists the collection of this resource - hits the list method in controller $resource->get->to(#list)->name("list_$name"); $resource = $r->route( "/$name/:id" )->to("$name#"); $resource->get->to(#show)->name("show_$name"); $resource->delete->to(#remove)->name("delete_$name"); $resource->put->to(#update)->name("update_$name"); return $resource; });
  9. 9. Generic Controller for CRUDOperations● Each resource needs a controller responsible for it● Each of those controllers will have to implement at least 7 actions: ○ create - POST /resource_name - creates a new resource ○ update - PUT /resource_name/:id - updates a resource ○ list - GET /resource_name - show the collection of resources ○ show - GET /resource_name/:id - get the resource with id :id ○ remove - DELETE /resource_name/:id - annihilate resource :id● Possible approaches ○ create a Moose role that will expose all those methods and use this role (I guess) ○ implement a basic controller that will be inherited by all the other resource controller
  10. 10. Sample op - update userIn child controller (ExpenseTracker::Controller::User)=head update sample of overriding a default update methodroute here: PUT /user/:id=cutsub update{ my $self = shift; return $self->render(status => 405, json => {message => You can only update your own profile!!!} ) if ( !defined $self->param(id) or !defined $self->app->user or $self->param(id) != $self->app->user->id ); return $self->SUPER::update(@_);}
  11. 11. Sample op - update userIn base controller ExpenseTracker::Controllers::Base - the one thatExpenseTracker::Controllers::User inherits from: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->req->json ); $result_rs->result_class(DBIx::Class::ResultClass::HashRefInflator); my @result = $result_rs->all(); return $self->render_json( [ @result ] );}
  12. 12. Steps for getting RESTfulroutes/operations● Generate the DBIx::Class model based on the DB table, with DBIx:: Class::Schema::Loader● Create a controller that inherits from ExpenseTracker::Controllers::Base● Add the resource name to the conf.yml
  13. 13. The EndFork the sample app and play with it:https://github.com/tudorconstantin/expense-tracker

×