I have a small REST API that is being consumed by a single page web application powered by Backbone.js
There are two resource types that the API provides, and therefore, the Backbone app uses. These are articles and comments. These two resources have different endpoints and there is a link from each of the articles to the location of all the comments for that item.
The problem that I'm facing is that, on the article list in my web app I would like to be able to display the number of comments for each article. Given that that would only be possible if I also get the comments list, on the current setup, would require me to make one API request to get the the initial article list and another one for each of the articles to be able to count the number of comments. That becomes a problem if, for instance, there are 100 articles, and therefore 101 HTTP requests would be necessary to populate one single view.
The solutions I can think of right now are:
1. to include the comments data in the initial articles request like so
{
{
"id": 1,
"name": "Article 1",
...
"comments": {
{
"id": 1,
"text": "some comment"
},
{
"id": 2,
"text": "some comment"
},
...
}
},
}
The question in this case is: How is it possible to parse the "comments" as a separate comments collection and not include it into the article model?
2. to include some metadata inside the articles response like so:
{
{
"id": 1,
"name": "Article 1",
...
"comments": 13
},
}
Option that raises the question: how should I handle the parse of the model so that, on one hand the meta information is available, and on the other hand, the "comments" attribute is not one Backbone would try to perform updates on?
I feel there might be another solution, compliant with the REST philosophy, for this that I'm missing, so if you have any other suggestion please let me know.
I think your best bet is to go with your second option, include the number of comments for each article inside your article model.
Option that raises the question: how should I handle the parse of the model so that, on one hand the meta information is available, and on the other hand, the "comments" attribute is not one Backbone would try to perform updates on?
Not sure what your concern is here. Why would you be worried about the comments attribute getting updated?
I can't think of any other "RESTy" way of achieving your desired result.
I would suggest using alternative 2 and have the server return
a subset of the article attributes that are deemed useful for
applications when dealing with the article collection resource
(perhaps reachable at /articles
).
The full article member resource with all its comments (whether
they are stored in separate tables in the backend) would be
available at /articles/:id
).
From a Backbone.js point of view you probably want to put the
collection resource in a, say, ArticleCollection
which will
convert each member (currently with a subset of the attributes)
to Article
models.
When the user selects to view an article in full you pull it
out from the ArticleCollection
and invoke fetch
to populate
it in full.
Regarding what to do with extra/virtual attributes that are included
in the collection resource (/articles
) like the comment count and
possibly other usefult aggregations, I see a few alternatives:
- In
Article#initialize
you can pull those out from the attributes
and store them as meta-data on the article. This way the built-in
Backbone.Model#toJSON
will not see them.
- Keep them in the
attributes
section of each model and override
Backbone.Model#toJSON
to exlcude them when "serializing" an Article
.
In atlernative 1, an Article#commentCount()
helper could return
this._commentCount || this.get('comments').length
to make it work
on both partially and fully loaded articles.
For a fully loaded Article
you would probably want to convert the
nested comments
array into a full-blown CommentCollection
anyway
and store that in this._comments
so I don't think it is that unusual
to have your models store additional stuff directly on the model instance,
outside of its attributes
hash.