O slideshow foi denunciado.
Seu SlideShare está sendo baixado. ×

RESTful web services

Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Próximos SlideShares
Mojolicious
Mojolicious
Carregando em…3
×

Confira estes a seguir

1 de 13 Anúncio

Mais Conteúdo rRelacionado

Diapositivos para si (20)

Semelhante a RESTful web services (20)

Anúncio

Mais recentes (20)

RESTful web services

  1. 1. RESTful Web Services with 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 Expense Tracker VERY simple application - but usable (insert expenses, assign categories and see 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 currency 1 operation belongs to a user
  5. 5. Intro to RESTful Web Services REST - 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 Mojolicious In 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 CRUD Operations ● 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 user In child controller (ExpenseTracker::Controller::User) =head update sample of overriding a default update method route here: PUT /user/:id =cut sub 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 user In base controller ExpenseTracker::Controllers::Base - the one that ExpenseTracker::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 RESTful routes/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 End Fork the sample app and play with it: https://github.com/tudorconstantin/expense-tracker

×