Given an id how can I get the next/previous of a recordset relative to that id?

I wrote some really awkward code earlier which basically filters through each item in the recordset on some condition and then selects the edge one.

export default Ember.Route.extend({
  model(params){
    const stories = this.store.findAll('story');

    const story = this.store.findRecord('story', params.id);

    const nextStory = story.then(function(story){
      const laterStories = stories.filter(function(filterStory){
        return filterStory.get('number') > story.get('number');
      });
      if(laterStories.get('firstObject')){
        return laterStories.get('firstObject');
      }else{
        return stories.get('firstObject');
      }
    });

    const previousStory = story.then(function(story){
      const newerStories = stories.filter(function(filterStory){
        return filterStory.get('number') < story.get('number');
      });
      if(newerStories.get('lastObject')){
        return newerStories.get('lastObject');
      }else{
        return stories.get('lastObject');
      }
    });
    return Ember.RSVP.hash({
      story,
      nextStory,
      previousStory
    });
  }
});

I know, it looks awful, there must be a nicer way of doing that. Any suggestions?

I just tossed this together, obviously didn’t have anything to test it against. But I would have written something like this:

export default Ember.Route.extend({
  model(params){
    const stories = this.store.findAll('story');

    return stories.then(stories => {
      const story = stories.findProperty('id', params.id),
            storyIndex = stories.indexOf(story);

      return {
        previousStory: (stories.objectAt(storyIndex-1) || stories.get('firstObject')),
        story: story,
        nextStory: (stories.objectAt(storyIndex+1) || stories.get('lastObject'))
      };
    });
  }
})

This takes advantage of the simplifying assumption that findAll will include the routed story. Since that’s the case, you just find it’s index in the list and look on either side of that index.

1 Like

Cool that works with some minor modifications.

  • I wanted it to cycle through.
  • findProperty isn’t a property on stories but findBy is.
  • Order is by the number property and not by id.
export default Ember.Route.extend({
  model(params){
    const stories = this.store.findAll('story');
    return stories.then(stories =>{
      stories = stories.sortBy("number");
      const story = stories.findBy('id', params.id),
        storyIndex = stories.indexOf(story);
      return {
        previousStory: (stories.objectAt(storyIndex - 1) || stories.get('lastObject')),
        story: story,
        nextStory: (stories.objectAt(storyIndex + 1) || stories.get('firstObject'))
      };
    });
  }
});

:+1: to all of those changes.

I missed the part about it cycling around and findProperty is what happens when you write an example without testing it :stuck_out_tongue: