Created
August 22, 2011 22:00
-
-
Save mattetti/1163733 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
DS = SC.Namespace.create(); | |
DS.property = function(transforms) { | |
return SC.computed(function(key, value) { | |
var data = get(this, 'data'), value, val, | |
name = transforms.keyName || key; | |
var from = transforms && transforms.from; | |
var to = transforms && transforms.to; | |
// if the data hasn't been populated yet, return immediately | |
if (!data) { return; } | |
if (value !== undefined) { | |
val = to ? to(value) : value; | |
SC.set(data, name, val); | |
} else { | |
value = SC.get(data, name); | |
if (from) { value = from(value); } | |
} | |
return value; | |
}).property('data') | |
}; | |
DS.property.string = DS.property; | |
DS.property.integer = function(keyName) { | |
return DS.property({ | |
keyName: keyName, | |
from: function(serialized) { | |
return Number(serialized); | |
}, | |
to: function(deserialized) { | |
return String(deserialized); | |
} | |
}); | |
}; | |
DS.property.date = function(keyName) { | |
return DS.property({ | |
keyName: keyName, | |
from: function(raw) { | |
return new Date(raw); | |
}, | |
to: function(date) { | |
return JSON.stringify(date); | |
} | |
}) | |
}; | |
DS.hasMany = function(other, klass) { | |
return function() { | |
var keys = SC.get(this.get('data'), other); | |
if (keys) { | |
var recordArray = SC.ArrayProxy.create(), content = []; | |
keys.forEach(function(key) { | |
content.push(klass.load(key)); | |
}) | |
recordArray.set('content', content); | |
return recordArray; | |
} else { | |
return; | |
} | |
}.property('data.' + other + '.@each').cacheable() | |
}; | |
DS.RecordArray = SC.Object.extend(SC.Array, { | |
keys: null, | |
objectAt: function(idx) { | |
var keys = this.get('keys'), | |
klass = this.get('klass'); | |
if (!keys) { return; } | |
var id = keys.objectAt(idx); | |
return klass.loadRecord(id); | |
} | |
}); | |
DS.Record = SC.Object.extend({ | |
unknownProperty: function(key, value) { | |
var data = this.get('data'); | |
if (value !== undefined) { | |
SC.set(data, key, value); | |
} else { | |
value = SC.get(data, key); | |
} | |
return value; | |
}, | |
save: function() { | |
DS.saveRecord(this); | |
} | |
}); | |
DS.RECORDS = {}; | |
DS.recordHashFor = function(klass, id) { | |
var recordsHash = DS.RECORDS[SC.guidFor(klass)]; | |
if (!recordsHash) { DS.RECORDS[SC.guidFor(klass)] = {} } | |
return recordsHash[id]; | |
}; | |
DS.setRecordHash = function(klass, id, hash) { | |
var recordsHash = DS.RECORDS[SC.guidFor(klass)]; | |
if (!recordsHash) { DS.RECORDS[SC.guidFor(klass)] = {}; recordsHash = {} } | |
recordsHash[id] = hash; | |
}; | |
// default method to look up a record by class and id. | |
// a record class can define its own load method for special behavior | |
// | |
// you can override this method to change the global loading behavior | |
DS.loadRecord = function(klass, id, force) { | |
var url = klass['instanceUrl'].fmt(id), | |
resource = klass['resource'], | |
instance = klass.create(); | |
if (!force) { | |
var recordHash = DS.recordHashFor(klass, id); | |
if (recordHash) { return instance.set('data', recordHash); } | |
} | |
$.ajax({ | |
url: url, | |
dataType: 'json', | |
success: function(json) { | |
DS.setRecordHash(klass, id, json[resource]); | |
instance.set('data', json[resource]); | |
} | |
}); | |
return instance; | |
}; | |
// params can be a Hash or a URL-encoded String | |
DS.loadRecords = function(klass, params) { | |
var url = klass['collectionUrl'], | |
resource = klass['resource'], | |
recordArray = SC.ArrayProxy.create(); | |
$.ajax({ | |
url: url, | |
data: params, | |
dataType: 'json', | |
success: function(json) { | |
var rawArray = json[resource], array = []; | |
rawArray.forEach(function(item) { | |
DS.setRecordHash(klass, item.id, item); | |
array.push(klass.create({ data: item })); | |
}); | |
recordArray.set('content', array); | |
} | |
}); | |
// Return the recordArray right away. It will asynchronously | |
// be populated with data when the data comes in via Ajax | |
return recordArray; | |
} | |
DS.saveRecord = function(record) { | |
var url = SC.get(this.constructor, 'instanceUrl'); | |
url = url.fmt(this.get('id')); | |
// TODO: Something on success vs. failure | |
$.ajax({ | |
type: 'PUT', | |
url: url, | |
data: SC.get(this, 'data'), | |
dataType: 'json', | |
}); | |
} | |
DS.Record.reopenClass({ | |
// force forces the record to be loaded even if it's already | |
// been fetched | |
load: function(id, force) { | |
return DS.loadRecord(this, id, force); | |
}, | |
// fetches all records. You can specify params as a Hash or | |
// URL-encoded string to narrow down the results. Returned | |
// records will override existing records | |
// | |
// TODO: Make sure instantiated objects get the updated | |
// data hashes. | |
loadAll: function(params) { | |
return DS.loadRecords(this, params); | |
} | |
}); | |
/** | |
USAGE | |
// TODO: Convention over configuration for instance URL, resource | |
// name and class URL | |
Person = DS.Record.extend({ | |
firstName: DS.property.string(), | |
lastName: DS.property.string(), | |
fullName: function() { | |
return this.get('firstName') + ' ' + this.get('lastName'); | |
}.property('firstName', 'lastName') | |
}); | |
Person.reopenClass({ | |
collectionUrl: "/people", | |
instanceUrl: "/people/%@", | |
resource: "people" | |
}); | |
var person = Person.load(1); | |
var people = Person.loadAll(); // can use this wherever an | |
// Array is expected, like in | |
// an ArrayController | |
*/ |
Totally understood, and thanks for posting this!
I'm mostly thinking out loud here so we can collectively converge. @staugaard and @shajith have been working on a similar library today and will be stealing the best ideas from here. @wycats and I have planned to reconvene later this week to polish and release.
Some updates & fixes by the above-mentioned @staugaard and @shajith are available here: https://gist.github.com/1167122
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@jamesarosen this is a very rudimental prototype that @wycats and I have been working on for a proof of concept. Feel free to modify and improve as you need it.