Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to populate a Backbone model from multiple URLs

I would like to use a single Backbone Model that is composed of data from different URL endpoints. Is it possible to specify multiple URLs within a single model? I'd like to avoid calling AJAX by hand.

Until now, I've been using jQuery Deferreds to call multiple URLs and synthesize their results into a single object.

I can think of two options so far: building a Backbone model with a partial model for each URL, or using one URL and then overriding Model.fetch() to call the other URLs. But neither one makes me comfortable.

(Or I can try to bribe the API developer to provide a merged URL endpoint...)

like image 872
Gingi Avatar asked Jan 23 '13 03:01

Gingi


1 Answers

I think both of the ways you suggested are quite reasonable, but personally I'd vote for the fetch approach.

Using nested models has the advantage of working "out of the box"; in other words, by using one model for every server <=> client mapping you avoid having to change any Backbone.Model methods. The problem with this approach though is that you wind up with a conglomeration of multiple models.

If that makes sense anyway (data retrieval aside) then stick to nested models. But if not you're forcing the rest of your code to work with several models instead of just one solely to keep your data retrieval code simple. If you'd rather just complicate the data retrieval code and keep everything else simple then you're better off overwriting fetch.

fetch does one thing, and that is retrieve data via a one-to-one mapping between it and a remote URL. If you want a one-to-many mapping instead it makes perfect sense to just override the default fetch behavior. Plus you know it's reasonably safe to override fetch because it's name isn't _fetch, and Backbone uses the the underscore style to name it's pseudo-private methods (eg. _validate).

If you still don't like either of those approaches, there is one other option: request events. The latest version of Backbone has a new event called request that is triggered whenever a fetch is started. What this means is that you can setup an event handler that retrieves your secondary data in response to the primary data's request, like so:

Backbone.Model.extend({
    initialize: function() {
        this.on('request', this.handleRequest);
        _.bindAll(this, 'handleTriggeredResponse');
    },
    handleRequest: function() {
        $.ajax({url: secondDataUrl, complete: this.handleTriggeredResponse});
        $.ajax({url: tertiaryDataUrl, complete: this.handleTriggeredResponse});
    },
    handleTriggeredResponse: function(response) {
        this.set(response.data);
    },
    url: firstDataUrl
});
like image 186
machineghost Avatar answered Oct 26 '22 18:10

machineghost