Skip to content

Commit

Permalink
load data on model reference for async use
Browse files Browse the repository at this point in the history
  • Loading branch information
collin committed Apr 11, 2012
1 parent e70f7bd commit 84c7855
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 24 deletions.
27 changes: 18 additions & 9 deletions lib/alpha_simprini/core/model.coffee
Expand Up @@ -9,19 +9,28 @@ AS.Model = AS.Object.extend ({def, include}) ->

def initialize: (attributes={}) ->
@model = this
@id = attributes.id ? AS.uniq()
@idRef = "#{@id}-#{@constructor.path()}"
@cid = @idRef or uniqueId("c")
delete attributes.id

AS.All.byCid[@cid] = AS.All.byId[@id] = AS.All.byIdRef[@idRef] = this

@set(attributes)

def set: (attributes) ->
for key, value of attributes
# assert @[key].set
@[key].set(value)
if key is "id"
@setId(value)
else
# assert @[key].set
@[key].set(value)

def setId: (id=AS.uniq()) ->
if @id
delete AS.All.byId[@id]
delete AS.All.byIdRef["#{@id}-#{@constructor.path()}"]

@id = id
@idRef = "#{@id}-#{@constructor.path()}"
@cid = @idRef or uniqueId("c")
AS.All.byCid[@cid] = AS.All.byId[@id] = AS.All.byIdRef[@idRef] = this

# Don't trigger 'change', this must be specifically listened for.
@trigger("change:id")

def destroy: ->
@trigger("destroy")
Expand Down
31 changes: 18 additions & 13 deletions lib/alpha_simprini/core/model/rest.coffee
@@ -1,6 +1,6 @@
AS = require "alpha_simprini"
{camelize, underscore, pluralize} = require "fleck"
isArray = require "underscore"
_ = require "underscore"
$ = require "jquery"

convertKeys = (object) ->
Expand Down Expand Up @@ -34,29 +34,32 @@ AS.Model.REST = AS.Module.extend ({delegate, include, def, defs}) ->
unless model = AS.All.byId[id]
model = @new()
callback ?= model.didLoad
@readOne id, _.bind(callback, model)
@readOne id, callback

return model

defs readOne: (id) ->
$.get
def didLoad: (data) ->
@loadData(data)

defs readOne: (id, callback=@loadData) ->
$.ajax
url: @resourceURL(id)
dataType: 'json'
success: _.bind(@loadData, this)
success: _.bind(callback, this)
error: =>
console.error "readone error"
console.error(this, arguments)

defs mappings: ->
mappings = {}
for klass in @appendedTo
mappings[pluralize klass.rootKey()] = klass
mappings[pluralize(camelize(klass.rootKey()))] = klass
mappings


defs loadData: (data) ->
def loadData: (data) ->
references = AS.Map.new()
root = @rootKey()
root = @constructor.rootKey()

# TODO: implement runtime assertions
# assert data[root], "loaded data for, but JSON had no data at rootKey: #{root}"
Expand All @@ -65,17 +68,18 @@ AS.Model.REST = AS.Module.extend ({delegate, include, def, defs}) ->
modelData = convertKeys(modelData)

[modelData, ids] = extractIds(modelData)
model = @new(modelData)

references.set(model, ids)
@set(modelData)

for key, embeds of data
references.set(this, ids)

for key, embeds of convertKeys(data)
continue if key is root
# assert AS.Model.REST.mappings[key], "sideload data provided for #{key}, but no mapping exists in AS.Model.REST.mappings"
@mappings()[key].sideloadData(embed, references) for embed in embeds
@constructor.mappings()[key].sideloadData(embed, references) for embed in embeds

references.each (model, ids) -> model.resolveReferences(ids)
return model
return this

defs sideloadData: (modelData, references) ->
modelData = convertKeys(modelData)
Expand All @@ -89,6 +93,7 @@ AS.Model.REST = AS.Module.extend ({delegate, include, def, defs}) ->
continue unless references

relationKey = key.replace(/Id/, '')
return if @[relationKey + "Type"] # polymorphic!
path = @[relationKey].model().path()

if references.length is undefined
Expand Down
6 changes: 4 additions & 2 deletions test/core/model/rest.coffee
Expand Up @@ -58,14 +58,16 @@ sideLoading =

exports.REST =
"loads a model from a simple JSON response": (test) ->
model = Rested.loadData(plain)
model = Rested.new()
model.loadData(plain)
test.equal "value", model.field.get()
test.equal null, model.owner.get()
test.equal 0, model.relations.backingCollection.length
test.done()

"loads a model from a JSON respons w/sideLoading": (test) ->
model = Rested.loadData(sideLoading)
model = Rested.new()
model.loadData(sideLoading)
test.equal "packed", model.field.get()
test.ok sideloaded = AS.All.byIdRef["1-NS.SimpleRest"]
test.equal "first", sideloaded.field.get()
Expand Down

0 comments on commit 84c7855

Please sign in to comment.