-
-
Save jamesarosen/1167122 to your computer and use it in GitHub Desktop.
Shed.Resource
This file contains hidden or 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
(function(window) { | |
Shed.Resource = SC.Object.extend({ | |
fetch: function() { | |
if (!this.hasFetched) { | |
this.hasFetched = true; | |
var self = this; | |
this.deferedFetch = $.getJSON(this.resourceURL()) | |
.done(function(json) { | |
self.set('data', self.constructor.parse(json)); | |
}); | |
} | |
return this.deferedFetch; | |
}, | |
resourceURL: function() { | |
return this.constructor.resourceURL(this); | |
}, | |
// Turn this resource into a JSON object to be saved via AJAX. Override | |
// this method to produce different syncing behavior. | |
toJSON: function() { | |
return this.get('data'); | |
}, | |
isNew: function() { | |
return !this.get('id'); | |
}, | |
save: function() { | |
var ajaxOptions = { | |
data: this.toJSON() | |
}; | |
if (this.isNew()) { | |
ajaxOptions.type = 'POST'; | |
ajaxOptions.url = this.constructor.resourceURL(); | |
} else { | |
ajaxOptions.type = 'PUT'; | |
ajaxOptions.url = this.resourceURL(); | |
} | |
return $.ajax(ajaxOptions); | |
} | |
}); | |
Shed.Resource.reopenClass({ | |
// Create an instance of this resource. If `options` includes an | |
// `id`, first check the identity map and return the existing resource | |
// with that ID if found. | |
create: function(options) { | |
var instance; | |
if (options && options.id) { | |
var id = options.id.toString(); | |
this.identityMap = this.identityMap || {}; | |
instance = this.identityMap[id]; | |
if (!instance) { | |
this.identityMap[id] = instance = this._super.call(this); | |
instance.set('data', options); | |
} | |
} else { | |
instance = this._super.call(this); | |
instance.set('data', options); | |
} | |
return instance; | |
}, | |
// Define a property of a resource. | |
property: function(transforms) { | |
var from = transforms && transforms.from, | |
to = transforms && transforms.to; | |
return function(name, value) { | |
var data = SC.get(this, 'data'), val; | |
if (!data || !data.hasOwnProperty(name)) { | |
this.fetch(); | |
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'); | |
}, | |
// Parse JSON -- likely returned from an AJAX call -- into the | |
// properties for an instance of this resource. Override this method | |
// to produce different parsing behavior. | |
parse: function(json) { | |
return json; | |
}, | |
// Define a resource class. | |
// | |
// Parameters: | |
// | |
// * `schema` -- the properties schema for the resource class | |
// * `url` -- either a function that returns the URL for syncing | |
// resources or a string. If the latter, a string of the form | |
// "/widgets" is turned into a function that returns "/widgets" if | |
// the Widget's ID is not present and "/widgets/{id}" if it is. | |
// * `parse` -- the function used to parse JSON returned from AJAX | |
// calls into the resource properties. By default, simply returns | |
// the JSON. | |
define: function(options) { | |
options = options || {}; | |
var klass = this.extend(options.schema); | |
var classOptions = { | |
url: options.url | |
}; | |
if (options.parse) { | |
classOptions.parse = options.parse; | |
} | |
klass.reopenClass(classOptions); | |
return klass; | |
}, | |
resourceURL: function(instance) { | |
if ($.isFunction(this.url)) { | |
return this.url(instance); | |
} else { | |
if (instance) { | |
return this.url + '/' + instance.get('id'); | |
} else { | |
return this.url; | |
} | |
} | |
} | |
}); | |
Shed.Resource.property.string = Shed.Resource.property(); | |
Shed.Resource.property.hash = Shed.Resource.property(); | |
Shed.Resource.property.integer = Shed.Resource.property({ | |
from: function(raw) { | |
return Number(raw); | |
}, | |
to: function(number) { | |
return String(number); | |
} | |
}); | |
Shed.Resource.property.date = Shed.Resource.property({ | |
from: function(raw) { | |
return new Date(raw); | |
}, | |
to: function(date) { | |
return JSON.stringify(date); | |
} | |
}); | |
Shed.Resource.property.boolean = Shed.Resource.property({ | |
from: function(raw) { | |
return raw === true || raw === 'true'; | |
}, | |
to: function(bool) { | |
return !!bool; | |
} | |
}); | |
Shed.Resource.resource = function(options) { | |
options = options || {}; | |
return function(name, value) { | |
var klass = SC.getPath(options.className); | |
var obj = klass.create({ | |
id: this.get(options.property) | |
}); | |
if (value !== undefined) { | |
SC.set(this, options.property, value.get('id')); | |
return; | |
} else { | |
return obj; | |
} | |
}.property(options.property).cacheable(); | |
}; | |
Shed.Resource.resources = function(options) { | |
options = options || {}; | |
return function(name, value) { | |
var collectionOptions = { | |
type: SC.getPath(options.className), | |
url: options.url | |
}; | |
if ($.isFunction(options.url)) { | |
collectionOptions.url = options.url(this); | |
} else if('string' === typeof options.url) { | |
collectionOptions.url = options.url.fmt(this.get('id')); | |
} | |
if (options.parse) { | |
collectionOptions.parse = options.parse; | |
} | |
var collection = Shed.ResourceCollection.create(collectionOptions); | |
return collection; | |
}.property('id').cacheable(); | |
}; | |
Shed.ResourceCollection = SC.ArrayProxy.extend({ | |
type: SC.Required, | |
fetch: function() { | |
if (!this.hasFetched && ! this.prePopulated) { | |
this.hasFetched = true; | |
var content = [], | |
self = this; | |
this.deferedFetch = $.getJSON(this.url || this.type.resourceURL()).done(function(json) { | |
_.each(self.parse(json), function(itemAttributes) { | |
content.push(self.type.create(itemAttributes)); | |
}); | |
self.set('content', content); | |
}); | |
} | |
return this.deferedFetch; | |
}, | |
parse: function(json) { | |
return _.map(json, this.type.parse); | |
}, | |
content: function(name, value) { | |
if (value === void(0)) { | |
this.fetch(); | |
return this.realContent; | |
} else { | |
this.realContent = value; | |
return value; | |
} | |
}.property() | |
}); | |
Shed.ResourceCollection.reopenClass({ | |
create: function(options) { | |
options = options || {}; | |
var content = options.content; | |
delete options.content; | |
options.prePopulated = !!content; | |
var instance = this._super.call(this, options); | |
if (content) { | |
instance.set('content', content); | |
} | |
return instance; | |
} | |
}); | |
}(this)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment