Skip to content

Instantly share code, notes, and snippets.

@simenbrekken
Created March 8, 2012 06:39
Show Gist options
  • Star 31 You must be signed in to star a gist
  • Fork 12 You must be signed in to fork a gist
  • Save simenbrekken/1999230 to your computer and use it in GitHub Desktop.
Save simenbrekken/1999230 to your computer and use it in GitHub Desktop.
Super simple Backbone + Express + MongoDB REST backend application

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.

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);
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
{
"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
}]
}
@haywoood
Copy link

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!

@simenbrekken
Copy link
Author

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

@lindekaer
Copy link

Thank you! Simple example - just what I needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment