2014-01-03 13:32:13 -05:00
|
|
|
class SuperModel
|
|
|
|
constructor: ->
|
|
|
|
@models = {}
|
|
|
|
@collections = {}
|
2014-03-08 17:34:25 -05:00
|
|
|
@schemas = {}
|
2014-01-03 13:32:13 -05:00
|
|
|
_.extend(@, Backbone.Events)
|
|
|
|
|
|
|
|
populateModel: (model) ->
|
|
|
|
@mustPopulate = model
|
2014-01-26 17:46:25 -05:00
|
|
|
model.saveBackups = @shouldSaveBackups(model)
|
2014-01-03 13:32:13 -05:00
|
|
|
model.fetch() unless model.loaded or model.loading
|
2014-03-26 17:44:11 -04:00
|
|
|
@listenToOnce(model, 'sync', @modelLoaded) unless model.loaded
|
2014-03-24 12:58:34 -04:00
|
|
|
@listenToOnce(model, 'error', @modelErrored) unless model.loaded
|
2014-01-03 13:32:13 -05:00
|
|
|
url = model.url()
|
|
|
|
@models[url] = model unless @models[url]?
|
|
|
|
@modelLoaded(model) if model.loaded
|
|
|
|
|
2014-01-26 17:46:25 -05:00
|
|
|
# replace or overwrite
|
2014-02-15 18:44:45 -05:00
|
|
|
shouldLoadReference: (model) -> true
|
2014-02-15 20:29:54 -05:00
|
|
|
shouldLoadProjection: (model) -> false
|
2014-02-15 18:44:45 -05:00
|
|
|
shouldPopulate: (url) -> true
|
|
|
|
shouldSaveBackups: (model) -> false
|
2014-01-03 13:32:13 -05:00
|
|
|
|
2014-02-11 19:09:44 -05:00
|
|
|
modelErrored: (model) ->
|
2014-01-03 13:32:13 -05:00
|
|
|
@trigger 'error'
|
2014-02-11 19:09:44 -05:00
|
|
|
@removeEventsFromModel(model)
|
2014-01-03 13:32:13 -05:00
|
|
|
|
2014-02-11 19:09:44 -05:00
|
|
|
modelLoaded: (model) ->
|
2014-03-08 17:34:25 -05:00
|
|
|
model.loadSchema()
|
2014-01-03 13:32:13 -05:00
|
|
|
schema = model.schema()
|
2014-03-08 17:34:25 -05:00
|
|
|
unless schema.loaded
|
|
|
|
@schemas[schema.urlRoot] = schema
|
|
|
|
return schema.once('sync', => @modelLoaded(model))
|
2014-02-15 20:29:54 -05:00
|
|
|
refs = model.getReferencedModels(model.attributes, schema.attributes, '/', @shouldLoadProjection)
|
2014-01-03 13:32:13 -05:00
|
|
|
refs = [] unless @mustPopulate is model or @shouldPopulate(model)
|
|
|
|
# console.log 'Loaded', model.get('name')
|
2014-02-15 18:44:45 -05:00
|
|
|
for ref, i in refs when @shouldLoadReference ref
|
2014-01-26 17:46:25 -05:00
|
|
|
ref.saveBackups = @shouldSaveBackups(ref)
|
2014-01-03 13:32:13 -05:00
|
|
|
refURL = ref.url()
|
|
|
|
continue if @models[refURL]
|
|
|
|
@models[refURL] = ref
|
|
|
|
ref.fetch()
|
2014-03-26 17:39:01 -04:00
|
|
|
@listenToOnce(ref, 'sync', @modelLoaded)
|
2014-01-03 13:32:13 -05:00
|
|
|
|
|
|
|
@trigger 'loaded-one', model: model
|
|
|
|
@trigger 'loaded-all' if @finished()
|
2014-02-11 19:09:44 -05:00
|
|
|
@removeEventsFromModel(model)
|
2014-02-12 16:10:58 -05:00
|
|
|
|
2014-02-11 19:09:44 -05:00
|
|
|
removeEventsFromModel: (model) ->
|
|
|
|
model.off 'sync', @modelLoaded, @
|
|
|
|
model.off 'error', @modelErrored, @
|
2014-01-03 13:32:13 -05:00
|
|
|
|
|
|
|
getModel: (ModelClass_or_url, id) ->
|
|
|
|
return @getModelByURL(ModelClass_or_url) if _.isString(ModelClass_or_url)
|
|
|
|
m = new ModelClass_or_url(_id: id)
|
|
|
|
return @getModelByURL(m.url())
|
|
|
|
|
|
|
|
getModelByURL: (modelURL) ->
|
|
|
|
return @models[modelURL] or null
|
|
|
|
|
|
|
|
getModelByOriginalAndMajorVersion: (ModelClass, original, majorVersion=0) ->
|
|
|
|
_.find @models, (m) ->
|
|
|
|
m.get('original') is original and m.get('version').major is majorVersion and m.constructor.className is ModelClass.className
|
|
|
|
|
|
|
|
getModels: (ModelClass) ->
|
|
|
|
# can't use instanceof. SuperModel gets passed between windows, and one window
|
|
|
|
# will have different class objects than another window.
|
|
|
|
# So compare className instead.
|
|
|
|
return (m for key, m of @models when m.constructor.className is ModelClass.className) if ModelClass
|
|
|
|
return _.values @models
|
|
|
|
|
|
|
|
addModel: (model) ->
|
|
|
|
url = model.url()
|
|
|
|
return console.warn "Tried to add Model '#{url}' to SuperModel, but it wasn't loaded." unless model.loaded
|
|
|
|
#return console.warn "Tried to add Model '#{url}' to SuperModel when we already had it." if @models[url]?
|
|
|
|
@models[url] = model
|
|
|
|
|
|
|
|
getCollection: (collection) ->
|
|
|
|
url = collection.url
|
|
|
|
url = url() if _.isFunction(url)
|
|
|
|
return @collections[url] or collection
|
|
|
|
|
|
|
|
addCollection: (collection) ->
|
|
|
|
url = collection.url
|
|
|
|
url = url() if _.isFunction(url)
|
|
|
|
if @collections[url]?
|
|
|
|
return console.warn "Tried to add Collection '#{url}' to SuperModel when we already had it."
|
|
|
|
@collections[url] = collection
|
|
|
|
|
|
|
|
# consolidate models
|
|
|
|
for model, i in collection.models
|
|
|
|
cachedModel = @getModelByURL(model.url())
|
|
|
|
if cachedModel
|
|
|
|
collection.models[i] = cachedModel
|
|
|
|
else
|
|
|
|
@addModel(model)
|
|
|
|
collection
|
|
|
|
|
|
|
|
progress: ->
|
|
|
|
total = 0
|
|
|
|
loaded = 0
|
|
|
|
|
2014-03-08 17:34:25 -05:00
|
|
|
for model in _.values @models
|
2014-01-03 13:32:13 -05:00
|
|
|
total += 1
|
|
|
|
loaded += 1 if model.loaded
|
2014-03-08 17:34:25 -05:00
|
|
|
for schema in _.values @schemas
|
|
|
|
total += 1
|
|
|
|
loaded += 1 if schema.loaded
|
2014-01-03 13:32:13 -05:00
|
|
|
|
|
|
|
return 1.0 unless total
|
|
|
|
return loaded / total
|
|
|
|
|
|
|
|
finished: ->
|
|
|
|
return @progress() == 1.0
|
|
|
|
|
|
|
|
module.exports = SuperModel
|