Last active
March 4, 2016 18:14
-
-
Save emilniklas/04ba843f2cbebf508845 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
dependencies: | |
embla: ^0.1.13 | |
embla_trestle: ^0.1.0 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:async'; | |
import 'package:embla/http.dart'; | |
import 'package:embla/http_annotations.dart' as http; | |
import 'package:embla/http_basic_middleware.dart'; | |
import 'package:embla_trestle/embla_trestle.dart'; | |
export 'package:embla/bootstrap.dart'; | |
get embla => [ | |
// As a default, the DatabaseBootstrapper connects to an in-memory database. | |
// This is configurable in this constructor. | |
new DatabaseBootstrapper(), | |
new HttpBootstrapper( | |
pipeline: pipe( | |
// Since we will be receiving POST and PUT requests, we must parse the | |
// request body first. This middleware will make it possible to inject | |
// an Input object in the handlers. | |
InputParserMiddleware, | |
// This routes the entire PostsController to the /posts namespace. | |
Route.all('posts/*', PostsController) | |
) | |
) | |
]; | |
/// The [Model] superclass is provided by Trestle, whose API is exposed | |
/// via the embla_trestle import. | |
class Post extends Model { | |
@field String title; | |
@field String body; | |
/// For convenience | |
void apply(Map<String, dynamic> map) { | |
title = map['title'] ?? title; | |
body = map['body'] ?? body; | |
} | |
} | |
class PostsController extends Controller { | |
final Repository<Post> posts; | |
/// We use Dependency Injection to inject the Trestle Repository | |
PostsController(this.posts); | |
/// A method with the name [index] is automatically bound to the | |
/// root of the current routing namespace. So the annotation below | |
/// is equivalent to | |
/// | |
/// @http.Get('/') | |
/// // or | |
/// @http.Get('') | |
@http.Get() index() { | |
return posts.all(); | |
} | |
/// If we type annotate the wildcard parameter with [int] it will | |
/// only be provided if the wildcard is numeric (^\d+$). Else it | |
/// be set to null. The [_findById] method helps with this case. | |
@http.Get(':id') show({int id}) { | |
return _findById(id); | |
} | |
/// Thanks to the [InputParserMiddleware] we can inject the [Input] | |
/// object, whose [body] property will contain the body of the request. | |
/// | |
/// We use that to create a new Post, and save it to the database. | |
@http.Post('') store(Input input) async { | |
final post = new Post() | |
..apply(input.body); | |
await posts.save(post); | |
return post; | |
} | |
/// Update is similar to store, but instead of creating a new | |
/// [Post], we find the one with the provided id and update it. | |
@http.Put(':id') update(Input input, {int id}) async { | |
final post = (await _findById(id)) | |
..apply(input.body); | |
await posts.save(post); | |
return post; | |
} | |
/// Deleting is trivial. | |
@http.Delete(':id') delete({int id}) async { | |
final post = await _findById(id); | |
await posts.delete(post); | |
return { 'message': 'OK' }; | |
} | |
/// This method is a convenience method to get the [Post] with the | |
/// provided [id] out of the database. | |
Future<Post> _findById(int id) async { | |
// If the id is null, that means the wildcard did not match ^\d+$, | |
// so we can return a 400 message (Bad Request). | |
if (id == null) { | |
abortBadRequest({ 'message': 'The id must be numeric' }); | |
} | |
// The find method below will get the first Post it can find with | |
// the id. If it find none it will throw a StateError, so we'll | |
// have to catch that. | |
try { | |
return await posts.find(id); | |
} on StateError { | |
abortNotFound({ 'message': 'No post has an id of $id' }); | |
} | |
} | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:async'; | |
import 'package:embla/http.dart'; | |
import 'package:embla/http_annotations.dart' as http; | |
import 'package:embla/http_basic_middleware.dart'; | |
import 'package:embla_trestle/embla_trestle.dart'; | |
export 'package:embla/bootstrap.dart'; | |
get embla => [ | |
new DatabaseBootstrapper(), | |
new HttpBootstrapper( | |
pipeline: pipe( | |
InputParserMiddleware, | |
Route.all('posts/*', PostsController) | |
) | |
) | |
]; | |
class Post extends Model { | |
@field String title; | |
@field String body; | |
void apply(Map<String, dynamic> map) { | |
title = map['title'] ?? title; | |
body = map['body'] ?? body; | |
} | |
} | |
class PostsController extends Controller { | |
final Repository<Post> posts; | |
PostsController(this.posts); | |
@http.Get() index() { | |
return posts.all(); | |
} | |
@http.Get(':id') show({int id}) { | |
return _findById(id); | |
} | |
@http.Post('') store(Input input) async { | |
final post = new Post() | |
..apply(input.body); | |
await posts.save(post); | |
return post; | |
} | |
@http.Put(':id') update(Input input, {int id}) async { | |
final post = (await _findById(id)) | |
..apply(input.body); | |
await posts.save(post); | |
return post; | |
} | |
@http.Delete(':id') delete({int id}) async { | |
final post = await _findById(id); | |
await posts.delete(post); | |
return { 'message': 'OK' }; | |
} | |
Future<Post> _findById(int id) async { | |
if (id == null) { | |
abortBadRequest({ 'message': 'The id must be numeric' }); | |
} | |
try { | |
return await posts.find(id); | |
} on StateError { | |
abortNotFound({ 'message': 'No post has an id of $id' }); | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment