4
votes

I have ember models called survey, question, and response. surveys have multiple questions, which have multiple responses. Each response has an attribute count.

How do I set a total_response_count computed value in the survey model? In emberjs 1.0.0, the questions are in a DS.PromiseArray (due to the async: true), so when I return the computed value, it shows up in my template as an Object rather than a value.

I can easily access responses from the question model because responses are embedded in question. However, Ember automatically makes promises for the questions referenced by survey because {async: true}.

Survey Model:

App.Survey = DS.Model.extend({
  title: DS.attr('string'),
  owner_id: DS.belongsTo('user'),
  questions: DS.hasMany('question', {async:true}),

  total_responses: function() {
    var question_cb = function(prevValue, item) {
      return prevValue + item.get('total_responses');
    };

    return this.get('questions').then(function(questions){
      return questions.reduce(question_cb, 0);
    });
  }.property('questions')
});

Question Model:

App.Question = DS.Model.extend({
  survey: DS.belongsTo('survey'),

  question: DS.attr('string'),

  responses: DS.hasMany('response'),

  total_responses: function() {
    var response_cb = function(prevValue, item) {
      return prevValue + item.get('count');
    };

    return this.get('responses').reduce(response_cb, 0);
  }.property('responses')
});

Response Model:

App.Response = DS.Model.extend({
  response: DS.attr('string'),
  count: DS.attr('number'),

  question: DS.belongsTo('question')
});

I'm using ember-1.0.0 and ember-data 1.0 beta-2.

1
Can you try calling reduce directly on the this.get('questions') PromiseArray?Bradley Priest
I did; it doesn't work because it tries to reduce the PromiseArray directly, and since it's an "array of length 0" it returns 0.az_
How about computing from both questions and questions.isFulfilled?Bradley Priest
How would I do that? Where is the data located when the promise is fulfilled? I couldn't find it in inspect element.az_
Have you tried to compute the property based on questions.@each ?andrei1089

1 Answers

6
votes

I also asked this question on Github, and got this response from Yehuda Katz:

You can try something like this:

App.Survey = DS.Model.extend({
  title: DS.attr(),
  owner: DS.belongsTo('user'),
  questions: DS.hasMany({ async:true }),

  totalResponses: Ember.arrayComputed('questions', {
    initialValue: 0,
    addedItem: function(accum, item) {
      accum += item.get('totalResponses');
    },
    removedItem: function(accum, item) {
      accum -= item.get('totalResponses');
    }
  })
});

When questions resolves, the addedItem callback in totalResponses will be called once for every item in the resolved array.