Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

Simplify fetching single models (aka incremental collection fetching) #1242

kevindente opened this Issue Apr 20, 2012 · 5 comments


None yet
3 participants

This is somewhat related to issue #78, but some things have changed since then, so I think it's worth another look.

I'm finding it a bit clunkier than I'd like to take a partially populated collection, fetch a new model by ID, and add it to the collection. It's quite possible I'm missing something something here, I'm no Backbone expert. The two approaches I've found are:

  1. Create a new model instance, specifying the the id in the constructor, and call fetch on it. This works, but has the problem that the initialize method has already been called when the model data is loaded. In my case, initialize does some stuff like creating child collections and populating them from attributes, but there's no data to work with yet because it hasn't been fetched. I considered using parse to do some of the init work, but the sequencing is reversed in the two cases - initialize is called first when creating a model then fetching, but parse is called first when a collection is doing the fetching.

  2. Use Collection.fetch with the "add" option set. This one is SO close to perfect, but there's no simple way to specify the ID of a model to load (in particular when using RESTful URLs where the ID is part of the base URL, not query string params). I sort of kludged it by specifying the ".url" option on the call to fetch, and building the URL manually by concatenating the collection URL with the model ID. It works, but again seems clunky.

One solution would be to specify an ID to collection.fetch (maybe as simple as options.id). Then along with add: true, you would have simple incremental collection loading.

Or maybe there's a better solution for single model fetching that solves issue 1) listed above.


braddunbar commented Apr 22, 2012

I think I would probably use a custom override of fetch. Something like this:

fetch: function(options) {
  if (options && options.id) options.url = this.url() + '/' + id;
  return Collection.__super__.fetch.call(this, options);

It strikes me that perhaps it would be nice if options was passed to url. That way no override of fetch is necessary.

url: function(options) {
  var url = '...';
  return (options && options.id) ? url + '/' + id : url;



jashkenas commented Apr 23, 2012

I'm not a big fan of passing the id in the options to fetch, as it's the URL that needs to be changed, which properly lives in the url() function -- really this is just highlighting that collection.fetch() is about fetching the contents of the collection -- not about loading an individual model.

What we really want here is something like:

var holmesBook = Book.fetch("102-hound-of-the-baskervilles");

Right? Or perhaps passing in the entire URL?

For me, specifying an ID doesn't feel that different than specifying a page number - in both cases you're specifying a subset of the collection to load (in fact, I just realized I could even munge up the server side code to check the querystring for the ID as a third approach). But I also get where you're coming from on the intent of collections.

The Book.fetch approach could work too, but URL handling seems a bit tricky. Just passing an ID may not be enough, as a Book could be a resource nested in different parents, so how would you know the URL to construct? So yeah, seems like you'd have to pass a complete URL, or maybe a collection as well as an ID (in my app I generally haven't used urlRoot on models, but have the models inherit their URL from the collection). Of course, if you have to construct the whole URL yourself, then there isn't much difference from my original solution of specify the url on the collection fetch options.


jashkenas commented Apr 23, 2012

Yep -- let's leave this be. That, combined with the fact that the fetch is necessarily asynchronous, means that you wouldn't have a reference to the complete model until the server came back. At that point, I think you're just as well off writing:

var holmesBook = new Book({id: "102-hound-of-the-baskervilles"});

... and either listening for change, or using the success callback.

@jashkenas jashkenas closed this Apr 23, 2012

Again, the big problem with new/fetch approach is the sequencing issue between initialize and parse in the two cases, described in the original post. Not sure if that can be fixed, but if it was that would also solve my problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment