2013-04-10 33 views
14

ứng dụng của tôi có các mô hình sau:Ember.js: Tính tổng của một tài sản của tất cả các mô hình con

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

Làm thế nào tôi có thể tính toán tổng của tất cả App.User.tweetsUnread và làm cho nó tự động cập nhật ứng dụng .List.tweetsUnread?

Trả lời

13

Sau đây nên làm điều đó. Có thể có một giải pháp ngắn gọn hơn dùng giảm, nhưng tôi chưa bao giờ sử dụng nó bản thân mình :-)

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

Cập nhật: Đây là một giải pháp thanh lịch hơn khi sử dụng giảm. Tôi chưa bao giờ sử dụng nó và điều này không được kiểm tra nhưng tôi khá tự tin rằng điều này sẽ làm việc:

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

Trong Ember 1.1 API cho giảm đã thay đổi! Thx @joelcox cho gợi ý, rằng các tham số initialValue và callback đã thay đổi vị trí của chúng. Vì vậy, đây đúng phiên bản của mã:

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

Cảm ơn, giảm đã làm các trick (_edited một chút để thêm t ông sửa params_) –

+2

Trong các phiên bản gần đây của Ember (ít nhất là ~ 1.1), giá trị ban đầu là đối số thứ hai cho phương thức giảm. Gọi lại là lần đầu tiên. http://emberjs.com/api/classes/Ember.Enumerable.html#method_reduce – joelcox

+0

Thx cho gợi ý này. Tôi đã cập nhật bài đăng cho phù hợp. – mavilein

3

Khi sử dụng coffeescript, tôi muốn sử dụng cú pháp một dòng, đầu tiên nhận được các mảng giá trị tài sản với .mapBy('propertyName') và sau đó sử dụng một coffeescript đơn giản reduce:

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

một lựa chọn khác là sử dụng Ember.computed.sum thấy 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

Đây rõ ràng là giải pháp tốt nhất, vì vậy tôi không chắc chắn lý do tại sao nó không ở trên cùng .. –

+0

@ BlueRaja-DannyPflughoeft vì SO tin rằng câu trả lời được đánh dấu là câu trả lời hay nhất của OP nên ở trên cùng! :( – Caltor

Các vấn đề liên quan