UNPKG

wns-mvc-package

Version:

MVC package/bundle for WNS Middleware

509 lines (445 loc) 12.1 kB
/** * @WNS - The NodeJS Middleware and Framework * * @copyright: Copyright © 2012- YEPT ® * @page: http://wns.yept.net/ * @docs: http://wns.yept.net/docs/ * @license: http://wns.yept.net/license/ */ /** * No description yet. * * @author Pedro Nasser */ // Exports module.exports = { /** * Class dependencies */ extend: ['wnModel'], /** * PRIVATE */ private: { _new: false, _attributes: {}, _collectionName: '', _db: null, _schema: null }, /** * Public Variables */ public: { /** * @var object events to be preloaded. */ defaultEvents: { 'beforeSave': {}, 'afterSave': {}, 'beforeUpdate': {}, 'afterUpdate': {}, 'beforeDelete': {}, 'afterDelete': {}, 'beforeFind': {}, 'afterFind': {}, 'beforeCount': {}, 'afterCount': {} } }, /** * Methods */ methods: { /** * Initializer */ init: function (config,c,parent,db) { _db = db || this.getParent().db || _db; _attributes = this.getDefaults(); _schema = this.schema() || this.getConfig('schema') || {}; this.setIsNewRecord(true) .setCollectionName(config.name) .prepareSchema() .afterInit(); }, /** * This function can be overwrite. */ afterInit: function () { }, /** * Return a new instance of the given AR * If null, returns a new instance of the same AR; */ model: function (className) { if (typeof className != 'string') className = this.getClassName(); return new this.c[className](this.getConfig(), this.c, this.getParent(), _db); }, /** * This sends this AR's schema for the {_collectionName}'s collection * to the wnDbSchema from the actual wnDbConnection. */ prepareSchema: function () { var schema = _db.getSchema(); schema.setCollection(this.collectionName(),this.getSchema()); return this; }, /** * Returns the name of the associated database collection. * @return string the collection name */ collectionName: function () { return _collectionName; }, /** * Sets the name of the associated database collection. * @param string $name the collection name */ setCollectionName: function (name) { _collectionName = name || _collectionName; return this; }, /** * Function that will return this AR schema. * This function is just called in the initialization. * To get the real schema object: {@see getSchema()} * This schema will define which properties of this AR * is valid, their types and default values. * Just override it, example: * return { * 'name': { type: 'String', label: "User's Name" }, * 'age': { type: 'Number', label: "User's Age" }, * 'status': { type: boolean, label: "User's Status", default: true } * }; * @return object model's schema object */ schema: function () { return null; }, /** * Returns the real AR schema's name. */ getSchema: function () { return _schema; }, /** * Redefines the schema of this AR; * @param object $schema new schema object. */ setSchema: function (schema) { if (!!schema && typeof schema == 'object') _schema = schema; return this; }, /** * Returns the AR's schema's default values for each property * @return object result */ getDefaults: function () { var schema = this.getSchema(), result = {}; for (s in schema) if (schema[s]!=undefined && schema[s].default != undefined) result[s] = schema[s].default; return result; }, /** * Returns the database connection used by active record. * By default, the "db" application component is used as the database connection. * You may override this method if you want to use a different database connection. * @return wnDbConnection the database connection used by active record. */ getDbConnection: function () { return _db; }, /** * Returns the query builder used by this AR. * @return wnDbQueryBuilder the query builder used by this AR */ getQueryBuilder: function () { return this.getDbConnection().getSchema().getQueryBuilder(); }, /** * Get the collection instance. * @return instance collection instance */ getCollection: function () { return this.getDbConnection().dataObject.getCollection(this.collectionName()); }, /** * Checks whether this AR has the named attribute * @param string $name attribute name * @return boolean whether this AR has the named attribute (collection property). */ hasAttribute: function (name) { return this.getSchema()[name] !== undefined; }, /** * Check if attribute is required * @return boolean is required? */ isAttributeRequired: function (name) { return this.getSchema()[name].required === true; }, /** * Check if attribute is safe * @return boolean is safe? */ isSafe: function (name) { return this.getSchema()[name].safe === true; }, /** * Returns the named attribute value. * @param string $name the attribute name */ getAttribute: function (name) { return _attributes[name]; }, /** * Returns the named attribute value. * @param string $name the attribute name */ attr: function (name,value) { if (!_.isUndefined(value)) _attributes[name]=value; else { return _attributes[name]; } }, /** * Returns the named attribute label. * @param string $name the attribute name * @return mixed the attribute label */ getAttributeLabel: function (name) { return this.getSchema()[name].label || ''; }, /** * Check if the attribute has errors. * @param string $name the attribute name */ hasErrors: function (name) { return false; }, /** * Sets the named attribute value. * @param string $name the attribute name * @param mixed $value the attribute value. * @return boolean whether the attribute exists and the assignment is conducted successfully */ setAttribute: function (name,value) { _attributes[name]=value; }, /** * Set all attributes in the object * @param object $attributes new attributes */ setAttributes: function (attributes) { for (a in attributes) this.setAttribute(a,attributes[a]); return this; }, /** * Returns all column attribute values. * @param {boolean} safeOnly */ getAttributes: function (safeOnly) { var attrs = _.extend({},_attributes); if (safeOnly===true) { var schema = this.getSchema(); for (a in attrs) if (schema[a] && !schema[a].safe) delete attrs[a]; } return attrs; }, /** * Clear all model's attributes */ clearAttributes: function () { _attributes={}; return self; }, /** * Saves the current record. * * @param array $attributes list of attributes that need to be saved. Defaults to null, * meaning all attributes that are loaded from DB will be saved. * @return boolean whether the saving succeeds */ save: function () { var arguments = _.toArray(arguments); var attributes = this.getAttributes() || {}; var cb; if (typeof arguments[0] == 'object') attributes = arguments.shift(); if (typeof arguments[0] == 'function') cb = arguments.shift(); return this.getIsNewRecord() ? this.insert(this.getAttributes(),cb) : this.update(this.getAttributes(),cb); }, /** * Returns if the current record is new. * @return boolean whether the record is new and should be inserted when calling {@link save}. * Defaults to false, but it will be set to true if the instance is created using * the new operator. */ getIsNewRecord: function () { return _new; }, /** * Sets if the record is new. * @param boolean $value whether the record is new and should be inserted when calling {@link save}. */ setIsNewRecord: function (value) { _new=value; return this; }, /** * TODO */ query: function (params) { var builder = this.getQueryBuilder(), query=builder.createQuery(this.collectionName(),params); return query; }, /** * Inserts a row into the data to the collection based on this active record attributes. * After the record is inserted to DB successfully, its {@link isNewRecord} property will be set false * @param array $attributes list of attributes that need to be saved. Defaults to null, * meaning all attributes that are loaded from DB will be saved. * @return boolean whether the attributes are valid and the record is inserted successfully. */ insert: function (attributes,cb) { if(this.getIsNewRecord()) this.getParent().e.log&& this.getParent().e.log('wnActiveRecord.insert: The active record cannot be inserted to database because it is not new.'); if (!attributes) return false; if (cb) this.once('afterSave',cb); var self = this; this.once('beforeSave', function () { var builder = self.getQueryBuilder(), query=builder.createInsert(self.collectionName(),attributes); query.exec(function (err) { if(!err) self.setIsNewRecord(false); self.e.afterSave.apply(self,arguments); }); }).e.beforeSave(); return this; }, /** * Remove all documents that matches with the criteria. * @param mixed $criteria wnDbCriteria or object */ delete: function (criteria,cb) { if (!criteria) return false; if (cb) this.once('afterDelete',cb); var self = this; this.once('beforeDelete', function () { var builder = self.getQueryBuilder(), query=builder.createDelete(self.collectionName(),criteria); query.exec(function (err) { self.e.afterDelete.apply(self,arguments); }); }).e.beforeDelete(); return this; }, /** * Find all objects that matches with the criteria. * @param mixed $criteria wnDbCriteria or object */ find: function (criteria,cb) { if (!criteria) return false; if (cb) this.once('afterFind',cb); var self = this; this.once('beforeFind', function () { var builder = self.getQueryBuilder(), query=builder.createFind(self.collectionName(),criteria); query.exec(function (err,d) { self.e.afterFind.apply(self,arguments); }); }).e.beforeFind(); return this; }, /** * Count all objects that matches with the criteria. * @param mixed $criteria wnDbCriteria or object */ count: function (criteria,cb) { if (!criteria) return false; if (cb) this.once('afterCount',cb); var self = this; this.once('beforeCount', function () { var builder = self.getQueryBuilder(), query=builder.createCount(self.collectionName(),criteria); query.exec(function (err,d) { self.e.afterCount.apply(self,arguments); }); }).e.beforeCount(); return this; }, /** * Update all documents that matches with the criteria. * @param mixed $criteria wnDbCriteria or object */ update: function (criteria,data) { if (!criteria || !data) return false; var cb = arguments[2] || arguments[3] || undefined; var options = typeof arguments[2]=='object' ? arguments[2] : {}; if (cb) this.once('afterUpdate',cb); var self = this; this.once('beforeUpdate', function () { var builder = self.getQueryBuilder(), query=builder.createUpdate(self.collectionName(),criteria,data,options); query.exec(function (err,affected,raw) { self.e.afterUpdate.apply(self,arguments); }); }).e.beforeUpdate(); return this; } } };