Ember.js: Calculate the sum of a property of all child models

只谈情不闲聊 提交于 2020-01-01 02:27:09

问题


My application has the following models:

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('tweets.@each'),
    list: DS.belongsTo('App.List')
});

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

How can I calculate the sum of all App.User.tweetsUnread and make it automatically update App.List.tweetsUnread?


回答1:


The following should do it. There might be an more concise solution using reduce, but i have never used it myself :-)

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("users.@each.tweetsUnread")
});

Update: This is a more elegant solution using reduce. I have never used it and this isn't tested but i am quite confident that this should work:

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("users.@each.tweetsUnread")
});

In Ember 1.1 the API for reduce has changed! Thx @joelcox for the hint, that the parameters initialValue and callback have changed their position. So here the correct version of the code:

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("users.@each.tweetsUnread")
});



回答2:


Another option would be to use Ember.computed.sum see 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')   
});



回答3:


When using coffeescript, I like to use the one-line syntax, first getting the property values array with .mapBy('propertyName') and then using a simple coffeescript reduce:

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


来源:https://stackoverflow.com/questions/15933633/ember-js-calculate-the-sum-of-a-property-of-all-child-models

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!