public
Last active

Super simple Backbone + Express + MongoDB REST backend application

  • Download Gist
README.md
Markdown

Requirements:

If you're on OSX you're probably best off using Homebrew to install this stuff:

$ brew install node mongodb

Usage:

$ npm install express mongoq
$ node backend.js

I've also attached a sample frontend code for using the backend via Backbone

I highly recommend the Postman Chrome extension for experimenting with REST APIs in which case you can import the attached collection export.

backend.js
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
var express = require('express'),
mongoq = require('mongoq');
 
var db = mongoq('test-database'); // Initialize database
 
var app = express.createServer();
app.use(express.bodyParser()); // Automatically parse JSON in POST requests
app.use(express.static(__dirname + '/public')); // Serve static files from public (e.g http://localhost:8080/index.html)
app.use(express.errorHandler({dumpExceptions: true, showStack: true})); // Dump errors
 
// Add score
app.post('/api/scores', function(req, res) {
var score = req.body;
score.id = Date.now().toString(); // You probably want to swap this for something like https://github.com/dylang/shortid
 
db.collection('scores').insert(score, {safe: true}).done(function(score) {
res.json(score, 201);
});
});
 
// List scores (accepts skip and limit query parameters)
app.get('/api/scores', function(req, res) {
db.collection('scores').find().skip(req.query.skip || 0).limit(req.query.limit || 0).toArray().done(function(scores) {
res.json(scores);
});
});
 
// Read score
app.get('/api/scores/:id', function(req, res) {
db.collection('scores').findOne({id: req.params.id}).done(function(score) {
res.json(score);
});
});
 
// Update score (supports partial updates, e.g only send one field or all)
app.put('/api/scores/:id', function(req, res) {
var score = req.body;
 
db.collection('scores').update({id: req.params.id}, {$set: score}, {safe: true}).done(function(success) {
res.json(success ? 200 : 404);
});
});
 
// Delete score
app.del('/api/scores/:id', function(req, res) {
db.collection('scores').remove({id: req.params.id}, {safe: true}).done(function(success) {
res.json(success ? 200 : 404);
});
});
 
app.listen(8080);
frontend.js
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12
var scores = new Backbone.Collection();
scores.url = 'http://localhost:8080/scores';
scores.fetch(); // Executes a HTTP GET to get scores from server
 
var score = new Backbone.Model();
score.set({'points': 1337, 'name': 'Foo'});
 
scores.add(score); // Executes a HTTP POST to create a new score
 
score.set({'name': 'Bar'}); // Executes a HTTP PUT to update the score
 
score.destroy(); // Executes a HTTP DELETE to remove the score
postman-collection.json
JSON
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
{
"id": "a62b331e-61c9-8891-7f60-abf135c54a9d",
"name": "Scores",
"timestamp": 1331189268220,
"requests": [{
"collectionId": "a62b331e-61c9-8891-7f60-abf135c54a9d",
"id": "71912c90-f23a-f4e0-a822-c9a4402c475f",
"name": "Delete score",
"description": "",
"url": "http://localhost:8080/api/scores/1331189244092",
"method": "delete",
"headers": "",
"data": "",
"dataMode": "raw",
"timestamp": 0
}, {
"collectionId": "a62b331e-61c9-8891-7f60-abf135c54a9d",
"id": "bc36c8d7-ff98-6ceb-31ee-b25524600b57",
"name": "Create dummy score",
"description": "",
"url": "http://localhost:8080/api/scores",
"method": "post",
"headers": "Content-Type: application/json\n",
"data": "{\"points\": 1337, \"name\": \"Foo\"}",
"dataMode": "raw",
"timestamp": 0
}, {
"collectionId": "a62b331e-61c9-8891-7f60-abf135c54a9d",
"id": "c1884e4f-fc23-8242-992e-d027563227c3",
"name": "Update score",
"description": "",
"url": "http://localhost:8080/api/scores/1331189866741",
"method": "put",
"headers": "Content-Type: application/json\n",
"data": "{\n\t\t\"points\": 456,\n\t\t\"name\": \"Bar\"\n}",
"dataMode": "raw",
"timestamp": 0
}, {
"collectionId": "a62b331e-61c9-8891-7f60-abf135c54a9d",
"id": "dfc4c181-e4d3-31fe-144b-eac2adf0278d",
"name": "Get scores",
"description": "",
"url": "http://localhost:8080/api/scores",
"method": "get",
"headers": "",
"data": "",
"dataMode": "raw",
"timestamp": 0
}]
}

Pretty much was looking for something like this all day, so thank you so much!

Would you have any insight on the best way to go about compiling the backbone app in an express project? Here you dont have to worry about it because it's a sing page app, but I'm really struggling to find the best way to go about that. I have seen Trevor Burnham's snockets / rails 3.1 asset clone, and using Alex Maccaw's Hem in conjuction with express, but it's not well documented. Or maybe you just use require.js (which I don't really like) in the public/js folder and build later. I have always just used ruby's middleman for developing backbone apps, but now I'm using express at work to build api's.

Anyways, it has my head spinning, any insight on the normal, easiest way would be awesome.

Again, thank you for this!

Truth be told so far my apps haven't been large enough to require an asset loading strategy. Usually a minified and gzipped collection of scripts is much less than one image on a page so I don't think the optimization is required until your app is huge

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.