Collection.Find method (probable) bug
Closed this issue · 7 comments
Hi Artemi.
I was trying to find a model in a collection, passing some of its attributes, but without the id.
Contrary to my expectations, the collection's find method yielded "undefined", although I was certain that there was the model whose attributes I was looking for.
I think I may have found a possible issue.
Changing (from line 80 onwards)
isEqual: function(attr) { for (var key in attr) { if (!isEqual(attr[key], this[key])) return false; } return true; },
To
isEqual: function(attr) { for (var key in attr) { if (isEqual(attr[key], this[key])) return true; } return false; },
made it possible to find a model in a collection, by passing some of its attributes (without the id).
Sorry, Artemi. Made a mistake. Cannot make find method to look for models in a collection without passing the id
This may be the problem:
// find index of matching object, eg: findIndex({ id: 1 }); findIndex: function(attr) { var items = this.items, isEqual = Model.prototype.isEqual, id; if (this.idAttribute in attr) id = this.idAttribute; for (var i = 0, len = items.length; i < len; i++) { if (id) { if (attr[id] === items[i][id]) return i; } else if (isEqual.call(attr, items[i])) return i; } return -1; },
I changed the elseif part from:
else if (isEqual.call(attr, items[i])) return i;
to:
else if (isEqual.call(items[i], attr)) return i;
And collection find method works (I think) as expected
good post, i ended up making my own .matching(matchingobj) method because i had the same problem
op i think you want .filter. find only works with the "id" attribute.
so
mycoll.find({id: 123})
or
mycoll.filter(function (item, i) { if (item.myprop == 'whatever') return true; return false; })
or you can make your own matches function like this
Espresso.Collection.prototype.matching = function(matchObj){
var keys = Object.keys(matchObj)
return this.filter(function(x){
for (var i = 0; i < keys.length; i++) {
if(typeof(x[keys[i]]) === 'undefined' || x[keys[i]] !== matchObj[keys[i]])
return false
}
return true
})
}
c = new Espresso.Collection( [{id:0, misc:true}] )
console.log(c.matching({misc:true}) // [ { id: 0, misc: true } ]
anyway passing this on to artemi, im not a JS expert
tbh i have no idea about .call and .apply but heres what i found:
obj1 = { id:0, b: 2 }
console.log( isEqual(obj1, obj1) ) // true
console.log( isEqual.call(obj1, obj1) ) // false
isEqual.call and isEqual return different things on chrome, .call always returns false
bumping for OP, i think you want .filter() -- i edited my post above with an explanation.
Thanks for spotting the bug, just pushed a fix