I am extending the standard Ember example project (in coffeescript) to talk to an express/mongoose RESTful server. I have successfully fetched all and single records via POSTS using the recommended:
Find GET /people/123
Find All GET /people
Now when attempting to update a record via ember-data PUT, triggered through the Ember adapter.
Update PUT /people/123
And it's not working.
Profiling: client
I am profiling the client side with Chrome dev tools, and server side with console.log. Here is what i'm seeing on the client side. Ember-data makes a PUT and an OPTIONS call to the server.

In the PUT I'm seeing that the payload contains the user edits, and the format looks correct.

The response tab shows a bunch of nonsense, so I'm assuming the problem is on the server side.
Profiling: server
On the server side, when I dump the request variable I get this. The body is received as {post: {}}, i.e. correct structure but empty of content. And the correct mongo id is received.

Here is a stacktrace from the server router:
Trace
at /home/vagrant/restl/node_modules/restgen/lib/routes.js:68:15
at callbacks (/home/vagrant/restl/node_modules/express/lib/router/index.js:161:37)
at param (/home/vagrant/restl/node_modules/express/lib/router/index.js:135:11)
at param (/home/vagrant/restl/node_modules/express/lib/router/index.js:132:11)
at param (/home/vagrant/restl/node_modules/express/lib/router/index.js:132:11)
at pass (/home/vagrant/restl/node_modules/express/lib/router/index.js:142:5)
at Router._dispatch (/home/vagrant/restl/node_modules/express/lib/router/index.js:170:5)
at Object.router (/home/vagrant/restl/node_modules/express/lib/router/index.js:33:10)
at next (/home/vagrant/restl/node_modules/express/node_modules/connect/lib/proto.js:190:15)
at Object.session [as handle] (/home/vagrant/restl/node_modules/express/node_modules/connect/lib/middleware/session.js:301:7)
at next (/home/vagrant/restl/node_modules/express/node_modules/connect/lib/proto.js:190:15)
at Object.cookieParser [as handle] (/home/vagrant/restl/node_modules/express/node_modules/connect/lib/middleware/cookieParser.js:60:5)
at next (/home/vagrant/restl/node_modules/express/node_modules/connect/lib/proto.js:190:15)
at Object.allowCrossDomain [as handle] (/home/vagrant/restl/app.js:21:5)
at next (/home/vagrant/restl/node_modules/express/node_modules/connect/lib/proto.js:190:15)
at Object.methodOverride [as handle] (/home/vagrant/restl/node_modules/express/node_modules/connect/lib/middleware/methodOverride.js:49:5)
at next (/home/vagrant/restl/node_modules/express/node_modules/connect/lib/proto.js:190:15)
at multipart (/home/vagrant/restl/node_modules/express/node_modules/connect/lib/middleware/multipart.js:60:27)
at /home/vagrant/restl/node_modules/express/node_modules/connect/lib/middleware/bodyParser.js:57:9
at urlencoded (/home/vagrant/restl/node_modules/express/node_modules/connect/lib/middleware/urlencoded.js:48:27)
at /home/vagrant/restl/node_modules/express/node_modules/connect/lib/middleware/bodyParser.js:55:7
at IncomingMessage.<anonymous> (/home/vagrant/restl/node_modules/express/node_modules/connect/lib/middleware/json.js:82:9)
at IncomingMessage.EventEmitter.emit (events.js:92:17)
at _stream_readable.js:910:16
at process._tickCallback (node.js:415:13)
What's wrong with my express REST server?
Server side code
Here are the relevant parts of the server code, which is forked from npm restgen.
var express = require('express')
, http = require('http')
, path = require('path')
, restgen = require('restgen');
var app = express()
, mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/rest');
// development only
if ('development' == app.get('env')) {
app.use(express.logger({ format: '\x1b[1m :date \x1b[1m:method\x1b[0m \x1b[33m:url\x1b[0m :response-time ms\x1b[0m :status' }));
}
//CORS middleware
var allowCrossDomain = function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type');
next();
}
// all environments
app.configure(function() {
app.set('root', __dirname);
app.set('port', process.env.PORT || 3000); //3000
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(allowCrossDomain);
app.use(express.cookieParser('your secret here'));
app.use(express.session());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
app.use(restgen.ErrorHandler)
});
restgen.Initialize(app, mongoose);
app.use(function(req, res, next){
next(restgen.RestError.NotFound.insert(req.url));
});
// example of how to throw a 404
app.get('/404', function(req, res, next){
next(restgen.RestError.NotFound.insert(req.url));
});
// example of how to throw a 500
app.get('/500', function(req, res, next){
next(new Error('keyboard cat!'));
});
if(!module.parent) {
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
}
exports.app = app;
Somewhere on the client side the request payload is getting lost. I'm happy to post additional parts of the server side code, such as routes, if it's relevant. Please ask in comments.
Client side code
Here is the Ember side, which I'm pretty sure is correct.
# ===== Adapter =====
# Extended to handle mongo's _id as primarykey
App.Adapter = DS.RESTAdapter.extend(
serializer: DS.RESTSerializer.extend(
primaryKey: (type) -> "_id"
)
)
DS.RESTAdapter.reopen({url: 'http://localhost:3000'});
# ===== Store =====
App.Store = DS.Store.extend(
revision: 12
adapter: App.Adapter
)
# ===== Controller =====
module.exports = App.PostController = Ember.ObjectController.extend
save: ->
@get("store").commit()
@get("target.router").transitionTo "posts.index"
# ==== Model ====
module.exports = App.Post = DS.Model.extend
title: DS.attr 'string'
author: DS.attr 'string'
intro: DS.attr 'string'
extended: DS.attr 'string'
publishedAt: DS.attr 'date'
Update #1
Version information from npm ls
vagrant@precise32:~/brunch-ember$ npm ls
[email protected] /home/vagrant/brunch-ember
├─┬ [email protected]
│ └─┬ [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ └── [email protected]
├─┬ [email protected]
│ └── [email protected]
├─┬ [email protected]
│ └─┬ [email protected]
│ └─┬ [email protected]
│ └── [email protected]
├─┬ [email protected]
│ └── [email protected]
├── [email protected]
├─┬ [email protected] extraneous
│ ├── [email protected]
│ └─┬ [email protected]
│ └─┬ [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ └─┬ [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ └─┬ [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ ├─┬ [email protected]
│ │ │ └── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ └─┬ [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ └── [email protected]
├─┬ [email protected] (git+ssh://[email protected]:bartsqueezy/ember-handlebars-brunch.git#19b9cfd141
│ └── [email protected]
├─┬ [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ └─┬ [email protected]
│ └── [email protected]
├─┬ [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ └─┬ [email protected]
│ │ ├── [email protected]
│ │ ├─┬ [email protected]
│ │ │ └── [email protected]
│ │ └─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └─┬ [email protected]
│ │ └─┬ [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ ├─┬ [email protected]
│ │ │ ├── [email protected]
│ │ │ └── [email protected]
│ │ ├─┬ [email protected]
│ │ │ └── [email protected]
│ │ └─┬ [email protected]
│ │ ├─┬ [email protected]
│ │ │ └── [email protected]
│ │ └─┬ [email protected]
│ │ └── [email protected]
│ └─┬ [email protected]
│ └─┬ [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ └─┬ [email protected]
│ └── [email protected]
├── [email protected]
├─┬ [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ └─┬ [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├─┬ [email protected]
│ │ │ ├── [email protected]
│ │ │ ├── [email protected]
│ │ │ └─┬ [email protected]
│ │ │ └── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├─┬ [email protected]
│ │ │ └─┬ [email protected]
│ │ │ ├── [email protected]
│ │ │ └─┬ [email protected]
│ │ │ └── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected] invalid
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ └─┬ [email protected]
│ │ ├─┬ [email protected]
│ │ │ └── [email protected]
│ │ ├── [email protected]
│ │ ├─┬ [email protected]
│ │ │ ├── [email protected]
│ │ │ ├── [email protected]
│ │ │ └── [email protected]
│ │ └── [email protected]
│ └── [email protected]
├─┬ [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ └─┬ [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ └── [email protected]
├── [email protected]
├─┬ [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ └── [email protected]
├─┬ [email protected]
│ ├── UNMET DEPENDENCY cli-color 0.2.2
│ ├── UNMET DEPENDENCY commander https://github.com/alexferreira/commander.js/tarball/master
│ ├── UNMET DEPENDENCY ejs latest
│ ├── UNMET DEPENDENCY fleck 0.5.1
│ ├── UNMET DEPENDENCY fs-extra 0.6.1
│ └── UNMET DEPENDENCY rsvp-that-works 1.2.0
├── [email protected]
├─┬ [email protected]
│ ├─┬ [email protected]
│ │ └─┬ [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├─┬ [email protected]
│ │ │ ├─┬ [email protected]
│ │ │ │ └── [email protected]
│ │ │ └─┬ [email protected]
│ │ │ └── [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ └─┬ [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ └── [email protected]
├─┬ [email protected]
│ ├── [email protected]
│ └─┬ [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ └── [email protected]
├── [email protected]
└─┬ [email protected]
└─┬ [email protected]
├─┬ [email protected]
│ └── [email protected]
└─┬ [email protected]
└── [email protected]
npm lsto print this out. - Nathan Friedly