codecombat/app/models/SuperModel.coffee

123 lines
3.8 KiB
CoffeeScript
Raw Normal View History

2014-01-03 13:32:13 -05:00
class SuperModel
constructor: ->
@models = {}
@collections = {}
@schemas = {}
2014-01-03 13:32:13 -05:00
_.extend(@, Backbone.Events)
populateModel: (model) ->
@mustPopulate = model
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
# replace or overwrite
2014-02-15 18:44:45 -05:00
shouldLoadReference: (model) -> true
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) ->
model.loadSchema()
2014-01-03 13:32:13 -05:00
schema = model.schema()
2014-04-08 12:03:03 -04:00
# Load schema first.
unless schema.loaded
@schemas[schema.urlRoot] = schema
return schema.once('sync', => @modelLoaded(model))
2014-04-08 12:03:03 -04: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)
2014-04-08 12:03:03 -04:00
console.debug 'gintau', 'superModel-refs', model, refs
# load references.
2014-02-15 18:44:45 -05:00
for ref, i in refs when @shouldLoadReference ref
ref.saveBackups = @shouldSaveBackups(ref)
2014-01-03 13:32:13 -05:00
refURL = ref.url()
continue if @models[refURL]
@models[refURL] = ref
ref.fetch()
@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
for model in _.values @models
2014-01-03 13:32:13 -05:00
total += 1
loaded += 1 if model.loaded
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