2013-04-10 8 views
14

Moja aplikacja ma następujące modele:ember.js: Oblicz sumę własność wszystkich modeli dziecięcych

App.Store = DS.Store.extend({ 
    revision: 11, 
    adapter: 'DS.FixtureAdapter' 
}); 

App.List = DS.Model.extend({ 
    name: DS.attr('string'), 
    users: DS.hasMany('App.User'), 
    tweetsUnread: function(){ 
     ///////////////////////////////////////// 
     // Code to dynamically calculate the sum 
     // of tweetsUnread property of all 
     // App.User that are related to this list 
     ///////////////////////////////////////// 
    } 
}); 

App.User = DS.Model.extend({ 
    screenName: DS.attr('string'), 
    tweets: DS.hasMany('App.Tweet'), 
    tweetsUnread: function(){ 
     // TODO: check if this is the correct way to do it 
     return this.get('tweets').get('length'); 
    }.property('[email protected]'), 
    list: DS.belongsTo('App.List') 
}); 

App.Tweet = DS.Model.extend({ 
    text: DS.attr('string'), 
    user: DS.belongsTo('App.User') 
}); 

Jak mogę obliczyć sumę wszystkich App.User.tweetsUnread i sprawiają, że automatycznie aktualizować aplikację .List.tweetsUnread?

Odpowiedz

13

Następujące powinno to zrobić. Nie może być bardziej zwięzły rozwiązanie wykorzystujące zmniejszyć, ale nigdy nie zostały wykorzystane siebie :-)

App.List = DS.Model.extend({ 
    name: DS.attr('string'), 
    users: DS.hasMany('App.User'), 
    tweetsUnread: function(){ 
     var users = this.get("users"); 
     var ret = 0; 
     users.forEach(function(user){ 
      ret += users.get("tweetsUnread"); 
     }); 
     return ret; 
    }.property("[email protected]") 
}); 

Aktualizacja: Jest to bardziej eleganckie rozwiązanie używając zmniejszyć. Nigdy nie używał go i to nie jest badana, ale jestem całkiem pewny, że to powinno działać:

App.List = DS.Model.extend({ 
    name: DS.attr('string'), 
    users: DS.hasMany('App.User'), 
    tweetsUnread: function(){ 
     var users = this.get("users"); 
     return users.reduce(0, function(previousValue, user){ 
      return previousValue + users.get("tweetsUnread"); 
     }); 
    }.property("[email protected]") 
}); 

W Ember 1.1 API dla zmniejszenia się zmieniło! Thx @joelcox dla podpowiedzi, że parametry initialValue i callback zmieniły swoją pozycję. Więc tutaj poprawna wersja kodu:

App.List = DS.Model.extend({ 
    name: DS.attr('string'), 
    users: DS.hasMany('App.User'), 
    tweetsUnread: function(){ 
     var users = this.get("users"); 
     return users.reduce(function(previousValue, user){ 
      return previousValue + user.get("tweetsUnread"); 
     }, 0); 
    }.property("[email protected]") 
}); 
+0

Dzięki, zmniejszyć wystarczyły (_edited trochę dodawania t on poprawne params_) –

+2

W ostatnich wersjach Ember (co najmniej jako ~ 1.1), wartość początkowa jest drugim argumentem dla metody redukcji. Oddzwanianie jest pierwsze. http://emberjs.com/api/classes/Ember.Enumerable.html#method_reduce – joelcox

+0

Thx za tę podpowiedź. Odpowiednio zaktualizowałem wpis. – mavilein

3

Podczas korzystania coffeescript, lubię używać składni jedna linia, pierwsza coraz tablicę wartości nieruchomości z .mapBy('propertyName') a następnie za pomocą prostego coffeescript reduce:

@get('users').mapBy('tweetsUnread').reduce (a, b) -> a + b 
36

Innym rozwiązaniem byłoby wykorzystanie Ember.computed.sum zobaczyć here

App.List = DS.Model.extend({ 
    name: DS.attr('string'), 
    users: DS.hasMany('App.User'), 

    tweetsUnread: Ember.computed.mapBy('users', 'tweetsUnread'), 
    totalTweetsUnread: Ember.computed.sum('tweetsUnread') 
}); 
+2

To oczywiście najlepsze rozwiązanie, więc nie jestem pewien, dlaczego nie jest na górze .. –

+0

@ BlueRaja-DannyPflughoeft, ponieważ SO uważa, że odpowiedź oznaczona jako najlepsza odpowiedź OP powinna być na górze! :( – Caltor

Powiązane problemy