Ember.js:计算所有子模型

问题描述:

我的应用有以下型号的财产的总和:Ember.js:计算所有子模型

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

如何计算所有App.User.tweetsUnread的总和,并使其自动更新应用程序.List.tweetsUnread?

下应该这样做。有可能是使用减少一个更简洁的解决方案,但我从来没有使用过它自己:-)

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

更新:这是用减少一个更优雅的解决方案。我从来没有使用它,这不是测试,但我非常有信心,这应该工作:

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

在余烬1.1降低API已经改变了! Thx @joelcox提示,参数initialValue和回调已经改变了它们的位置。所以这里的正确版本的代码:

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

谢谢,减少的伎俩(_edited有点添加ŧ他正确params_) – 2013-04-12 19:13:20

+2

在最近版本的灰烬(至少作为〜1.1),初始值是用于减少方法中的第二个参数。回调是第一个。 http://emberjs.com/api/classes/Ember.Enumerable.html#method_reduce – joelcox 2013-11-14 11:05:51

+0

THX此提示。我已经相应地更新了这篇文章。 – mavilein 2013-11-14 16:03:30

当使用CoffeeScript的,我喜欢用一个行语法,首先得到的属性值阵列.mapBy('propertyName'),然后用一个简单的CoffeeScript reduce

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

另一种选择是使用Ember.computed.sum看到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

这显然是最好的解决办法,所以我不知道为什么它不是在顶部.. – 2015-06-10 06:16:16

+0

@ BlueRaja-DannyPflughoeft因为这么认为,被OP标记为最佳答案的答案应该在最上面! :( – Caltor 2017-11-21 15:53:17