Skip to content

Instantly share code, notes, and snippets.

@ericf
Created April 4, 2011 16:50
Show Gist options
  • Save ericf/901958 to your computer and use it in GitHub Desktop.
Save ericf/901958 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html>
<head>
<title>ModelResource Manual Tests</title>
</head>
<body>
<h1>ModelResource Manual Tests</h1>
<script src="http://yui.yahooapis.com/3.3.0/build/yui/yui.js"></script>
<script>
YUI({
filter : 'DEBUG',
modules : {
'model-base' : {
fullpath : '../../../../build/model/model-base-debug.js',
requires : ['attribute', 'pluginhost']
},
'model-resource' : {
fullpath : '../../../../build/model/model-resource-debug.js',
requires : ['model-base', 'gallery-resource', 'plugin', 'base-build']
}
}
}).use('model-resource', function(Y){
var ProjectModel = Y.Model.create('project', {}, {
ID_ATTR : 'uuid',
ATTRS : {
description : { value: 'foo' }
}
});
// plug all ProjectModel instances with their _own_ ModelResource
Y.Model.plug(ProjectModel, Y.ModelResource, { uri: '/project/{uuid}' });
var project = new ProjectModel({
description : 'bar'
});
console.log(project.resource.get('uri'));
project.resource.on('request', function(e){
console.log('resource request');
});
project.save();
console.log(project.toJSON());
});
</script>
</body>
</html>
/**
* Model Collection
*/
var ModelCollection,
MODEL_COLLECTION = 'modelCollection',
noop = function(){},
YLang = Y.Lang,
isArray = YLang.isArray,
isString = YLang.isString,
isFunction = YLang.isFunction;
// *** Model Collection *** //
ModelCollection = function (config) {
config = isArray(config) ? { models: config } : config;
var c = this.constructor,
name = c.NAME,
models;
// Setup Y.EventTarget
Y.EventTarget.call(this, {
prefix : name,
emitFacade : true,
queuable : true,
bubbles : true
});
// Setup Y.PluginHost
Y.Plugin.Host.call(this);
this.name = name;
Y.stamp(this);
models = this._initModels((config || {}).models);
ModelCollection.superclass.constructor.call(this, models);
this.initializer(config);
this._initPlugins(config);
};
Y.extend(ModelCollection, Y.ArrayList, {
// *** Prototype *** //
model : Y.Model,
// *** Lifecycle Methods *** //
initializer : noop,
destructor : noop,
// *** Public Methods *** //
fetch : function () {
this.fire('fetch');
return this;
},
create : function () {},
// *** Private Methods *** //
_initModels : function (models) {
models = Y.Array(models);
var initedModels = [],
byId = this._byId || (this._byId = {}),
model, i, len;
for (i = 0, len = models.length; i < len; i++) {
model = models[i];
(model instanceof Y.Model) || (model = new this.model(model));
if (model._id) {
byId[model._id] = model;
}
model.addTarget(this);
initedModels.push(model);
}
return initedModels.length > 1 ? initedModels : initedModels[0];
},
_detachModels : function (models) {
models = models ? Y.Array(models) : this._items;
var i, len;
for (i = 0, len = models.length; i < len; i++) {
models[i].removeTarget(this);
}
},
_reset : function () {
this._detachModels();
this._items = [];
},
_defAddFn : function (e) {
ModelCollection.superclass.add.apply(this, e.args);
},
_defRemoveFn : function (e) {
ModelCollection.superclass.remove.apply(this, e.args);
},
_defRefreshFn : function (e) {
var models = e.args[0];
this._reset();
this._items = this._initModels(models);
},
}, {
// *** Static *** //
NAME : MODEL_COLLECTION,
create : function (name, px, sx) {
function BuiltModelCollection () {
BuiltModelCollection.superclass.constructor.apply(this, arguments);
}
BuiltModelCollection.NAME = name;
if (isFunction(px)) {
px = { model: px };
}
return Y.extend(BuiltModelCollection, ModelCollection, px, sx);
},
plug : Y.Plugin.Host.plug,
unplug : Y.Plugin.Host.unplug,
eventWrap : function (event, defFn) {
var proto = this.prototype;
proto[event] = function(){
isFunction(defFn) || (defFn = isString(defFn) && isFunction(this[defFn]) ? this[defFn] : null);
this.publish(event, { defaultFn: defFn });
function fireEvent () {
this.fire(event, { args: Y.Array(arguments) });
return this;
}
proto[event] = fireEvent;
return fireEvent.apply(this, arguments);
};
}
});
ModelCollection.eventWrap('add', '_defAddFn');
ModelCollection.eventWrap('remove', '_defRemoveFn');
ModelCollection.eventWrap('refresh', '_defRefreshFn');
Y.mix(ModelCollection, Y.EventTarget, false, null, 1);
Y.mix(ModelCollection, Y.Plugin.Host, false, null, 1);
// *** Namespace *** //
Y.ModelCollection = ModelCollection;
/**
* ModelResource
*/
var ModelResource,
MODEL_RESOURCE = 'modelResource',
MODEL_RESOURCE_NS = 'resource';
// *** ModelResource *** //
ModelResource = Y.Base.create(MODEL_RESOURCE, Y.Resource, [Y.Plugin.Base], {
initializer : function (config) {
config || (config = {});
this.set('headers', Y.merge(ModelResource.HEADERS, config.headers));
this.onHostEvent('*:fetch', this.read);
this.onHostEvent('*:save', function(e){
var model = this._getModel(e);
if (model) {
this[ model.isNew() ? 'create' : 'update' ](model);
}
});
this.onHostEvent('*:destroy', this.del);
},
create : function (e) {
var model = this._getModel(e),
idAttr, params;
// we need a new model
if ( ! (model && model.isNew())) { return; }
idAttr = model.constructor.ID_ATTR;
params = {};
params[idAttr] = ''; // chop off id placeholder from URI
this.POST({ params: params, entity: model, on: {
success : function(e){
model.setAttrs(e.entity);
model._id = model.get(idAttr);
}
}});
},
read : function (e) {
var model = this._getModel(e),
success = e && e.success ? e.success : null,
idAttr, params;
if (model) {
if (model.isNew()) { return; }
idAttr = model.constructor.ID_ATTR;
params = {};
params[idAttr] = model.get(idAttr);
success = function(e){
model.setAttrs(e.entity);
};
}
this.GET({ params: params, on: { success: success }});
},
update : function (e) {
var model = this._getModel(e),
idAttr, params;
// we need an existing model
if ( ! model || model.isNew()) { return; }
idAttr = model.constructor.ID_ATTR;
params = {};
params[idAttr] = model.get(idAttr);
this.PUT({ params: params, entity: model });
},
del : function (e) {
var model = this._getModel(e),
idAttr, params;
// we need an existing model
if ( ! model || model.isNew()) { return; }
idAttr = model.constructor.ID_ATTR;
params = {};
params[idAttr] = model.get(idAttr);
this.DELETE({ params: params });
},
// *** Private Methods *** //
_getModel : function (obj) {
obj || (obj = this.get('host'));
if (Y.instanceOf(obj, Y.Model)) {
return obj;
}
if (Y.instanceOf(obj, Y.EventFacade) && Y.instanceOf(obj.target, Y.Model)) {
return obj.target;
}
}
}, {
// *** Static *** //
NS : MODEL_RESOURCE_NS,
HEADERS : {
'Accept' : 'application/json',
'Content-Type' : 'application/json'
}
});
// *** Namespace *** //
Y.ModelResource = ModelResource;
/**
* Model
*/
var Model,
MODEL = 'model',
noop = function(){},
isValue = Y.Lang.isValue;
// *** Model *** //
Model = function (config) {
var c = this.constructor,
name = c.NAME,
idAttr = c.ID_ATTR;
// Setup Y.EventTarget
Y.EventTarget.call(this, {
prefix : name,
emitFacade : true,
queuable : true,
bubbles : true
});
// Setup Y.Attribute
// NOTE: not calling Y.Attribute() because it does shitty things :-(
this._ATTR_E_FACADE = {}; // Perf tweak - avoid creating event literals if not required.
this._state = new Y.State();
this._stateProxy = this._stateProxy || null;
this._requireAddAttr = this._requireAddAttr || false;
this.addAttrs(this._protectAttrs(c.ATTRS), config, true);
// Setup Y.PluginHost
Y.Plugin.Host.call(this);
this.name = name;
Y.stamp(this);
if (idAttr) {
this._id = this.get(idAttr);
}
this.initializer(config);
this._initPlugins(config);
};
// *** Static *** //
Y.mix(Model, {
NAME : MODEL,
ATTRS : {},
create : function (name, px, sx) {
function BuiltModel () {
BuiltModel.superclass.constructor.apply(this, arguments);
}
BuiltModel.NAME = name;
return Y.extend(BuiltModel, Model, px, sx);
},
plug : Y.Plugin.Host.plug,
unplug : Y.Plugin.Host.unplug
});
// *** Prototype *** //
Model.prototype = {
// *** Lifecycle Methods *** //
initializer : noop,
destructor : noop,
// *** Public Methods *** //
isNew : function () {
return ! isValue(this._id);
},
clone : function () {
return new this.constructor(Y.clone(this.getAttrs()));
},
fetch : function () {
this.fire('fetch');
return this;
},
save : function () {
this.fire('save');
return this;
},
destroy : function () {
this._destroyPlugins();
this.destructor();
this.fire('destroy');
this.detachAll();
return this;
},
toJSON : function () {
return this.getAttrs();
}
};
Y.mix(Model, Y.Attribute, false, null, 1);
Y.mix(Model, Y.Plugin.Host, false, null, 1);
Model.prototype.constructor = Model;
// *** Namespace *** //
Y.Model = Model;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment