Controllers
Lightning-fast and flexible controller prototype

The main aim of the controller is to help simplify the most common tasks that you need to do when setting up routes and functions/classes to handle them.

Controllers are the thing that directly responds to each HTTP Request that comes into your application, as such each web request will result in (if routed) a new instance of a Controller (Class).

Avoid callback soup/hell and promise slowdown by using this.proxy() or this.callback() in the Static section of the Controller, this keeps code nesting to a minimum and brings code re-use up. Instead of passing around req and res as arguments like other less organized solutions, in CleverStack they are exposed as this.req and this.res

  • Lightning fast
  • V8's Hidden Classes & Inline Caches
  • V8's Optimizing Compiler which generates efficient machine code to run in place of your javascript
  • Clean, Efficient and Optimized code
  • Super methods
  • Static & Prototypal inheritance
  • Setup and initialization methods for both Static and Prototype
  • Easy-to-use method proxys with currying ( Static.callback() and Prototype.proxy() )
  • Internet Addressable functions/methods, simply add 'Action' to the end of your controllers method() name and it will be Internet Addressable (as long as a route points to that controller).
  • Private functions, any function without 'Action' on the end of its name is NOT Internet Addressable.
  • Easy accessors for Request and Response, available as this.req and this.res (and additionally this.next)

Needs more information

This section of the documentation is either out-dated or incomplete, please ask for help in github or gitter if you need more information.

You define any options along with the Class/Static section of your Controller.extend() call

Controller.extend(
/* @Class */
{
  // Options & Middleware are defined here
},
/* @Prototype */
{
  // Actions here
})
Property Type/s Default Description
route boolean | string | array Dynamic Sets the route/s for the controllers actions, if this is not set it will be automatically determined based off the Controllers name (usually the filename less "Controller", eg User /user/...)
autoRouting boolean | array true Turns automatic routing (binding of routes to the router) on or off, additionally you can provide an array of middleware to attach
restfulRouting boolean true Turns RESTFul routing to actions on or off.
actionRouting boolean true Turns Action Based routing on or off.
service boolean | Model false If set to a CleverStack Model it will provide automatic CRUD routing using restfulActions and/or actionRouting

Needs more information

This section of the documentation is either out-dated or incomplete, please ask for help in github or gitter if you need more information.

module.exports = ExampleController = function() {
    return Controller.extend(
    {
        // example that returns JSON, available from route '/example/hello'
        helloAction: function() {
            this.send({
                message: 'Hi there'
            })
        }
    });
};

Needs more information

This section of the documentation is either out-dated or incomplete, please ask for help in github or gitter if you need more information.

When doing a GET /example it will route to either listAction first OR getAction if listAction is not defined.
If neither are defined, express's .next() function will be called allowing it to fall through the controller and move onto any other middleware you may have configured.
If you want /example/hello as a route, you can simply implement helloAction in your controller and it will be automatically routed to it.

Standard for defining actions

This is the default way to setup a controller to use actions. By default you can also visit /example/12 and it will route to the getAction function in your controller (if it's defined) with this.req.params.id set for you to use (the same applies for all HTTP methods, eg PUT/DELETE/POST/et cetera)

Needs more information

This section of the documentation is either out-dated or incomplete, please ask for help in github or gitter if you need more information.

module.exports = ExampleController = function() {
    return Controller.extend(
    {
        someMiddleware: function(req, res, next) {
            res.send({
                message: 'Hi from middleware!'
            });
        }
    },
    {
        // example that returns JSON, available from route '/example/hello'
        helloAction: function() {
            this.send({
                message: 'Hi there'
            })
        }
    });
};

Your modules routes.js file is what defines which Controllers are loaded and added into routes, this example shows the default way you can attach your controller. (Except for Controllers which have autoRoute enabled, those controllers have these routes automatically attached)

// modules/backend-example-module/routes.js
module.exports = function( app, ExampleController ) {

  // Restful and Action based routing
  app.all( '/example/:action/:id?', ExampleController.attach() );
  app.all( '/example/?:action?', ExampleController.attach() );

  // Middleware routing
  app.use( ExampleController.someMiddleware );

}

Note This will automatically load the ExampleController's dependencies including Services, Models and any other resources.

Note We use ExpressJS as our main web service, so be sure to checkout how to use ExpressJS Routes


Automatic Routing ( Class.autoRouting )
  • Ability to turn on or off autoRouting (true or array for ON, false for OFF)
  • Array notation allows (Connect or any other) Middleware to be attached to the routes that are autoRouted
  • Route naming: Ability to either define your own route (name), or have it automatically generated based on the filename of your controller! (ExampleController would have a route name of /example and /examples in a RESTful fashion )
Examples:
{
    // ...

    autoRouting: [
        // As a String (only available for methods on the controllers Class, either inherited or defined)
        'middlewareFromThisController',

        // Any function
        function definedFunction( req, res, next ) {
            // any function (from any file) that takes these three arguments can be attached
        },

        // CleverStack example
        PermissionController.requiresPermission({
            all: 'Example.$action', // optional: ability to define rules based on action (Example.post for POST, etc)
            postAction: false       // optional: ability to define overrides per action (Overrides must include 'Action')
        })
    ],

    middlewareFromThisController: function( req, res, next ) {
        // Attached inside of autoRouting array
        next();
    }

    // ...
}