Reply to comment
Nüby
Submitted by bingomanatee on 19 January, 2011 - 12:43Nüby is an attempt to create a MVC framework that encapsulates the mundane aspect of request brokering and makes it easy to toss up a page at a given url. Nüby emphasizes isolating the business parts of the action -- the parts that matter to you -- from the authorization, layouts, flash messages, session data et al. (see "Why" link below for more detail). Its emphasis is on writing self-contained, blendable web components. and breaks actions into independent units where most other MVC tools "gang" them into a long bulky single controller file.
The Action Hierarchy
Nüby applications are built around a hierarchy of objects.
- The framework at the top of the hierarchy contains an Express app as an exposed property.
- In the initialization process, controllers are loaded from one or more component folders. Unlike Ruby with its singular app folder, Nüby can load an arbitrary number of component folders.
- Each component folder has one or more controller folders.
- Each controller folder has one or more action folders.
- The action folders have at least two files as a rule: action.js and view.html.
- Lastly, a req_state object(see below) is created to manage each individual request.
Note that each element on the hierarchy has the elements above it as properties, for convenience. I.e., controllers, actions, and req_state all have the framework value attached to its framework property; actions and req_state have their controller property set to the current controller, and the req_state has the action as the value of its action property.
The Request State (req_state) object
Every action is governed by the Request State (req_state) object. This object contains req and res from express, as well as a host of functions for getting and setting session values, flash messages, and most importantly parameters. As the view file is set by convention for all actions, the final step in most actions is to pass control back to the req_state object either through a call to req_state.render(params).
The Parameter Stack
Parameters are an amalgam of framework, controller and action configuration and request post and URL parameters. Every object in the hierarchy has a params object. This object is a dictionary of arbitrary parameters, for settings, defaults, etc. that is, if you set the frameworks param.foo value to 3, everything from the controllers to the actions to the req_state's params' foo will default to 3 unless, say, a controller sets its param.foo to 4, in which case, all its actions will default to 4, unless overridden at the action level.
Request Parameters
This might seem a bit confusing -- but the input parameters from the route definition can be automatically inserted into req_state.params by setting an actions load_req_params parameter to true. Or they can be stored in an arbitrary parameter - say "input" -- by setting an actions' load_req_params value to "input". (note- load_req_params is NOT itself in the params collection.)
Also the request body, if it exists, is assigned to the req_state.params.form property, if action.load_req_params is truthy.
req_state.set_param and req_state.get_param
req_state.set_param(key, value [,context, extend]) is straightforward. Key can be a string or an array of strings for deep insert. context and extend are not that important; context is the label of the current function, used mainly for journaling. extend allows you to merge an existing object with the passed object. This is especially useful for adding several parameters to the render parameter without erasing any values previously set.
req_state.get_param(key, callback, absent) is pretty simple; again, key can be an array, and the value if present will be passed as the second property of the callback. If the value is absent the absent value (if present) or null is passed to the callback.
Note that absent can be a function, which if the value is not present, is called. Absent functions have the signature (req_state, callback).
Parameters can be polled "en masse" via req_state.get_params(param_array, callback). see below for details.
Writing Actions
The core of action customization happens within the execute(req_state, callback) method. Any parameters passed to the callback -- i.e., callback(null, {user: my_user, date: new Date()}) -- will be made available to the view. The below is an example page for listing the movies a user likes:
{
load_req_params: "input",
execute: function(req_state, callback){
_on_user_movies(err, movies){
callback(null, {user_movies: movies});
}
_on_user_id(err, uid){
if (uid) {
req_state.models.user_movies.find({user: uid}, _on_user_movies);
}
}
req_state.get_param('user_id', _on_user_id, 0);
}
}Authentication
There is a built in authentication method in every action that is called before execute: auth(req_state). Whatever ACL you have can be included by overriding that method.
REST controllers
There are (currently) two types of controllers: rest controllers and default controllers. REST controllers actively seek out any actions in the rest folder that are named using the standard REST verbs: get, put, post, delete.
* A component is a series of reusable tools, like a user component, a blog component or a photo album component; what you'd call "Modules" in any other CMS if Node itself hadn't grabbed that term.
