I am using Mongodb (Rails 3 + Mongoid) and Angular JS.
In my db, I have a collection users
which holds an array of objects addresses
. I am trying to update the fields on an address in the array, but when I send the update request (using Angular's resourceProvider
), all the _id
that Angular sends to my server is "{}
" (i.e. empty), so I end up with duplication instead of modification.
$scope.user.addresses holds non-blank ids and looks something like this:
[{_id:{$oid:"123431413243"}, text:"123 fake", cat:1},{_id:{$oid:"789789078907890}, text:"789 test", cat:7},...]
The PUT request body holds empty ids and looks something like this:
{"_id":{}, "user":{"addresses_attributes":[{"_id":{}, "text":"123 fake", "cat":"1"},{"_id":{}, "text":"789 test", "cat":"7"},...]}}
Angular JS code
myApp.factory('Users', ['$resource', function ($resource) {
return $resource( '/users/:id.json', {id:0}, {update: {method:'PUT', _method:'PUT'}} );
}]);
myApp.controller('UsersCtrl', function ($scope, Users) {
$scope.save = function () {
$scope.user.$update({}, {user:$scope.user});
};
});
Do you have any idea why this is and what I can do about it?
It looks like there are two options here: override Angular JS’s transformation behavior or override Mongoid’s serializing behavior.
Option 1: Overriding Mongoid's serializing behavior
Add a file to override serializable_hash
on Mongoid::Document
.
# config/initializers/override_mongoid_serializable_hash.rb
module Mongoid
module Document
def serializable_hash(options={})
attrs = super
attrs['id'] = attrs.delete('_id').to_s
attrs
end
end
end
Don't simply try to override the as_json
method because (for some reason) the new behavior that you define for that function will only apply to the object on which it is called (User), not on the included objects (Addresses).
Option 2: Overriding Angular JS's transforming behavior
Use the instructions in this answer: https://stackoverflow.com/a/12191613/507721
In short, in the call to myApp.config()
in your Angular JS app, set your own function value for $httpProvider.default.transformRequest
. The example from the answer linked above is as follows:
var myApp = angular.module('myApp');
myApp.config(function ($httpProvider) {
$httpProvider.defaults.transformRequest = function(data){
if (data === undefined) {
return data;
}
return $.param(data);
}
});
The body of the foregoing function is up to you. Transform it however is necessary.