Collections

AJAX Abstraction for Lists of Resources

model

The model property is the Model class that resources should be converted to.

Default Implementation

The default implementation looks like this:

import { Model } from 'lore-models';
...
model: Model,

Usage

Most of the time, this property won't be needed, except when you need to transform the data for individual resources returned from the server.

For example, let's say you have an API endpoint located at http://localhost:1337/tweets, that returns a collection of tweets that looks like this:

[
  {
    id: 1,
    text: 'An old tweet'
  },
  {
    id: 2,
    text: 'A new tweet'
  }
]

If you wanted to retrieve those tweets, you could create this collection:

import { Collection } from 'lore-models';

const TweetCollection = Collection.extend({
  urlRoot: 'http://localhost:1337/tweets'
});

const tweets = new TweetCollection();

tweets.fetch();

Once the API call returns, tweet.models would look like this (exactly mirroring the API response, but converted into Models):

[
  new Model({
    id: 1,
    text: 'An old tweet'
  }),
  new Model({
    id: 2,
    text: 'A new tweet'
  })
]

And if we converted that into a raw JSON object using tweets.toJSON() we would see this:

[
  {
    id: 1,
    text: 'An old tweet'
  },
  {
    id: 2,
    text: 'A new tweet'
  }
]

But sometimes you might want to transform that data, such as changing the name or value of a property, as mentioned in the parse() docs for Models (link).

For example, let's say we wanted to add a message field to each model, to resolve a breaking API change. One way to do that would be to account for that in the collection's parse() method like this:

You can do that by defining a parse() like this:

import { Collection } from 'lore-models';

const TweetCollection = Collection.extend({
  urlRoot: 'http://localhost:1337/tweets',

  parse: function(response){
    return response.data.map(function(datum){
      datum.message = datum.text;
      return datum;
    });
  }
});

const tweets = new TweetCollection();

tweets.fetch();

In the code above, we're iterating through the data provided by the API, and modifying the response to include a message attribute that mirrors the text attribute.

Alternatively, we could define that parse method in a custom Tweet Model like this:

import { Model, Collection } from 'lore-models';

const Tweet = Model.extend({
  parse: function(response){
    response.message = response.text;
    return response;
  }
});

const TweetCollection = Collection.extend({
  model: Tweet,

  urlRoot: 'http://localhost:1337/tweets',

  parse: function(response){
    return response.data;
  }
});

const tweets = new TweetCollection();

tweets.fetch();

In this code we've created a custom Tweet Model, and defined a parse() method that knows how to convert a single tweet resource into the format we need. Then, instead of including that logic in the parse() method for the TweetCollection, we can leave it out.

By defining the model for the TweetCollection, the resources will automatically be cast to a Tweet, and once the API call returns tweets.models will be composed like this:

[
  new Tweet({
    id: 1,
    text: 'An old tweet'
  }, { parse: true }),
  new Tweet({
    id: 2,
    text: 'A new tweet'
  }, { parse: true })
]

And calling tweets.toJSON() would provide this:

[
  {
    id: 1,
    text: 'An old tweet',
    message: 'An old tweet'
  },
  {
    id: 2,
    text: 'A new tweet',
    message: 'A new tweet'
  }
]