Backbone.js collection getting multiple models - backbone.js

You can get a model from the collection by using collection.get(id);
but i want to get mulitple models. The get only gets 1 models.
I now use this piece of code, but it doesn't look pretty or feels good for performance. Anyone knows a better way to select an array of models from the collection?
var models = this.collection.filter(function(model){
return _.indexOf([1,2,3,4], model.get('id')) > -1;
});

Since you just need 4 items, your code iterate whole collection.
Following code is better performance by iterating only size 4 array.
var models = _.map([1,2,3,4], function(id) {
return collection.get(id);
});

Related

How to efficiently get a collection that contains multiple nested collections

Title might not be the best, an improvement would be much appreciated!
What i mean is actually very simple question:
Say i have a School class containing an array of Students that has an array of Notebooks, and i want to refer all the Notebooks in my School
public class School{
students: Student[];
}
public class Student{
notebooks: Notebook[]
}
How should i refer to all of the Notebooks in my school?
Looking for a more efficient way from saving all the Notebooks in a separate array achieved with a for loop..
Thanks in advance :)
It all depends on what you want to do with the output or each individual notebook? This function closely replicates to for loops without all the boilerplate.
school.students.forEach(function(student) {
student.notebooks.forEach(function(notebook) {
doSomethingWithNotebook(notebook);
});
});
// this returns all notebooks for all students and puts it into a single (flat) array
var allNotebooks = school.students.reduce(function(collection, student) {
return collection.concat(sudent.notebooks);
}, []);
// now you can do things like filter out only New notebooks
var newNotebooks = allNotebooks.filter(notebook => notebook.isNew);
Conceptually, my reflex would be to look for something like an n-dimensional array/matrix, think
myMatrix[ [school][student][notebook[]] ]
(but with valid syntax),
and then figure out how to pull myMatrix[[anything][anything][Notbooks[]]].
This would end up avoiding the for loop, but anything that's going to let you select all of the 3nested elements I'm pretty dang sure is going to be just as complex with those elements stored nested or not.
Not a definitive answer per se, but without more details on what you need, the best I can do is offer up avenues of thought.

How do I modify/enrich an Eloquent collection?

I'm using eloquent relationships.
When I call $carcollection = $owner->cars()->get(); I have a collection to work with. So let's say that I have, for this particular owner, retrieved three cars. The collection is a collection of three arrays. Each array describes the car.
This is all working fine.
Now I want to add more attributes to the array, without breaking the collection. The additional attributes will come from a different source, in fact another model (e.g. servicehistory)
Either I retrieve the other model and then try merge() them, or I try manipulate the arrays within the collection without breaking the collection.
All this activity is taking place in my controller.
Is one way better than another, or is there a totally different approach I could use.... perhaps this logic belongs in the model themselves? Looking for some pointers :).
Just to be specific, if you do $owner->cars()->get(); you have a collection of Car Models, not array.
That have been said, you can totally load another relation on you Car model, using
$carcollection = $owner->cars()->with('servicehistory')->get();
$carcollection->first()->servicehistory;
You can try to use the transform method of the collection.
$cars = $owner->cars()->get();
$allServiceHistory = $this->getAllService();
$cars->transform(function($car) use($allServiceHistory) {
// you can do whatever you want here
$car->someAttribute = $allServiceHistory->find(...):
// or
$car->otherAttribute = ServiceHistoryModel::whereCarId($car->getKey())->get();
});
And this way, the $cars collection will be mutated to whatever you want.
Of course, it would be wiser to lazy load the data instead of falling into an n+1 queries situation.

Backbone: pluck models with an array of IDs, and save them

So I have an array of IDs:
var myIDs = [1,5,9];
I have a collection that I want to search through, and pluck from. I thought I could do something like the following:
var searchResults = myCollection.where({"uID" : myIDs});
Of course that won't work, but there must be a way to achieve something similar.
Once I have the selected models, the plan is to edit the contents of, then save. Am I correct in assuming I can save the whole batch by doing the following?
myCollection.reset(searchResults);
I'm a total n00b to Backbone, obviously.
You can use Collection.filter to compare each item against the array:
var searchResults = myCollection.filter(function(model) {
return myIDs.indexOf(model.id) != -1;
});
("Where" is like a special case of "filter", with a specific iterator -- it compares the properties of each model with the hash set you provide.)
As far as saving, if you mean replacing the items in the collection, then yes, you can use reset for that. (Note that "save" in Backbone parlance normally means syncing model updates back to the server.)

How to alter a backbone.js collection using equivalent of .slice(start, end)

My Backbone Collection receives 30 models on fetch().
I have tried
newColl=origColl.first(2);
to return a new Collection. When I try to pass to the View it won't work.
Is there anyway to do this using an underscore.js method?
Your code doesn't work likely because first(n) returns an array while your view is expecting a collection. You need to wrap it like this:
var newColl = new Backbone.Collection(origColl.first(2));
For a general "slice" you can use find in conjunction with _.range:
var newColl = new Backbone.Collection(origColl.find(_.range(start, end));
Naturally, tou can use your own collection class instead of Backbone.Collection.
See the documentation of range at http://documentcloud.github.com/underscore/#range.
I am not sure I understand your question correctly, but the following snippet might be what you are looking for.
var model = origColl.at(2);
var models = [model];
var newColl = new YourCollection(models);
newColl will now be a new collection containing the model at position 2 of your original collection. The example is a bit more verbose than I would write it, but it might make it clearer for you.

How can I access to some model in Backbone collection

I have a collection of models:
city = new M.City
App.citiesList = new C.CitiesList model: city
App.citiesList.fetch()
How can I access to the model with id=15 for example?
I need something like App.citiesList.find(15).name(), where name() is model function
When I try to add function find to the collection it is incorrect.
When I try to iterate over App.citiesList.models - I see only one model or what it is.. I actually don't know.
Thanks a lot!
If App.citiesList is a Backbone collection then you'd want to use get:
get collection.get(id)
Get a model from a collection, specified by id.
So this would get you your model from the collection:
fifteen = App.citiesList.get 15
And if you wanted to call a method on it:
App.citiesList.get(15).name()
You'd probably want to make sure you got something back from App.citiesList.get 15 first though (unless you knew it was there of course). Since you're working in CoffeeScript you could use the existence operator like this:
name = App.citiesList.get(15)?.name()
#----------------------------^
to get 15's name or undefined in the name variable.
The find method on App.citiesList would be Underscore's find and that doesn't find an object with a particular ID.

Resources