There is indeed.
When you call 'fetch' on a collection, it passes the response through Backbone.Collection.parse before adding it to the collection.
The default implementation of 'parse' just passes the response through, as is, but you can override it to return a list of models to be added to the collection:
class Logbooks extends Backbone.Collection
model: Logbook
url: 'api/logbooks'
parse: (resp, xhr) ->
_(resp).map (attrs) ->
switch attrs.type
when 'UML' then new UmlLogbook attrs
when 'Plane' then new PLaneLogbook attrs
EDIT: whoa, idbentley got there before me. the only difference being he used 'each' and I used 'map'. Both will work, but differently.
Using 'each' effectively breaks the chain that the 'fetch' call started (by returning 'undefined' - the subsequent call to 'reset' (or 'add') therefore will do nothing) and does all the processing right there in the parse function.
Using 'map' just transforms the list of attributes into a list of models and passes it back to the chain already in motion.
Different strokes.
EDIT AGAIN: just realized there's also another way to do this:
The 'model' attribute on a collection is there only so the collection knows how to make a new model if it's passed attributes in 'add', 'create' or 'reset'. So you could do something like:
class Logbooks extends Backbone.Collection
model: (attrs, options) ->
switch attrs.type
when 'UML' then new UmlLogbook attrs, options
when 'Plane' then new PLaneLogbook attrs, options
# should probably add an 'else' here so there's a default if,
# say, no attrs are provided to a Logbooks.create call
url: 'api/logbooks'
The advantage of this is that the collection will now know how to 'cast' the right subclass of Logbook for operations other than 'fetch'.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…