FlightPath.txt | |
FlightPath Overview | Myna FlightPath is a Model-View-Controller(MVC) web application framework inspired by CakePHP, CFWheels and Ruby On Rails. |
Glossary | Terms used when talking about Myna FlightPath Applications |
Getting Started | To create a FlightPath template, navigate to the Myna Administrator and select “Add/Update FlightPath App”, and enter a path and folder name, relative to the Myna web root. |
FlightPath Config | FlightPath configuration is stored in the “config” property of $application. |
Behaviors | Behaviors are functions that are applied to the current object. |
Elements | An element file is a specialized view (see: Views) that is intended to contain a fragment of output (usually HTML) that can be used in a view |
Layouts | A layout file is a specialized view (see: Views) that is intended to wrap content before sending it to the browser. |
Modules | Modules are self-contained FlightPath applications that can be embedded in other applications. |
Routes | Routes are URL patterns that can be mapped to controllers and actions. |
Views | View Templates are .ejs templates used to render the result of an action. |
Myna FlightPath is a Model-View-Controller(MVC) web application framework inspired by CakePHP, CFWheels and Ruby On Rails.
Myna FlightPath is an application template that implements much of the infrastructure web developers typically have to create to start working on a web application. This allows you to write your business logic as plain JavaScript functions, your displays as EJS templates, and have your data objects automatically generated from the database, nearly eliminating the need to write SQL.
MVC framework | Strong separation of data, business logic and display.Each of these can be manipulated independent of the others. |
Automatic model generation | If your application has a single datasource, FlightPath will create models for that datasource automatically, just when needed. FlightPath will also analyze foreign key relationships and create related models. Data type constraints are also analyzed and become validators. See: Model |
URL “routes” | It is possible with FlightPath to map virtually any URL to an action. “appdir/book/get/12”, “appdir/mypage.html”, “appdir/index.sjs?controller=test&action=run” are all valid URLs. An action can even have multiple routes assigned to it. |
Ext.Direct support | FlightPath provides a builtin-in controller to handle Ext.Direct API calls. See: Controller: Direct |
Authentication and authorization | FlightPath comes with an optional permissions behavior that can secure individual controllers or whole applications. See: Behavior: MynaAuth |
Terms used when talking about Myna FlightPath Applications
$flash | Global temporary message store. Intended for displaying messages to the user regardless of which action will be next loaded. Used by $FP.redirectTo and the default Layout. See: $flash |
$FP | Global FlightPath object that contains functions accessible from everywhere in a FlightPath application. See: $FP |
Action | A function on a Controller that takes input from a web request, sets data on the controller instance, and picks a View to render the data back to the browser. |
bean | An instance of a beanClass. Represents a single object from a Model data store. |
beanClass | A class associated with a Model that represents a “row” of data from that model. This class contains functions for getting and setting values, validating values, field metadata, etc. Also contains liks to related beans from related <models> |
Behavior | A mixin class that overrides, alters, or appends functionality to a class. Behaviors can be applied to either Controllers or Models. See: Behaviors |
camelCase | name format where all words are lower case, first letter of each word after the first capitalized, with no separation. ex: employeeAction |
Controller | Refers to either a Controller class or instance. Controllers contain Actions manage Layouts, an contain Behaviors, and Filters |
Element | Specialized View template for containing output snippets to be included in a View |
Filter | A function applied in the init() function of a Controller to be executed before or after an Action. This can be used to alter how actions are performed without changing the actions themselves. For example authentication and permissions checks can be performed in filters and certain actions can be denied or audited. See: Controller.addFilter |
file_case | a name format where all words are lower case, and separated by underbars(_). ex: employee_action |
Helpers | Helpers are function libraries used inside of Views and Actions for repetitive tasks, usually related to generating output. See: $FP.helpers.Html |
Layout | Specialized View template set in a Controller to wrap content created by an Action, See: Layouts |
Model | Refers to either a Model class or instance. Models in FlightPath are static singletons (Only one instance per request). Model Functions can return one or more beanClass instances that contain the actual model data |
ProperCase | name format where all words are lower case, first letter capitalized with no separation. ex: EmployeeAction |
Route | A URL pattern that maps to a controller an d action. A FlightPath application can support multiple routes. See: Routes |
url-case | a name format where all words are lower case, and separated by underbars(_) or dashs(-). ex: employee-action, employee_action |
View | An .ejs template intended to be sent to the browser. There are also specialized views: Layouts and Elements |
To create a FlightPath template, navigate to the Myna Administrator and select “Add/Update FlightPath App”, and enter a path and folder name, relative to the Myna web root. If this directory does not exist, it will be created. Once The FlightPath template has been unpacked you will see a directory structure like this:
+-application.sjs
+-app/
+...
+-framework/
+...
The “framework” folder contains the FlightPath framework code. These files will be overwritten future uses of the “Add/Update FlightPath App” feature. Here you will find built-in controllers and behaviors such as Controller: Direct and Behavior: MynaAuth. You should not modify any files in this folder.
”application.sjs” is a standard Myna application definition (See: $application), With custom “config” section specific to FlightPath (See: FlightPath Config)
The “app” folder contains your application. These files will not be altered by future uses of the “Add/Update FlightPath App” feature.
+-app/
+-behaviors/
| +-controllers/
| \-models/
+-controllers/
| \-global.sjs
+-models/
| \-global.sjs
+-modules/
+-static/
\-views/
+-elements/
+-home.ejs
+-layouts/
| \-default.ejs
\-themes/
behaviors | Stores Controller behaviors in the “controllers” folder and Model behaviors in the “model” folder. See Behaviors |
controllers | Stores Controller files. File names should be lower case with underbars (_) between words and “_controller” on the end, e.g. MyItem becomes my_item_controller.sjs. The global.sjs file is included before every controller file. Use this file for global initialization and/or to add common functions to all controllers. The init() in the global.sjs file is executed before the controller’s init() |
models | Stores Model files. File names should be lower case with underbars (_) between words and “_model” on the end, e.g. MyItem becomes my_item_model.sjs. The global.sjs file is included before every model file. Use this file for global initialization and/or to add common functions to all models. The init() in the global.sjs file is executed before the model’s init() |
modules | Modules are self-contained FlightPath applications that can be embedded in other applications. These controllers, models and views can be accessed as if they were in the main application. See: Modules |
static | This folder contains static content that will not be interpreted as Myna or FlightPath code. These files are accessed via http://server.tld/appname/static/filename This is a good place for images, client-side JavaScript files and css files |
views | This folder contains a sub-folder for each controller that has views. For example the view for the Main controller’s index() action would be views/main/index.ejs |
views/home.ejs | default page loaded if no homeRoute is defined (see: FlightPath Config) |
views/elements | This folder contains any Elements defined for the app |
views/layouts | This folder contains any Layouts defined for the app, including the global layout. This folder may also contain sub-folders by controller name. |
views/layouts | reserved for future use |
First, let’s edit our application.sjs file and disable our default datasource, for now
// in application.sjs
...
config:{
ds:{
//"default":"flight_path_app"
},
...
You should probably edit the appname and other metadata properties while you are here
// in app/controllers/main_controller.sjs
function index(){
this.renderContent("Hello World!")
}
You can now access this via /yourapp/
This works because the default route (See: FlightPath Config) is set to Main.index. The full URL would be /yourapp/main/index
This is fine for a single line of text, but it is not very flexible for HTML. Lets add a view:
// in app/controllers/main_controller.sjs
function index(){
this.set("text","Hello World!");
}
<%-- in app/views/main/main_index.ejs --%>
<h1><%=text%></h1>
In our controller we set some data that then appears as a global variable in our view. If you view source on this page you’ll see something like this:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="description" content="" />
<meta name="keywords" content="" />
<title>Main.index</title>
<link rel="shortcut icon" href="/dev/favicon.ico" >
<script type="text/javascript" src="/dev/shared/js/libOO/client.sjs"></script>
</head>
<body>
<div class="flash_message_container">
</div>
<h1>Hello World!</h1>
</body>
</html>
All that extra HTML wrapping your view is coming from the default layout in app/views/layouts/default.ejs. Unless you make a call to Controller.setLayout all views in your app will be wrapped in this layout. You can manipulate the metadata in this layout by setting properties on Controller.$page. Let’s set a title for our page.
// in app/controllers/main_controller.sjs
function index(){
this.$page.title = "Howdy"
this.set("text","Hello World!");
}
That’s entertaining, but it would be nice to work with some actual data. Let’s create a database to work with
// in application.sjs
...
config:{
ds:{
"default":"fp_app"
}
...
}
...
onRequestStart:function(){ // run directly before requested file
if (!Myna.Admin.ds.exists("fp_app")){
Myna.Admin.ds.createLocalDatabase("fp_app")
var db = new Myna.Database("fp_app");
db.getTable("authors").create({
recreate:true,
columns:[{
name:"id",
isPrimaryKey:true,
type:"VARCHAR",
maxLength:255,
allowNull:false,
},{
name:"name",
type:"VARCHAR",
maxLength:255,
}]
});
db.getTable("posts").create({
recreate:true,
columns:[{
name:"id",
isPrimaryKey:true,
type:"VARCHAR",
maxLength:255,
allowNull:false,
},{
name:"slug",
type:"VARCHAR",
maxLength:255,
},{
name:"created",
type:"DATE",
},{
name:"author_id",
type:"VARCHAR",
maxLength:255,
references:{
table:"authors",
column:"id",
onDelete:"cascade",
onUpdate:"cascade",
}
}]
});
db.getTable("post_contents").create({
recreate:true,
columns:[{
name:"id",
isPrimaryKey:true,
type:"VARCHAR",
maxLength:255,
allowNull:false,
},{
name:"post_id",
type:"VARCHAR",
maxLength:255,
references:{
table:"posts",
column:"id",
onDelete:"cascade",
onUpdate:"cascade",
}
},{
name:"content",
type:"TEXT"
}]
});
db.getTable("tags").create({
recreate:true,
columns:[{
name:"id",
isPrimaryKey:true,
type:"VARCHAR",
maxLength:255,
allowNull:false,
},{
name:"tag_name",
type:"VARCHAR",
maxLength:255,
}]
});
db.getTable("posts_tags").create({
recreate:true,
columns:[{
name:"post_id",
type:"VARCHAR",
maxLength:255,
allowNull:false,
},{
name:"tag_id",
type:"VARCHAR",
maxLength:255,
allowNull:false,
}]
});
}
var frameworkFolder=this.config.frameworkFolder||this.dir + "framework"
Myna.include(frameworkFolder+"/FlightPath.sjs",{}).init().handleRequest();
}
...
This creates a local database with some example tables for a blog application. Have a look at Myna.Admin, Myna.Database and Myna.Table for more details. If you were including this in a real application, you might limit it to development environments or at least move it to onApplicationStart which runs less often.
Notice that the names are plural, and the primary and foreign keys are defined. This is important for the Models to properly auto generate (See: Model.Model Conventions).
Lets create a way to edit our posts.
//in app/controllers/post_controller.sjs
function edit(params){
// Generate ID for new record if none-supplied. That way ID will be in
// the URL and refreshing the page won't create a new record
if (!params.id){
$FP.redirectTo({
id:this.model.genKey()
})
}
// only get here if not re-directed
this.set("bean",this.model.get(params));
}
Here we’re creating an “edit” action that can be used for both new posts and existing posts. New posts will generate a unique key that will be used when the post is saved. If you looks at ManagerObject.genKey, you will see that for tables with a varchar primary key, the default key generator outputs UUID’s. This can be overridden in Model definitions. See $FP.redirectTo for how redirects work.
Finally, we set a local “bean” property with the result of “this.model.get(params)” (See: Model.get). This creates a temporary bean that contains either the data of an existing bean, or the default values for a new bean
<%-- in app/views/post/post_edit.ejs --%>
<form action="<%=Html.url({action:"save",id:bean.id})%>" method="post">
<table width="100%" height="1" cellpadding="0" cellspacing="0" border="0" >
<tr>
<th ><%=bean.getLabel("id")%>:</th><td><%=bean.id%>, <%=bean.getLabel("created")%>: <%=bean.get_created()%><td>
</tr>
<tr>
<th><%=bean.getLabel("slug")%>:</th>
<td><input name="slug" value="<%=String(bean.get_slug()||"")%>"><td>
</tr>
<tr>
<th><%=bean.Author().getLabel("name")%>:</th>
<td><input name="Author.name" value="<%=String(bean.Author().name||"")%>"><td>
</tr>
<tr>
<th colspan="2" align="left"><%=bean.PostContent().getLabel("content")%>:</th>
</tr>
<tr>
<td colspan="2" align="left">
<textarea cols="70" rows="50" name="PostContent.content"><%=String(bean.PostContent().content||"")%></textarea>
<td>
</tr>
<tr>
<td colspan="2" align="right">
<button type="submit">Save</button>
</td>
</tr>
</table>
</form>
Note the form action. Here we are using the Html helper (see: $FP.helpers.Html) to make a URL for our “save” action. Next, note that the “bean” property we set in the action is now a global variable in the view (See: Views). We’re using <Model.beanClass.getLabel> to get a label for each field. This allows for centralized field name definition in Model files, and potentially even international language translation.
The bean’s getters (get_created, get_slug, etc) will return either the current value or the default value defined in the Model file, depending on whether this is a new or an existing record.
Notice the line containing “bean.Author()”. This is accessing the related parent author bean. Myna knows that Posts belongTo Authors because of the foreign key defined on the posts table. If this is a new post then there will not be an associated parent Author record. In this case a new parent record will be created. Normally you would probably want to have a <select> here and have a separate Author controller manage Author records. On the next line, notice that the name for the input field is “Author.name”. Myna recognizes structure and array notation in query variables and attempts to reconstruct complex objects from them (See: $req.data and Object.setByPath) This means that the “params” object passed the “save” action will have an Author object with a “name” property. Because the Post model knows that it belongsTo Author, it will automatically create or load the related Author record and set its “name” property. More on that when we get to save()
Notice that we are doing something similar with PostContent. Because the post_contents table has a foreign key to posts, the Post model knows it potentially has a “hasMany” or “hasOne” relationship with post_contents. By using “PostContent.content” we are using the “hasOne” relationship to create a content row and associate it with this post.
// in app/controllers/post_controller.sjs
...
function save(params){
var bean = this.model.get(params);
var validation = bean.save();
if (validation.success) {
$FP.redirectTo({
action:"index",
success:"Record Saved."
})
} else {
$FP.redirectTo({
action:"edit",
id:bean.id,
error:validation
})
}
}
Here we create a temporary bean via Model.get and the attempt to save it via <Model.beanClass.save>, which returns a Myna.ValidationResult. If successful we redirect to the index page, otherwise back to the edit page. The extra parameters to redirectTo (“success” and “error”) are converted into $flash messages and displayed via the default layout
All that is left now is to make the index page to display our posts
// in app/controllers/post_controller.sjs
...
function index(params){
//this will pass paging info from params to the underlying query
params.setDefaultProperties({
page:1,
pageSize:25
})
this.set("rows",this.model.findBeans({},params))
}
<%-- in app/views/post/post_index.ejs --%>
<%=Html.link({
action:"edit",
text:"Add Post"
})%>
<table width="100%" height="1" cellpadding="0" cellspacing="0" border="0" >
<tr>
<th><%=$controller.model.getLabel("id")%></th>
<th><%=$controller.model.getLabel("slug")%></th>
<th><%=$controller.model.getLabel("created")%></th>
<th><%=$controller.model.Author.getLabel("name")%></th>
</tr>
<@loop array="rows" element="bean" index="i">
<tr>
<td>
<%=Html.link({
action:"edit",
id:bean.id,
text:bean.id
})%>
</td>
<td><%=bean.get_slug()%></td>
<td><%=bean.get_created().format("m/d/Y H:i:s")%></td>
<td><%=bean.Author().get_name()%></td>
</tr>
</@loop>
</table>
<table width="100%" height="1" cellpadding="0" cellspacing="0" border="0" >
<tr>
<td nowrap>
<@if $params.page != 1>
<%=Html.link({
params:{
page:parseInt($params.page)-1
},
text:"<< previous page"
})%>
</@if>
</td>
<td width="100%"> </td>
<td nowrap>
<@if rows.length == $params.pageSize>
<%=Html.link({
params:{
page:parseInt($params.page)+1
},
text:"next page >>"
})%>
</@if>
</td>
</tr>
</table>
Now we can page through our results and add new posts.
FlightPath configuration is stored in the “config” property of $application.
Here is the default FlightPath config
//--------- FlightPath config -----------------------------------------
config:{
ds:{
"default":"flight_path_app"
},
homeRoute:{
controller:"Main",
action:"index"
},
routes:[{
name:"pages",
pattern:"page/$page*",
controller:"page",
action:"display",
page:"$page"
},{
name:"default",
pattern:"$controller/$action/$id/$restParams*",
controller:"$controller",
action:"$action",
id:"$id"
restParams:"$restParams"
}],
//frameworkFolder:"file:/home/mark/myna/web/shared/js/FlightPath/framework",
MyCustomProperty:"woot!"
},
This structure lists data sources and their manager aliases, where the property is the alias, and the value is the DS name. Normally you only need the default data source. However, if you need access to models from multiple data sources, list them here. Note that you also need to set the manager property of the model to match the manager alias defined here, for any models beyond the default model/DS
Defines the default route the will be executed when no url is provided, i.e. “http/server.tld/appname/”. This structure should include everything that should be passed as “params” to the action
Defines what routes are available in this app. See: Routes
Defaults to “framework”. This is the MynaPath to where the framework folder is located. Setting this to a central location will allow all FlightPath apps to share these files and be upgraded at once. Using the example path of “file:/home- /mark- /myna- /web- /shared- /js- /FlightPath- /framework” will cause the app to always use the version of the FlightPath framework included with the server. When Myna is upgraded, this folder is as well.
All properties in the config will be applied to $FP and are available there from any model, controller or view
Behaviors are functions that are applied to the current object.
Behaviors can be applied to either models or controllers to modify their functionality. If you want to add a set of functions multiple controllers or models behaviors are a good mechanism.
In the case of a name conflict, custom behaviors hide built-in behaviors
//in some_controller.sjs
function init(){
// loads the built-in PDF andJSON filters
// Each of these has an "init" function that adds the appropriate
// before and after filters
this.applyBehavior([
"FormatPdf",
"FormatJson"
]);
//loads a single behavior with options
this.applyBehavior("MynaAuth",{
whitelist:[
"Main.index",
"Main.logout"
],
redirectParams:{
message: "Enter your AD domain credentials",
providers:["ldap_ad"]
}
});
}
An element file is a specialized view (see: Views) that is intended to contain a fragment of output (usually HTML) that can be used in a view
//in app/views/test/index.ejs
<%=getElement("shared/common_commonlinks.ejs")%>
<%=getElement()%>
A layout file is a specialized view (see: Views) that is intended to wrap content before sending it to the browser.
Global Default | app/views/layouts/default.ejs |
Controller Default | app/views/layouts/<controller name>/default.ejs |
General Layouts | app/views/layouts/<layout name>.ejs |
General layouts are stored in app/views/layouts/<layout name>.ejs. The global default layout is stioreController default layouts are store Layouts are applied by calling Controller.addLayout or Controller.setLayout
Layouts can wrap other layouts. For example the global default layout wraps the controller Layouts are layered like so:
/app/views/layouts/default.ejs wraps
/app/views/layouts/controllername/default.ejs wraps
/app/views/controllername/actionname.ejs
function init(){
this.addLayout("mylayout1")
this.addLayout("otherController/mylayout2.ejs")
}
//results in
/app/views/layouts/default.ejs wraps
/app/views/layouts/controllername/default.ejs wraps
/app/views/layouts/mylayout1.ejs wraps
/app/views/layouts/otherController/mylayout2.ejs wraps
/app/views/controllername/actionname.ejs
Modules are self-contained FlightPath applications that can be embedded in other applications. These controllers, models and views can be accessed as if they were in the main application.
A module can be created from a FlightPath application by copying its “app” folder to the new application’s “app/modules” folder and then renaming it to the module name. Then all folders except “models”, “controllers” and “views” should be removed. Local models, controllers and views are always found before module models, controllers and views, so published modules should have names that are unique for these objects.
Routes are URL patterns that can be mapped to controllers and actions. Routes are defined in the config section of the application.sjs for your app (See: FlightPath Config). An incoming URL is matched against the routes array from top to bottom, exiting early if a match is found
name | name of the route. This is used by $FP.helpers.Html.url and $FP.helpers.Html.link to create URL’s that match a particular route. |
pattern | String. Pattern to match. see Pattern Definitions below |
controller | String. Either the URL name of a controller or the placeholder variable that should contain the controller name |
action | String. Either the URL name of an action or the placeholder variable that should contain the action name |
id | Optional String. Either a hard-coded id value or the placeholder variable that should contain the id |
<other> | Optional any other properties will become parameters to the action. Value can be a literal or a placeholder variable |
Patterns are a series of tokens separated by slashes(/). tokens can be:
String literals | ”page”, |
Variable placeholders | ”$page” |
Globbing variable placeholders (must be last token) | ”$page*” |
Regular expressions | ”rpt\\d+\\.\\w{3}” |
Regular expression variable placeholders | ”$report(rpt\\d+\\.\\w{3})” |
Request method prefix (only before first token) | ”[GET]<first token>/<next token...>” |
Request method prefix variable placeholder (before first token) | ”[$method]<first token>/<next token...>” |
The URL is examined from left to right matching URL tokens to route tokens.
Literal tokens are matched as if they were lower case
name:"home",
pattern:"index.html",
controller:"main",
action:"index"
/*
"server.tld/<appname>/index.html"
controller:"main",
action:"index"
*/
Variable placeholders start with $ and can only consist of letters, numbers and the underbar (_). Variable placeholders capture the token in the URL at the position where they appear and assign that value to the route property that has the same value as the placeholder.
name:"emp",
pattern:"emp/$empnum",
controller:"emp",
action:"display",
id:"$empnum"
/*
"server.tld/<appname>/emp/22045563"
controller:"emp",
action:"display",
id:"22045563"
*/
Globbing variable placeholders capture the rest of the URL, including slashes(/)
name:"pages",
pattern:"page/$page*",
controller:"page",
action:"display",
page:"$page"
/*
"server.tld/<appname>/page/archive/2011/dec/christmas-party"
controller:"page",
action:"display",
page:"archive/2011/dec/christmas-party"
*/
Regular expressions need to be matched but don’t capture. Note that they still only match one token
name:"deleted",
pattern:"oldstuff/.*",
controller:"deleted",
action:"error-deleted-content",
/*
"server.tld/<appname>/oldstuff/some-random-file.xls"
controller:"deleted",
action:"error-deleted-content",
*/
Regular expression variable placeholders capture the matched token
name:"reports",
pattern:"reports/$report(rpt\\d+\\.\\w{3})",
controller:"report",
action:"generate_report",
id:"$report"
/*
"server.tld/<appname>/reports/rpt12345.doc"
controller:"page",
action:"generate_report",
report:"rpt12345.doc"
*/
The Request method prefix can be used to test or capture the method used to submit the web request (GET,POST,PUT,DELETE,HEAD). This can be a literal or a variable placeholder.
name:"default",
pattern:"[$method]$controller/$action/$id/$rest*",
controller:"$controller",
action:"$action",
id:"$id",
method::"$method",
extraPath:"$rest"
/*
"server.tld/<appname>/emp/get/22012/pdf"
controller:"emp",
action:"get",
id:"22012",
method:"GET"
extraPath:"pdf"
*/
View Templates are .ejs templates used to render the result of an action. They are stored in app/views. Normally views are loaded automatically for a given controller and action by looking in app/views/<controller name>/<controller_name>_<action_name>.ejs. Views can also be directly rendered via Controller.render
There are also two specialized kinds of view files: Layouts and Elements. Generally Layouts wrap view templates, and view templates include Elements
Views Layouts and Elements have access to several global properties
$controller | A reference to the controller that called this view |
$model | A reference to this controllers default model, may be null |
$params | A reference to the params of the most recent action |
$page | A reference to this controller’s Controller.$page property |
getElement | A reference to <getElement> |
[data properties] | All of the calling controller’s Controller.data properties are available as global variables |
[$FP.helpers classes] | ”Html” refers to $FP.helpers.Html, etc |
.
redirects the browser to another controller/action, cancels further processing.
function redirectTo( options )
Adds an action filter
Controller.prototype.addFilter = function addFilter( filter, options )
Sets a single layout layer to this this request, clearing any existing layouts
Controller.prototype.setLayout = function setLayout( layout )
returns either an instance of an existing bean or the result of getNew
get:function get( values )
sets a property or nested object property of this object
Object.prototype.setByPath=function ( path, value )
loads a behavior and applies it to this object
Controller.prototype.applyBehavior = function applyBehavior( name, options )
loads a behavior and applies it to this object
applyBehavior:function applyBehavior( name )
renders an HTML template returns the content as a string
Controller.prototype.getElement = function renderElement( element, options )
adds a layout layer to this this request
Controller.prototype.addLayout = function addLayout( layout )
Returns a URL for a specified controller and action
function url( options )
Returns an HTML link for a specified controller and action
function link( options )
renders a view
Controller.prototype.render = function render( options )