How do I get a model from a Backbone.js collection by its id? - javascript

In my app, everything I do with data is based on the primary key as the data is stored in the database. I would like to grab a model from a collection based on this key.
Using Collection.at() requires the array index, Collection.getByCid() requires the client ID that backbone randomly generates.
What is the best way to grab the model I want from the collection with the given id value? I figure the worst I could do would be to iterate over each item, .get('id'), and return that one.

Take a look at the get method, it may be of some help :)
http://backbonejs.org/#Collection-get
get collection.get(id)
Get a model from a collection, specified by an id, a cid, or by passing in a model.

If your data requires you to use a different kind of key or a set that doesn't mesh well with at(), getByCid() or get(), there is also where(). Something like this might work:
window.lib = new Library;
window.lib.fetch([
success: function(model, response) {
console.log(window.lib.where({'BookID':488, 'Rev':2, 'Status':'Active'});
}
});

Related

nodejs Cycle and callback

Recently i wrote a blog with nodejs,when it comes to add some tags to posts,problems occured.In my view, the relation between posts and tags is many-to-many,each post has several tags,in turn,each tag also match to some posts.So i create a tag collection and a post collection in mongodb.
exports.Post=mongolass.model("Post",{
author:{type:Mongolass.Types.ObjectId,ref:"User"},
title:{type:"string"},
content:{type:"string"},
pv:{type:"number"},
tagIds:[{tagId::Mongolass.Types.ObjectId}]
});
exports.Tag=mongolass.model("Tag",{
tagName:{type:"string"}
});
exports.Tag.index({tagName:1},{unique:true}).exec();
and store the tag as an array in posts.As we know,when i create a post, i will get the post's tagName from html by method POST,so i have to use
getTagByName:function getTagByName(tagName){
return Tag.find({tagName:tagName}).exec();
}
to get the object tag,and use
TagModel.getTagByName(tagName).then(function(tag){
var postToTag={
postId:postId,
tagId:tag[0]._id
};
to get the tagId,Unfortunately, as a post has many tags,so i have to use a for cycle to get all tagId of a post, i also want to collect these tagIds to an Array, thus i can push it to my Post model, but the cycle and callback make it difficult.
any advice is appreciated.

In creating a primary key in a Forerunner database collection, can the key property live inside of an object of the collection object?

I have a work-around, however I'm wondering why this is failing - is it a JavaScript error on my part?
My app uses two models. I'm using Forerunner to persist a JSON model that is previously created in my MVC.
I want to store the Forerunner primary key in an object, to make it clearer (in my first model) that the key is used only in the Forerunner model.
The key will need to be saved in both models, so that when the first model changes, I can immediately update the Forerunner model - it is the link between two models.
Here is a code sample to illustrate:
var games = db.collection("games", {
primaryKey: "gamedb._id"
});
games.insert({
gamedb : {
_id: 1,
},
userDesc : "original 11x11",
Size : [11,11],
Plays : []
.
.
}, function (result) {
console.log(result);
});
I did try it out, and got confusing results, so for now I'm just leaving the key as property of the collection.
Here is the console.log result of my attempt using the above code sample. The forerunner insert() did not fail.
I'm confused about the property 'gamedb._id : "225b...".
Thanks for any suggestions or insight.
gamedb : Object
_id: 1
gamedb._id: "225b3c25aeb38a0",
}
.
.
Primary keys in ForerunnerDB must currently be in the root of the object. When you tell it to make the primary key "gamedb._id" it is not parsing that string as a path, it is assuming you are passing that as a root key e.g. {"gamedb._id": myId}
There are plans to update ForerunnerDB to allow nested primary keys, but this is not currently possible.
Source: I wrote ForerunnerDB

Bookshelf.js set attribute not in database

I have a Bookshelf.js model. I want to be able to set and get attributes for this model that are not persistent in the database.
For instance lets say I have a model that looks like this:
var Domain = bookshelf.Model.extend({
tableName: 'domains',
initialize: function() {
this.on('creating', this.setDomainName);
},
setDomainName: function() {
this.set('name', getDomainFromUrl(this.url));
}
});
With a schema that looks like this:
knex.schema.createTable('domains', function (table) {
table.increments().index();
table.text('name').index();
table.timestamps();
});
I want to be able to save an attribute called url, then later parse the url into a domain before it saves.
When I try something like this:
new Domain({url: 'http://someurl.com/foo/bar'}).save()
I get the error message:
"column \"url\" of relation \"domains\" does not exist"
I've looked and looked. I cant find any way to add non-persistent attributes to a bookshelf.js model. I also couldn't find anything about adding custom getter and setter methods to a bookshelf.js model.
Any help or insight is appreciated!
On my phone, so forgive the short reply, but what you want is called 'virtual' or 'composite' fields.
https://github.com/tgriesser/bookshelf/wiki/Plugin:-Virtuals
Every database mapper has them, but when you don't know what they're called it's understandably difficult to google a solution.

I'm getting a "newItem() was not passed an identity for the new item" error while trying to add a new item to a JSON store

I've seen other posts in this site regarding the same issue and I've tried the solutions given. I've also visited the links that may offer a solution but I'm still stuck with the same error.
I'm using DOJO and something as simple as this won't even work
myStore.newItem({id: 'test', otherfield: 'otherinfohere'});
myStore.save();
Supposedly the "newItem() was not passed an identity for the new item" error appears when you haven't provided an identifier for the new item, which i have.
The whole purpose of this (Just in case anyone can provide a good idea or has done something similar before) is that i want to create a data grid that shows info from a particular store. The problem is, that in that store all the items may not have the same structure. For instance:
I may have a store that looks like this
{identifier: 'id',
label: 'name',
items: [
{ id:'1', name:'Ecuador', capital:'Quito' },
{ id:'2', name:'Egypt', capital:'Cairo' },
{ id:'3', name:'El Salvador', capital:'San Salvador' , additionalField: 'otherinfohere'},
{ abbr:'gq', name:'Equatorial Guinea', capital:'Malabo', additionalField: 'otherinfohere'},
]}
This is possible because I'm the one constructing the store in a Spring Controller (I'm also using the Spring Framework) from information I have locally stored in a Berkeley DB. So what i need is a data grid with a dynamic layout because I don't want blank spaces to show in the view in the rows with lesser amount of fields, and i need to show all the info in the store at the same time, but i don't know how to do this.
I thought of doing it by creating a simple layout of only 1 field. In it I would load data from a store i create dynamically at runtime. The data in the store would be composed of HTML combined with the values coming from the original store so I could obtain something like this, which is inside an attribute of a JavaScript Object and let the browser parse it for me:
<div><span>id: originalID </span>....</div>
This of course is a simple example, the html layout i'm looking for is far more complicated, but i think that passing it as a string to an object might do the trick.
The problem is that i don't even know if that idea will work because i get that error whenever i try to add values to my secondary store.
rdb.modules.monitor.historicStore.fetch({onComplete: function(items, request){
for (var i = 0; i < items.length; i++){
var item = items[i];
var obj = new Object();
obj.id = rdb.modules.monitor.historicStore.getValue(item, "id");;
var html = "<div><span>";
html += rdb.modules.monitor.historicStore.getValue(item, "sql");
html += "</span></div>";
obj.html = html;
myStore.store.newItem(obj);
}
}});
In this context "historicStore" refers to the JSON store that has the values that i need to convert and add to "myStore" after i added some HTML.
I hope you got the main idea of what I'm trying to do. If anyone can help me we either of these problems i would really appreciate it. Thanks in advance
For the issue regarding store:-
"id" is mandatory for a store, if it is going to be used for a grid(datagrid, EnhancedGrid, etc. whatever). The items are handled only on basis of "id" attribute by the grid data structures.
Usually, id can be a loop variable/ auto incrementation, to avoid any cases like you have said. Before adding the store to the grid, ensure that all items have the id attribute. You can write a function which will loop through each item and check for this, else add an auto-incrementing value for the id attribute of that item.

Fetch Backbone Collection by Model IDs list

I have a REST API serving a few URLs:
/rest/messages
provides all messages. A message is a JSON/Backbone Model
{
title: 'foo',
body : 'bar'
}
To get a single message I have:
/rest/messages/:id
Is it possible to fetch a Backbone Collection using message IDs array? I don't want the whole message list, but just a few messages I specify by ID.
I could fetch Models one-by-one and fill up the Collection, but I'm wondering if Backbone has a cleaner way to do this.
Thanks
According to documentation, you can pass ajax options to the fetch call. So, you can pass ids as data attribute to the fetch call being done and based on it, return the respective models from the server.
For example (when doing fetch),
collection.fetch({
data : {
message_ids : [1, 3, 5] // array of the message ids you want to retrieve as models
}
})
This message_id array will be accessible as parameters (not sure of the name in your case) in the server code being executed at /rest/messages, from there you can return only specific models based on ids you receive as message_ids. The only thing you need is, client side must be aware of the ids of all the message models it needs.
You can use any data structure instead of array to send message_ids.
The url property of collection reference to the collection location on the server. When you use fetch, backbone uses that url.
The url property can be also a function that returns the url. So you can do something like that:
var ids = [1,2,3]
var messages = new MessegecCollection();
messages.url = function() {
return "/rest/messages/"+ids.join("-"); //results "/rest/messages/1-2-3"
}
messages.fetch();
You can also create a method in your collection that generated and set the url, or even fetchs a set of models.
Now all you have to do is to support this url: /rest/messages/1-2-3
Hope this helps!

Categories

Resources