2013-04-10 49 views
14

我的應用有以下型號的財產的總和: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?

回答

13

下應該這樣做。有可能是使用減少一個更簡潔的解決方案,但我從來沒有使用過它自己:-)

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

3

當使用CoffeeScript的,我喜歡用一個行語法,首先得到的屬性值陣列.mapBy('propertyName'),然後用一個簡單的CoffeeScript reduce

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

另一種選擇是使用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