Permalink
Browse files

converted from localStorage to mongodb (via mongoose) backend storage

  • Loading branch information...
1 parent 0ced6ad commit 248c6bfc6c5c0abcb3f23031e19b981ded613e34 @swbiggart committed Jan 10, 2012
View
@@ -1,3 +1,4 @@
node_modules
.monitor
-.DS_Store
+.DS_Store
+todos.css
View
@@ -1,7 +1,23 @@
-Node.js, Coffee, Express, Jade, Stylus, Backbone, RequireJS Todo App
+Node.js, Coffee, Express, Mongoose, Jade, Stylus, Backbone, RequireJS Todo App
---
This is a conversion of
[addyosmani's modular-todo-app](https://github.com/addyosmani/backbone-fundamentals/tree/master/practicals/modular-todo-app) from his
[backbone-fundamentals](https://github.com/addyosmani/backbone-fundamentals) book.
+Install
+
+```
+git clone git@github.com:swbiggart/node-coffee-express-requirejs-backbones-todo.git
+cd node-coffee-express-requirejs-backbones-todo
+npm install coffee-script -g
+npm install
+coffee app.coffee
+```
+
+Make sure you have mongodb installed. If you don't, on a Mac use Homebrew:
+
+```
+brew install mongodb
+```
+and follow the instructions.
View
@@ -1,15 +1,19 @@
-
express = require('express')
-routes = require('./routes')
+mongoose = require('mongoose')
+models = require('./models')
+app = module.exports = express.createServer()
-app = module.exports = express.createServer();
+#connect to mongodb
+mongodb_url = process.env.MONGOHQ_URL || 'mongodb://localhost/todo'
+mongoose.connect mongodb_url
# Configuration
app.configure ->
app.set 'views', __dirname + '/views'
app.set 'view engine', 'jade'
app.set 'view options', { pretty: true }
+ app.use express.logger()
app.use express.bodyParser()
app.use express.methodOverride()
app.use require('stylus').middleware { src: __dirname + '/public' }
@@ -24,7 +28,12 @@ app.configure 'production', ->
app.use express.errorHandler()
# Routes
+routes = require('./routes')
app.get '/', routes.index
+app.post '/todos', routes.create
+app.get '/todos', routes.read
+app.put '/todos/:_id', routes.update
+app.del '/todos/:_id', routes.delete
port = process.env.PORT || 3000
app.listen port, ->
View
@@ -0,0 +1 @@
+module.exports = require('./todo')
View
@@ -0,0 +1,9 @@
+mongoose = require('mongoose')
+Schema = mongoose.Schema
+ObjectId = Schema.ObjectId;
+
+Todo = new Schema
+ content: String
+ done: Boolean
+
+module.exports = mongoose.model 'Todo', Todo
View
@@ -1,10 +1,10 @@
{
- "name": "require-js-boiler"
+ "name": "node-coffee-express-backbone-requirejs-todo"
, "version": "0.0.1"
- , "private": true
, "dependencies": {
"express": "2.5.2"
, "stylus": ">= 0.0.1"
, "jade": ">= 0.0.1"
+ , "mongoose": ">= 2.0.0"
}
}
@@ -1,16 +1,15 @@
depends = [
'underscore',
'backbone',
- 'libs/backbone/localstorage',
'cs!models/todo'
]
-define depends, (_, Backbone, Store, Todo) ->
+define depends, (_, Backbone, Todo) ->
TodosCollection = class extends Backbone.Collection
# Reference to this collection's model.
model: Todo
- # Save all of the todo items under the `"todos"` namespace.
- localStorage: new Store "todos"
+ # url to read todos from
+ url: '/todos'
# Filter down the list of all todo items that are finished.
done: ->
@@ -1,88 +0,0 @@
-define(['underscore', 'backbone'], function(_, Backbone){
-
-// A simple module to replace `Backbone.sync` with *localStorage*-based
-// persistence. Models are given GUIDS, and saved into a JSON object. Simple
-// as that.
-
-// Generate four random hex digits.
-function S4() {
- return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
-};
-
-// Generate a pseudo-GUID by concatenating random hexadecimal.
-function guid() {
- return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4());
-};
-
-// Our Store is represented by a single JS object in *localStorage*. Create it
-// with a meaningful name, like the name you'd give a table.
-var Store = function(name) {
- this.name = name;
- var store = localStorage.getItem(this.name);
- this.data = (store && JSON.parse(store)) || {};
-};
-
-_.extend(Store.prototype, {
-
- // Save the current state of the **Store** to *localStorage*.
- save: function() {
- localStorage.setItem(this.name, JSON.stringify(this.data));
- },
-
- // Add a model, giving it a (hopefully)-unique GUID, if it doesn't already
- // have an id of it's own.
- create: function(model) {
- if (!model.id) model.id = model.attributes.id = guid();
- this.data[model.id] = model;
- this.save();
- return model;
- },
-
- // Update a model by replacing its copy in `this.data`.
- update: function(model) {
- this.data[model.id] = model;
- this.save();
- return model;
- },
-
- // Retrieve a model from `this.data` by id.
- find: function(model) {
- return this.data[model.id];
- },
-
- // Return the array of all models currently in storage.
- findAll: function() {
- return _.values(this.data);
- },
-
- // Delete a model from `this.data`, returning it.
- destroy: function(model) {
- delete this.data[model.id];
- this.save();
- return model;
- }
-
-});
-
-// Override `Backbone.sync` to use delegate to the model or collection's
-// *localStorage* property, which should be an instance of `Store`.
-Backbone.sync = function(method, model, options) {
-
- var resp;
- var store = model.localStorage || model.collection.localStorage;
-
- switch (method) {
- case "read": resp = model.id ? store.find(model) : store.findAll(); break;
- case "create": resp = store.create(model); break;
- case "update": resp = store.update(model); break;
- case "delete": resp = store.destroy(model); break;
- }
-
- if (resp) {
- options.success(resp);
- } else {
- options.error("Record not found");
- }
-};
-return Store;
-});
View
@@ -15,4 +15,4 @@ require.config({
require(['cs!views/app'], function(AppView){
var app_view = new AppView;
-});
+});
@@ -1,6 +1,12 @@
define ['underscore', 'backbone'], (_, Backbone) ->
TodoModel = class extends Backbone.Model
-
+
+ #use _id instead of id to work with mongodb
+ idAttribute: "_id"
+
+ # UrlRoot to CRUD against
+ urlRoot: '/todos'
+
# Default attributes for the todo.
defaults:
content: "empty todo..."
@@ -15,9 +21,9 @@ define ['underscore', 'backbone'], (_, Backbone) ->
toggle: ->
@save {done: !@get("done")}
- # Remove this Todo from *localStorage* and delete its view.
+ # Remove this Todo from server and delete its view.
clear: ->
- @destroy()
- @view.remove()
-
- TodoModel
+ @destroy
+ success: (model, response) =>
+ @view.remove()
+
@@ -25,7 +25,7 @@ define depends, ($, _, Backbone, Todos, TodoView, statsTemplate) ->
# At initialization we bind to the relevant events on the `Todos`
# collection, when items are added or changed. Kick things off by
- # loading any preexisting todos that might be saved in *localStorage*.
+ # loading any preexisting todos that might be saved on server.
initialize: ->
_.bindAll @, 'addOne', 'addAll', 'render'
@@ -65,7 +65,7 @@ define depends, ($, _, Backbone, Todos, TodoView, statsTemplate) ->
}
# If you hit return in the main input field, create new **Todo** model,
- # persisting it to *localStorage*.
+ # persisting it to server.
createOnEnter: (e) ->
if e.keyCode != 13
return
@@ -89,6 +89,3 @@ define depends, ($, _, Backbone, Todos, TodoView, statsTemplate) ->
return
show = -> tooltip.show().fadeIn()
@tooltipTimeout = _.delay show, 1000
-
- AppView
-
@@ -69,6 +69,4 @@ define depends, ($, _, Backbone, todosTemplate) ->
# Remove the item, destroy the model.
clear: ->
- @model.clear()
-
- TodoView
+ @model.clear()
View
@@ -1,2 +1,26 @@
+Todo = require('mongoose').model('Todo')
+
exports.index = (req, res) ->
res.render 'index', { title: 'Todos' }
+
+exports.create = (req, res) ->
+ todo = new Todo req.body
+ todo.save (err) ->
+ if err
+ res.send err
+ res.send todo
+
+exports.read = (req, res) ->
+ Todo.find {}, (err, docs) ->
+ if err
+ res.send err
+ res.send docs
+
+exports.update = (req, res) ->
+ delete req.body._id #remove _id from put so mongodb doesn't complain
+ Todo.update {_id: req.params._id}, req.body, (err) ->
+ res.send err
+
+exports.delete = (req, res) ->
+ Todo.remove {_id: req.params._id}, (err) ->
+ res.send err

0 comments on commit 248c6bf

Please sign in to comment.