Backbone.js sents an POST on updated objects instead of an PUT.
I think this is because mongoDB uses _id instead of id.
How do I say backbone.js to use _id instead of id?
I already tried some server-side change but I think it would be easier just to say that backbone should use another attribute as id.
MongoDB: output 'id' instead of '_id'
From the fine manual http://backbonejs.org/#Model-idAttribute
idAttribute model.idAttribute
A model's unique identifier is stored under the id attribute. If you're directly communicating with a
backend (CouchDB, MongoDB) that uses a different unique key, you may
set a Model's idAttribute to transparently map from that key to id.
Id attribute can be changed per model like
var Meal = Backbone.Model.extend({
idAttribute: "_id"
});
To make it default for all models (eg., if we are using mongodb), override the default setting by placing this LOC in your app js file that runs after backbone.js
//override the id attribute for model
Backbone.Model.prototype.idAttribute = '_id';
Related
I am using backbone with Node and Express. I have my restful api set up to return my model and collection data. The api works fine. But I'm having trouble binding a route to one of my api paths.
I have a company model and collection so that when go to the routes you get the restful api data for that route:
http://localhost:3000/employees you get the data for restful api path api/employees
http://localhost:3000/employees/1 you get the data for restful api path api/employees/1
I also have a category model and collection to do the same:
http://localhost:3000/categories you get the data for restful api path api/categories
but the following does not work:
http://localhost:3000/categories/Auto you don't get the data for restful api path api/cateogries/Auto The restful api works and returns the right data, but the collection I get in my app returns the same data as the category collection called with the path api/cateogries. Almost like the path gets ignored.
Typically you have a collection and then you provide a id attribute to get a model that belongs to that collection. But what if you want a collection whose id attribute returns another collection? For example, you get a list of categories and then when you select a category you get a list of all the companies in that category? What is the right way to do this in backbone?
Thanks. I actually figured it out. I was returning a collection and needed to adust the url of my collection to point it to the correct path in my restful api. So in my collection I added a url function that goes to a different route if a parameter is passed into the constructor:
url:function(){
if(this.category1){
return "api/categories/"+this.category1;
}
return "api/categories";
},
initialize:function(opts){
this.category1=opts && opts.category1;
}
I'm trying to PUT the data and my model doesn't have an id.
Is it possible to explicitly tell the Save() method to PUT the data irrespective of ID.
The save method has an options parameter that can override anything on the XHR:
model.save(newVals, { type: 'PUT' })
You can also override the isNew method. PUT vs POST is determined by the result of that method. You'll also want to make sure the URL is being created correctly for new and non-new objects.
Also consider setting the idAttribute correctly so that your model does have an id field that can be used to generate a correct url. Using POST and PUT correctly (POST new items, PUT updates to items) makes your api more intuitive.
is it possible to fetch on backbone, by a different attribute?
Now I can only fetch by ID which will return /url/IDVALUE
is is possible to do
model.fetch({name:'VALUE'});
and then it will generate the /url/NAMEVALUE ?
Thanks.
this is a workaround and I think you should use this just to do the fetch but I think it can work
change the IdAttributte and use the name,
then when you fetch your model the url will use the name attribute
http://backbonejs.org/#Model-idAttribute
var Model = Backbone.Model.extend({
idAttribute: "name"
});
Is always equivalent use one or the other?
These prints in console same things
class Model extends Backbone.Model
defaults:
some: 'thing'
other: 'item'
model = new Model
console.log model.attributes
console.log model.toJSON()
toJSON() is a standard method that the JavaScript JSON serializer looks for when serializing an object.
In the context of Backbone, if you override toJSON in your model you can change the format of values which get sent to the server when saving. For example you could filter out read only fields like time stamps.
attributes is the JavaScript object containing the model data, that's what gets altered when you use model.set(). Except if you don't use set() to alter values, then you bypass all the events and loose some of the benefits of backbone. So only use attributes directly if you know what you're doing.
I have the following Backbone.js collection:
var Tags = Backbone.Collection.extend({
url: "/api/v1/tags/"
}),
How do I update one of the models in the collection so that it posts to /api/v1/tags/id and saves the data for that model.
So if I change name of model with id 2 in the collection
It should PUT to
/api/v1/tags/2 with the following data:
name: new name id: 2
I've also recently wanted to update particular model in the collection. The problem was that if I did use just model.save it didn't update the collection. The goal was to change the model in collection, change it on the server, update collection accordingly and not use the sync method. So for example I have my variable collection and I want to change the model with id = 2. So the first thing, I will create an instance model, like this: var model = collection.get(2)Then I will update the attributes on this particular model:model.set({name: 'new name'})Then I will save it to the server:model.save({}, {url:'/api/v1/tags/'+model.get('id')})Then we have to update collection accordingly to the changes:collection.set({model},{remove: false})set method - it's a 'smart' update of the collection with the list of the models you passed in parameters. remove: false parameter - it's a restriction for a collection to remove existing models in collection. More here.
The first thing you can miss is that in your corresponding Tag model you'll need to set "urlRoot" to match the Collection's "url". Otherwise it doesn't know about the collection at all:
var Tag = Backbone.Model.extend({
urlRoot: "/api/v1/tags"
});
var Tags = Backbone.Collection.Extend({
model: Tag,
url: "/api/v1/tags"
});
This is useful if you want to save the tag separately:
var tag = collection.get(2);
tag.set({key: "something"});
tag.save(); // model.save works because you set "urlRoot"
On the collection, "create()" is also "update()" if id is not null. That's not confusing. :) Therefore, this is pretty much equivalent to the previous sample:
collection.create({id: 2; key: "something"});
This will update the existing tag with id=2 and then trigger a PUT.
This is an ancient question; answering because I was searching for the same answer--you've probably long since solved this problem and moved on. :)
You can pass variables to the save method. It accepts all the options which jQuery's ajax method uses (unless you overrided Backbone.Sync)
You could do something like:
model.save( { name:'new name' } );
The id and PUT method will automatically be added by Backbone for you.