Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

added limited rest adapter w/sideloading

  • Loading branch information...
commit e70f7bd5af5af123e95787054839a1fb36a84d72 1 parent 98663df
@collin authored
View
1  examples/todo/server.coffee
@@ -14,6 +14,7 @@ share.attach app, db: type: "none"
new ModuleLoader
server: app
+ env: "production"
module_root: pathname.resolve("./node_modules")
ignorefile: pathname.resolve("./.stitchignore")
packages: "jquery underscore underscore.string jwerty socket.io-client share rangy-core pathology taxialpha_simprini fleck todo".split(" ")
View
1  lib/alpha_simprini.coffee
@@ -18,6 +18,7 @@ AS.Models = Pathology.Namespace.new()
AS.Views = Pathology.Namespace.new()
AS.Object = Pathology.Object
+AS.Map = Pathology.Map
AS.Module = Pathology.Module
AS.Namespace = Pathology.Namespace
AS.Property = Taxi.Property
View
10 lib/alpha_simprini/core.coffee
@@ -10,14 +10,12 @@ Core.require """
properties/field properties/has_many properties/has_one properties/virtual_property
properties/embeds_many properties/embeds_one properties/belongs_to
- collection model/share
+ collection
models/radio_selection_model models/multiple_selection_model
"""
-AS.ShareJsURL = "http://#{window?.location.host or 'localhost'}/sjs"
-
-AS.share = require("share").client
+# model/share
# # ## Some little utility functions.
@@ -52,10 +50,6 @@ AS.deepClone = (it) ->
AS.uniq = ->
(Math.floor Math.random() * 100000000000000000).toString(32) + "-" + (Math.floor Math.random() * 100000000000000000).toString(32) + "-" + (new Date).getTime().toString(32)
-AS.openSharedObject = (id, callback) ->
- @share.open id, "json", @ShareJsURL, (error, handle) ->
- if error then console.log(error) else callback(handle)
-
AS.humanSize = (size) ->
units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
i = 0;
View
11 lib/alpha_simprini/core/model.coffee
@@ -2,7 +2,7 @@ AS = require("alpha_simprini")
{uniqueId, toArray} = _ = require("underscore")
Taxi = require("taxi")
-AS.All = byCid: {}, byId: {}
+AS.All = byCid: {}, byId: {}, byIdRef: {}
AS.Model = AS.Object.extend ({def, include}) ->
include Taxi.Mixin
@@ -10,15 +10,18 @@ AS.Model = AS.Object.extend ({def, include}) ->
def initialize: (attributes={}) ->
@model = this
@id = attributes.id ? AS.uniq()
- @cid = @id or uniqueId("c")
+ @idRef = "#{@id}-#{@constructor.path()}"
+ @cid = @idRef or uniqueId("c")
delete attributes.id
- AS.All.byCid[@cid] = AS.All.byId[@id] = this
+ AS.All.byCid[@cid] = AS.All.byId[@id] = AS.All.byIdRef[@idRef] = this
@set(attributes)
def set: (attributes) ->
- @[key].set(value) for key, value of attributes
+ for key, value of attributes
+ # assert @[key].set
+ @[key].set(value)
def destroy: ->
@trigger("destroy")
View
102 lib/alpha_simprini/core/model/rest.coffee
@@ -0,0 +1,102 @@
+AS = require "alpha_simprini"
+{camelize, underscore, pluralize} = require "fleck"
+isArray = require "underscore"
+$ = require "jquery"
+
+convertKeys = (object) ->
+ converted = {}
+ for key, value of object
+ converted[camelize key] = value
+ converted
+
+extractIds = (object) ->
+ data = {}
+ ids = {}
+ for key, value of object
+ if key.match /Ids?$/
+ ids[key] = value
+ else
+ data[key] = value
+
+ [data, ids]
+
+AS.Model.REST = AS.Module.extend ({delegate, include, def, defs}) ->
+ defs mappings: AS.Map.new()
+
+ defs rootKey: ->
+ underscore @_name()
+
+ defs resourcesURL: -> "/#{pluralize @rootKey()}"
+
+ defs resourceURL: (id) -> "#{@resourcesURL()}/#{id}"
+
+ defs load: (id, callback) ->
+ unless model = AS.All.byId[id]
+ model = @new()
+ callback ?= model.didLoad
+ @readOne id, _.bind(callback, model)
+
+ return model
+
+ defs readOne: (id) ->
+ $.get
+ url: @resourceURL(id)
+ dataType: 'json'
+ success: _.bind(@loadData, this)
+ error: =>
+ console.error "readone error"
+ console.error(this, arguments)
+
+ defs mappings: ->
+ mappings = {}
+ for klass in @appendedTo
+ mappings[pluralize klass.rootKey()] = klass
+ mappings
+
+
+ defs loadData: (data) ->
+ references = AS.Map.new()
+ root = @rootKey()
+
+ # TODO: implement runtime assertions
+ # assert data[root], "loaded data for, but JSON had no data at rootKey: #{root}"
+
+ modelData = data[root]
+ modelData = convertKeys(modelData)
+
+ [modelData, ids] = extractIds(modelData)
+ model = @new(modelData)
+
+ references.set(model, ids)
+
+ for key, embeds of 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
+
+ references.each (model, ids) -> model.resolveReferences(ids)
+ return model
+
+ defs sideloadData: (modelData, references) ->
+ modelData = convertKeys(modelData)
+ [modelData, ids] = extractIds(modelData)
+ model = @new(modelData)
+
+ references.set(model, ids)
+
+ def resolveReferences: (ids) ->
+ for key, references of ids
+ continue unless references
+
+ relationKey = key.replace(/Id/, '')
+ path = @[relationKey].model().path()
+
+ if references.length is undefined
+ id = references
+ @[relationKey].set AS.All.byIdRef["#{id}-#{path}"]
+
+ else
+ for id in references
+ @[relationKey].add AS.All.byIdRef["#{id}-#{path}"]
+
+
View
11 lib/alpha_simprini/core/model/share.coffee
@@ -1,6 +1,12 @@
AS = require "alpha_simprini"
_ = require "underscore"
+AS.ShareJsURL = "http://#{window?.location.host or 'localhost'}/sjs"
+
+AS.openSharedObject = (id, callback) ->
+ @share.open id, "json", @ShareJsURL, (error, handle) ->
+ if error then console.log(error) else callback(handle)
+
AS.Model.Share = AS.Module.extend ({delegate, include, def, defs}) ->
defs index: (name, config) ->
@writeInheritableValue 'indeces', name, config
@@ -15,14 +21,11 @@ AS.Model.Share = AS.Module.extend ({delegate, include, def, defs}) ->
defs load: (id, callback) ->
unless model = AS.All.byId[id]
- model = AS.All.byId[id] or @new(id:id)
+ model = @new(id:id)
callback ?= model.didLoad
AS.openSharedObject id, _.bind(callback, model)
model
- def initialize: ->
- @_super.apply(this, arguments)
-
def new: ->
@share is undefined
View
3  lib/alpha_simprini/core/properties/has_many.coffee
@@ -10,6 +10,7 @@ AS.Model.HasMany.Instance = AS.Model.Field.Instance.extend ({def, delegate}) ->
delegate AS.COLLECTION_DELEGATES, to: "backingCollection"
def initialize: (@object, @options={}) ->
+ @model = @options.model
@options.source = @object if @options.inverse
@backingCollection = AS.Collection.new(undefined, @options)
@@ -18,7 +19,7 @@ AS.Model.HasMany.Instance = AS.Model.Field.Instance.extend ({def, delegate}) ->
segment.binds this, "remove", segment.removeCallback
def set: (models) ->
- @backingCollection.add models
+ @backingCollection.add(model) for model in models
def add: (models) -> @backingCollection.add.apply(@backingCollection, arguments)
View
1  lib/alpha_simprini/core/properties/has_one.coffee
@@ -9,6 +9,7 @@ AS.Model.HasOne = AS.Model.Field.extend ({delegate, include, def, defs}) ->
AS.Model.HasOne.Instance = AS.Model.Field.Instance.extend ({def}) ->
def initialize: (@object, @options) ->
@options.model ?= -> AS.Model
+ @model = @options.model
@namespace = ".#{_.uniqueId()}"
@_super.apply(this, arguments)
@bind "destroy", => @set(null)
View
3  package.json
@@ -29,6 +29,7 @@
"devDependencies": {
"jsdom": ">= 0.2",
"nodeunit": ">= 0.6.0",
- "sinon": "1.3.1"
+ "sinon": "1.3.1",
+ "module_loader": "latest"
}
}
View
3  test/core/model.coffee
@@ -4,13 +4,14 @@ exports.setUp = coreSetUp
exports.Model =
"has a place for all models": (test) ->
- test.deepEqual AS.All, byCid: {}, byId: {}
+ test.deepEqual AS.All, byCid: {}, byId: {}, byIdRef: {}
test.done()
"puts new models in that place": (test) ->
model = AS.Model.new()
test.equal AS.All.byCid[model.cid], model, "puts model in AS.All.byCid"
test.equal AS.All.byId[model.id], model, "puts model in AS.All.byId"
+ test.equal AS.All.byIdRef[model.idRef], model, "puts model in AS.All.byIdRef"
test.done()
# "runs initialize callbacks": (test) ->
View
74 test/core/model/rest.coffee
@@ -0,0 +1,74 @@
+{AS, NS, _, sinon, coreSetUp, makeDoc} = require require("path").resolve("./test/helper")
+exports.setUp = coreSetUp
+
+AS.part("Core").require("model/rest")
+console.log AS.Model.REST.toString()
+
+Rested = NS.Rested = AS.Model.extend ({delegate, include, def, defs}) ->
+ include AS.Model.REST
+ @field "field"
+ # @embedsMany "embeds", model: -> SimpleRest
+ # @embedsOne "embedded", model: -> SimpleRest
+ @hasMany "relations", model: -> SimpleRest
+ # @hasOne "relation"
+ @belongsTo "owner", model: -> SimpleRest
+
+SimpleRest = NS.SimpleRest = AS.Model.extend ({delegate, include, def, defs}) ->
+ include AS.Model.REST
+ @field "field"
+ # @embedsMany "embeds", model: -> SimplerRest
+ # @embedsOne "embedded", model: -> SimplerRest
+ @hasMany "relations", model: -> SimplerRest
+ # @hasOne "relation"
+ @belongsTo "owner", model: -> SimplerRest
+
+SimplerRest = NS.SimplerRest = AS.Model.extend ({delegate, include, def, defs}) ->
+ include AS.Model.REST
+ @field "field"
+
+plain =
+ rested:
+ id: 1
+ field: "value"
+ relation_ids: []
+ owner_id: null
+
+sideLoading =
+ rested:
+ id: 1
+ field: "packed"
+ relation_ids: [1,2,3,4,5]
+ owner_id: 1
+
+ simple_rests: [
+ {id: 1, field: "first", relation_ids: [2,4]}
+ {id: 2, field: "second", relation_ids: []}
+ {id: 3, field: "third", relation_ids: [1,2,3]}
+ {id: 4, field: "fourth", relation_ids: [4,5]}
+ {id: 5, field: "fifth", relation_ids: []}
+ ]
+
+ simpler_rests: [
+ {id: 1, field: "first"}
+ {id: 2, field: "second"}
+ {id: 3, field: "third"}
+ {id: 4, field: "fourth"}
+ {id: 5, field: "fifth"}
+ ]
+
+exports.REST =
+ "loads a model from a simple JSON response": (test) ->
+ model = Rested.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)
+ test.equal "packed", model.field.get()
+ test.ok sideloaded = AS.All.byIdRef["1-NS.SimpleRest"]
+ test.equal "first", sideloaded.field.get()
+ test.equal AS.All.byIdRef["1-NS.SimpleRest"], model.owner.get()
+ test.equal 5, model.relations.backingCollection.length
+ test.done()
View
2  test/core/properties/has_many.coffee
@@ -21,7 +21,7 @@ exports.HasMany =
test.done()
"is set when constructing the model": (test) ->
- o = NS.Parent.new children: {}
+ o = NS.Parent.new children: [{}]
test.ok o.children.first().value() instanceof AS.Model
test.done()
View
1  test/helper.coffee
@@ -22,6 +22,7 @@ exports.coreSetUp = (callback) ->
AS.All =
byCid: {}
byId: {}
+ byIdRef: {}
callback()
BoundModel = exports.BoundModel = NS.BoundModel = AS.Model.extend()
Please sign in to comment.
Something went wrong with that request. Please try again.