2012-10-26 14 views
14

Deve esserci qualcosa di semplice che mi manca qui.Backbone/Underscore chain method with where metodo

http://jsfiddle.net/v9mdZ/

sto solo imparando Backbone e Underscore/loDash e sto cercando di prendere confidenza con chain.

Ho il seguente codice, che funziona come previsto:

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

ho cercato di refactoring questo, utilizzando chain in questo modo:

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

Perché non funziona il codice di refactoring? Sto usando chain sbagliato?

Solution (dettagli sotto)

non utilizzare where con chain.

risposta

18

La fusione di some Underscore methods in raccolte è un po 'imperfetta. Quando dici collection.some_mixed_in_underscore_method(), la raccolta scartala alcuni elementi della Backbone dietro la schiena in modo che il metodo Underscore sia applicato agli attributi all'interno dei modelli della collezione; E 'sorta di funziona così:

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

Ma collection.chain() non funziona così, chain avvolge solo la collezione di models direttamente, quindi se si esegue questa operazione:

console.log(collection.chain()); 

vedrai che chain è dandoti un oggetto che avvolge una serie di modelli. I tuoi modelli non avranno una proprietà is_checked (ad esempio non c'è model.is_checked), ma avranno gli attributi is_checked (ad esempio, ci sarà model.get('is_checked') e model.attributes.is_checked).

Ora possiamo vedere dove tutto va male:

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

I modelli non hanno is_checked proprietà. In particolare, non ci saranno modelli in cui is_checked è true e tutto ciò che segue lo where funziona con un array vuoto.

Ora che sappiamo dove vanno le cose di lato, come lo ripariamo? Beh, si potrebbe usare filter invece di where in modo che si può facilmente decomprimere i modelli:

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

Ma, i vostri modelli non hanno id s ancora come non hai creato loro con id s e si rifugio' Ho parlato con un server per ottenere id s in modo da ottenere una serie di undefined s indietro. Se si aggiungono alcuni id s:

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

allora si otterrà il [1,2] che stai cercando.

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

+0

Ottima spiegazione. Grazie! Nel mio ambiente attuale, la raccolta viene prelevata dal server, quindi hanno ID. – Bart

+0

'pluck' avrà lo stesso problema per la maggior parte degli attributi perché non chiama' model.get() 'ma guarda direttamente gli attributi del modello. 'id' è un attributo speciale che viene definito sull'oggetto, quindi funzionerà ma altri attributi, come' is_checked' restituiranno 'undefined'. – Spig