2013-04-10 10 views
14

Meine Anwendung folgende Modelle hat:Ember.js: Berechnen Sie die Summe einer Eigenschaft aller Kind Modelle

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') 
}); 

Wie kann ich die Summe aller App.User.tweetsUnread berechnen und machen es automatisch App aktualisieren .List.tweetsUnread?

Antwort

13

Folgendes sollte es tun. Es könnte eine prägnante Lösung reduzieren mit, aber ich habe es selbst nie

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]") 
}); 

aktualisieren :-)

verwendet: Dies ist eine elegantere Lösung unter Verwendung reduzieren. Ich habe es nie benutzt, und dies ist nicht getestet, aber ich bin sehr zuversichtlich, dass dies funktionieren soll:

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]") 
}); 

In Ember 1.1 die API für reduziert geändert hat! Thx @joelcox für den Hinweis, dass die Parameter initialValue und Callback ihre Position geändert haben. Also hier die richtige Version des Codes:

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

Dank zu verwenden wäre, reduzieren den Trick tat (_edited ein wenig t hinzufügen Er korrigiert params_) –

+2

In neueren Versionen von Ember (mindestens ab 1.1) ist der Anfangswert das zweite Argument für die reduce-Methode. Der Rückruf ist der erste. http://emberjs.com/api/classes/Ember.Enumerable.html#method_reduce – joelcox

+0

Thx für diesen Hinweis. Ich habe den Beitrag entsprechend aktualisiert. – mavilein

3

Wenn Coffeescript verwenden, Ich mag die einzeilige Syntax verwenden, zunächst die Eigenschaftswerte Array mit .mapBy('propertyName') bekommen und dann mit einem einfachen Coffee reduce:

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

eine weitere Option Ember.computed.sum siehe 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

Dies ist offensichtlich die beste Lösung, also bin ich mir nicht sicher, warum es nicht an der Spitze ist .. –

+0

@ BlueRaja-DannyPflughoef weil SO glaubt, dass die Antwort als beste Antwort des OP markiert sollte an der Spitze sein! :( – Caltor

Verwandte Themen