2012-10-26 7 views
14

Es muss etwas Einfaches sein Ich vermisse hier.Backbone/Underscore-Ketten-Methode mit, wo Methode

http://jsfiddle.net/v9mdZ/

Ich lerne gerade Backbone und Unders/loDash und ich versuche, mit chain vertraut zu machen.

Ich habe den folgenden Code, der wie erwartet funktioniert:

var ids = _.pluck(collection.where({'is_checked':true}), 'id'); 

ich das Refactoring versucht, mit chain wie so:

var ids = collection.chain().where({'is_checked':true}).pluck('id').value(); 

Warum funktioniert die Refactoring-Code arbeiten? Benutze ich chain falsch?

Solution (Details unten)

Verwenden where nicht mit chain.

Antwort

18

Die Zusammenführung von some Underscore methods in Sammlungen ist ein wenig unvollkommen. Wenn Sie collection.some_mixed_in_underscore_method() sagen, wird ein Teil des Backbone-Materials hinter der Rückseite von der Sammlung abgewickelt, sodass die Underscore-Methode auf die Attribute in den Modellen der Sammlung angewendet wird. es ist eine Art, wie das funktioniert:

var ary = _(this.models).map(function(m) { return m.attributes }); 
return _(ary).some_mixed_in_underscore_method(); 

Aber collection.chain() nicht so funktioniert, chain wickelt nur die Sammlung des models direkt so, wenn Sie dies tun:

console.log(collection.chain()); 

Sie sehen, dass chain ist Sie erhalten ein Objekt, das eine Reihe von Modellen umschließt. Ihre Modelle haben keine is_checked Eigenschaft (d. H. Es gibt keine model.is_checked), sie werden jedoch is_checked Attribute haben (d. H. Es wird model.get('is_checked') und model.attributes.is_checked geben).

Jetzt können wir sehen, wo alles schief geht:

collection.chain().where({'is_checked':true}) 

Die Modelle haben keine is_checked Eigenschaften. Insbesondere wird es keine Modelle geben, bei denen is_checkedtrue ist und alles nach dem where mit einem leeren Array arbeitet.

Nun, da wir wissen, wo die Dinge seitwärts gehen, wie reparieren wir es? Nun könnte man filter statt where verwenden, so dass Sie leicht die Modelle entpacken:

collection.chain() 
      .filter(function(m) { return m.get('is_checked') }) 
      .pluck('id') 
      .value(); 

Aber Ihre Modelle haben nicht id s noch, wie Sie sie nicht erstellt haben mit id s und Sie haven‘ Ich habe mit einem Server gesprochen, um id s zu bekommen, so dass du ein Array von undefined zurück bekommst. Wenn Sie einige id s hinzufügen:

var collection = new App.OptionCollection([ 
    {id: 1, 'is_checked': true}, 
    {id: 2, 'is_checked': true}, 
    {id: 3, 'is_checked': false} 
]); 

dann werden Sie die [1,2] erhalten, die Sie suchen.

Demo: http://jsfiddle.net/ambiguous/kRmaD/

+0

Hervorragende Erklärung. Vielen Dank! In meiner tatsächlichen Umgebung wird die Sammlung vom Server abgerufen, daher haben sie IDs. – Bart

+0

'pluck' wird das selbe Problem für die meisten Attribute haben, da es nicht' model.get() 'aufruft, sondern stattdessen direkt auf die Attribute des Modells schaut. "id" ist ein spezielles Attribut, das für das Objekt definiert ist, so dass es funktioniert, aber andere Attribute wie "is_checked" geben "undefined" zurück. – Spig