Ok, so I figured it out. The two problems I were having were:
1) instead of updating the existing item in the database, it was creating a new one with the same ID but in string format instead of using the ObjectId format.
2) any time I called $update, it would not append the ID to the path, but always PUT to /cards.
So here are the solutions to each of the problems.
1) This is really a hack that assumes that ALL id are in ObjectId format. I don't like this solution but for now it works and I am sticking to it. All I had to do was to add the line that converts the card._id back to ObjectId format to the updateCard function inside the cards.js file on the server side.
exports.updateCard = function(req, res) {
var id = req.params.id;
var card = req.body;
console.log('Updating card: ' + id);
console.log(JSON.stringify(card));
card._id = new BSON.ObjectID.createFromHexString(card._id); // HACK!
db.collection('cards', function(err, collection) {
collection.update({'_id':new BSON.ObjectID(id)}, card, {safe:true}, function(err, result) {
if (err) {
console.log('Error updating card: ' + err);
res.send({'error':'An error has occurred'});
} else {
console.log('' + result + ' document(s) updated');
res.send(card);
}
});
});
}
2) This was a two part fix. First, I had to modify the services.js file to explicitly say that I want to use update via PUT:
var mindrServices = angular.module('mindrServices', ['ngResource']);
mindrServices.factory("Card", ["$resource",
function($resource) {
return $resource("http://localhost:3000/cards/:cardId", {cardId:"@id"},
{
query: {method: "GET", isArray:true},
update: {method: "PUT"}
}
);
}]);
Next, I was under the assumption that simply calling currentCard.$update() would grab the ID from the calling instance, instead I have to explicitly pass in the ID as follows:
var mindrControllers = angular.module('mindrControllers', []);
mindrControllers.controller('CardsController', ["$scope", "Card",
function ($scope, Card) {
$scope.cards = Card.query();
console.log("cards populated correctly...");
$scope.processCard = function(currentCard, currentAction) {
console.log("processCard: card[" + currentCard._id + "] needs to be moved to [" + currentAction.next + "] state... ");
currentCard.state = currentAction.next;
currentCard.$update({cardId: currentCard._id}); // passing the ID explicitly
}
This is the output I get on the server side:
Updating card: 52910eb526f1db6a13915d9c
{"_id":"52910eb526f1db6a13915d9c","content":"this is some content for this really cool card","workflow":"simple","state":"backlog"}
1 document(s) updated
PUT /cards/52910eb526f1db6a13915d9c 200 4ms - 111b