Sabin Sabin - 2 months ago 20
Javascript Question

Ember.js - Filter messages

I'm getting the following JSON response on /messages endpoint:

{
"messages": [
{
id: 1,
sender: 2,
receiver: 1,
body: "this is a first comment",
created_at: "2016-09-05 10:00:00",
updated_at: "2016-09-05 10:00:00",
user: 2
},
{
id: 2,
sender: 1,
receiver: 2,
body: "this is a second comment",
created_at: "2016-09-05 11:00:00",
updated_at: "2016-09-05 11:00:00",
user: 2
},
{
id: 3,
sender: 3,
receiver: 1,
body: "this is a first comment",
created_at: "2016-09-05 12:00:00",
updated_at: "2016-09-05 12:00:00",
user: 3
},
{
id: 4,
sender: 1,
receiver: 3,
body: "this is a second comment",
created_at: "2016-09-05 13:00:00",
updated_at: "2016-09-05 13:00:00",
user: 3
},
]
}


These are all the messages the current user has with the other users. The
user
property is the user whom the current user is having the conversation with, whether is receiving from or sending to. I need to filter these messages and get only the last message with each user.

In this example I'll end up with the messages with the id's 1 and 3.

Moving forward I have set up the route
messages/:user_id
and when going to this route you can see all the messages exchanged with that particular user.

If doing the filter I need server side, then when visiting
messages/:user_id
route, all the messages with that user would be loaded in the store. Then when going back to
messages
I get all these messages that were previously loaded in the store.

I've put up an Ember Twiddle to help illustrate this.

I was looking into the mapBy and uniq methods and toying around with them with no success.

Any directions or suggestions are greatly appreciated.

Answer

I would do it using an observer on the controller's model:

export default Ember.Controller.extend({
  appName: 'Ember Twiddle',
  messages: Ember.computed('model', function () {
    return this.get('model').sortBy('created_at').reverse().uniqBy('user');
  }),
});

You can also chain computed properties together if you have a use for the intermediate states:

export default Ember.Controller.extend({
  appName: 'Ember Twiddle',
  sorting: ['created_at:desc'],
  sortedModel: Ember.computed.sort('model', 'sorting'),
  uniqModel: Ember.computed.uniqBy('sortedModel', 'user'),
});

You could also do this filtering in the route:

// routes/application.js
export default Ember.Route.extend({
  model() {
    return messages.sortBy('created_at').reverse().uniqBy('user');
  },
});