I have a Backbone model:
var User = Backbone.Model.extend({
idAttribute: '_id',
url: '/api/user',
defaults:
{ username: ''
}
});
I fetch it:
var user = new User();
user.fetch();
Now, as an click
event in one of my views, I have this:
toggleSubscription: function () {
user.set('subscriptions', true);
user.save();
}
This causes a POST request. However, the record already exists on the server, and since I fetched it (and the model instance has an id
property), I thought that Backbone should do a PUT instead of a POST. Why might it be doing a POST instead?
Try checking user.isNew()
.
Looks like you created a new model which does not have an ID, that's why it's trying to add it during Backbone.sync
.
UPDATE:
Above is exactly true. It does POST
because it's a new model (which means, it does not have an id). Before you fetch a model, you need to give it an id. In your example:
var user = new User();
user.fetch();
user.save(); // in XHR console you see POST
var user = new User({ id: 123 });
user.fetch();
user.save(); // in XHR console you see PUT
if the model does not yet have an id, it is considered to be new. --http://backbonejs.org/#Model-isNew
if the model does not yet have an id, it is considered to be new... AND therefore backbone will do a PUT
request rather than a POST
.
This behavior can be overridden simply by adding type: 'POST'
to your save block:
var fooModel = new Backbone.Model({ id: 1});
fooModel.save(null, {
type: 'POST'
});
Use urlRoot property to set base URL /api/user
. Then
- it will POST to
/api/user
when you save a model which doesn't have _id
property set
and
- it will PUT to
/api/user/{_id}
when you save a model which has _id
property set. Notice that it automatically appends _id
value to the base URL.
It will look for value of _id
property because you have set that value to idAttribute
.
The server response must be in this way:
{
_id : 111
}
Because you set _id as the primary key. When model is fetched verify the value of _id it must have a value:
console.log( model.get('_id') );
My thought is that you set in your backbone model '_id' as primary key, but service is returning you 'id'
Update: Adding sample code of normal behavior:
var UserModel = Backbone.Model.extend({
idAttribute: '_id',
url: '/api/user',
defaults:
{ username: ''
}
});
user = new UserModel({_id : 20});
user.save();
user = new UserModel();
user.save();
Output:
PUT /api/user 405 (Method Not Allowed)
POST /api/user 404 (Not Found)
Check how the first instance of the Model has an id and it tries to do the PUT but the other POST. I cannot reproduce your issue, so my thought is that the problem is on your server response.
It may be worth checking if maybe emulateHTTP
is true. This will change all your PUT into POST with an added _method
header (you may also want to check that this exists to confirm the idea).