Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
1602 committed Oct 8, 2012
0 parents commit ab594c1
Show file tree
Hide file tree
Showing 12 changed files with 815 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
coverage
npm-debug.log
Empty file added README.md
Empty file.
3 changes: 3 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

exports.BaseController = require('./lib/base.js');

119 changes: 119 additions & 0 deletions lib/base.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
var util = require('util');
module.exports = BaseController;

/**
* Base class for any controller. It describes common API for controllers.
*
* Each instance method could be triggered from controller context (when
* run in new context). Basically this class describes context, which contains
* description of controller. This looks pretty tricky, but it helps to write
* clean and easy to read controller classes without thinking about OOP (in case
* of running in new context). Alternatively you can use this class as parent
* for any other class.
*
* Example 1. OOP-style
*
* function MyController() {
* BaseController.call(this);
* }
* MyController.prototype.__proto__ = BaseController.prototype;
* var ctl = new MyController;
* ctl.action('index', function index() {
* this.locals.items = [];
* this.render();
* });
* ctl.perform('name');
*
* Example 2. Functional style
*
* action(function index() {
* this.items = [];
* render();
* });
*
*/
function BaseController() {
this.controllerName = this.constructor.controllerName;

// just declare context things here
this.context = {
req: null,
res: null,
next: null,
actionName: null
};

var ctl = this;

Object.keys(this.context).forEach(function (key) {
if (key === 'next') return; // except next;
ctl.__defineGetter__(key, contextGetter(ctl, key));
});

['params', 'session', 'body'].forEach(function (key) {
ctl.__defineGetter__(key, contextGetter(ctl, 'req', key));
});

function contextGetter(ctl, key, subkey) {
return subkey ?
function () {
return ctl.context[key][subkey];
}:
function () {
return ctl.context[key];
};
}

}

BaseController.constructClass = function (controllerName) {
Controller.controllerName = controllerName;
function Controller() {
BaseController.call(this);
}
Controller.prototype.__proto__ = BaseController.prototype;
// util.inherits(Controller, BaseController);
return Controller;
};

BaseController.prototype.reset = function () {
this.constructor.actions = {};
this.constructor.before = [];
this.constructor.after = [];
};

BaseController.prototype.build = function (script) {
var ctl = this;
exportMembers(BaseController.prototype);
exportMembers(this.constructor.prototype);
script.runInNewContext(this);

function exportMembers(from) {
Object.getOwnPropertyNames(from).forEach(function (name) {
if (name !== 'constructor') {
ctl[name] = from[name].bind(ctl);
}
});
}
};

/**
* @override default controller string representation
*/
BaseController.prototype.toString = function toString() {
return 'Controller ' + this.controllerName;
};


extendWith('rendering');
extendWith('flow-control');
extendWith('helpers');
extendWith('code-sharing');

function extendWith(what) {
var bc = require('./' + what);
Object.keys(bc.prototype).forEach(function (meth) {
BaseController.prototype[meth] = bc.prototype[meth];
});
}

37 changes: 37 additions & 0 deletions lib/code-sharing.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
module.exports = CodeSharing;

function CodeSharing() {
}

/**
* Publish some object or function to use in another controller
*
* @param {String} name (optional)
* @param {Mixed} obj
*/
CodeSharing.prototype.publish = function publish(name, obj) {
if (!this._buffer) {
this._buffer = {};
}

if (typeof name === 'function') {
obj = name;
this._buffer[obj.name] = obj;
} else if (typeof name === 'string') {
this._buffer[name] = obj;
}

};

/**
* Get some object or function published in another controller
*
* @param {String} name
* @return {Mixed} result
*/
CodeSharing.prototype.use = function use(name) {
var what = this._buffer && this._buffer[name];
if (typeof what === 'undefined') throw new Error(name + ' is not defined');
return what;
};

Loading

0 comments on commit ab594c1

Please sign in to comment.