Lasso Soft Inc. > Home

  • Articles

ARM Framework for Lasso 9

Presentation at Lasso Developer Conference May 2012
by Douglas Burchard

Philosophy

Every project should start with a philosophy, to help keep the effort focussed. Let's begin with then, with the philosophy behind Arm.

Easy

Lasso itself made its largest gain in marketshare by being easy to get started with. Arm should bring some of that back, by providing as gentle a learning curve as possible, while still promoting best practices in programming.

Small, but Capable

Arm's footprint should be remarkably small. But, balanced against its size, Arm should have the potential for an enormous amount of features. Through custom configuration, Arm should provide everything you want, but nothing you don't need.

Free

Yes, free as in speech. And yes, free as in beer. But, also free as in "spirit", or "style". Arm should always allow the developer as much flexibility in their own style as possible. Do you want to produce XHTML, HTML5 (with or without trailing slashes), pure XML, or some hybrid of your own? Arm should allow you to produce what you want, without modification of the framework.

Features

Clean

Clean URLs allow separating a web application from the underlying technology. They also make the URL more human readable, which improves both security and usability. Clean URLs make an application's focus be on resources, rather than locations.
A framework like Arm couldn't work without clean URLs. Arm expects there to be a single file, index.lasso for example, that accepts every request, and directs that request to the appropriate file and custom type. A URL rewriting mechanism on the web server is typically used to accomplish this, and the original request is placed in a parameter named "_q" for use by the Arm framework.

	<VirtualHost *:80>
			RewriteEngine on
			RewriteCond /path/to/webroot/%{REQUEST_FILENAME} !^.*.LassoApp [NC]
			RewriteCond /path/to/webroot/%{REQUEST_FILENAME} !-f
			RewriteRule ^(.*)$ /index.lasso?_q=$1 [PT,L,NC,NE,NS,QSA]
		</VirtualHost>

The aforementioned single index.lasso file then loads the Arm library, and calls the arm object. The default path, and unknown path, are specified in the event the request cannot be resolved to an appropriate file and custom type.

Example: index.lasso
			library_once( '/_libraries/arm.lasso' )
			arm( -defaultpath = '/_controllers/home_cont.lasso',
				-unknownpath = '/_controllers/error_cont.lasso' )

RESTful

The Arm framework supports a RESTful (Representational State Transfer) architecture, through its mapping of paths to custom types, and the arm_request object.
In the terminology of Arm, the first path-segment of the requested URL is the "path", and any remaining portion of the requested URL is the "route". When a request is made, the path is automatically mapped to a custom type by the file and type name. So, a request for http://example.com/users would be mapped to the users_cont type, in the file _controllers/users_cont.lasso. So, a path represents a resource in a RESTful architecture.

Example: URL
	http://www.example.com/path[/route]

Example: Form
		<form action="/path[/route]" method="POST">
			<input type="hidden" name="_method" value="PUT">
		</form>

In addition, the arm_request object, which is automatically available, can be used to characterize a client request as a sort of request signature. This signature consists of the request method, route, and parameters (action_params). Arm_request understands four HTTP methods: GET, POST, PUT, and DELETE. Since many – perhaps most – current browsers don't understand the last two themselves, arm_request also supports a Rails-style “_method” parameter as an override to the HTTP request method.

Example: Request Signature
		arm_request( -method = 'GET', -route = '/' ) => { … }
		arm_request( -method = 'GET', -route = '/new' ) => { … }
		arm_request( -method = 'POST', -route = '/' ) => { … }
		arm_request( -method = 'GET', -route = '/!new' ) => { … }
		arm_request( -method = 'GET', -route = '/:any/edit' ) => { … }
		arm_request( -method = 'PUT', -route = '/:any' ) => { … }
		arm_request( -method = 'DELETE', -route = '/:any' ) => { … }

DRY

Arm helps you to not repeat yourself, or your code, by providing a layered approach to your code structure. For the model, view and controller objects, there's the Arm level – which should never be modified, the application level, and the path level. Each layer inherits from the previous layer, so you can write once, and reuse the same code block.

Example: Controller inheritance
		define arm_controller => type { ... }
		define myapp_controller => type { 
			parent arm_controller 
		}
		define mypath_controller => type { 
			parent myapp_controller 
		}

Since Arm also allows multiple applications per site, you could add additional layers to further refine your code's scope.

MVC

Arm is a true Model / View / Controller based architecture. Client requests are directed to a path-controller, that controller takes data from one, or many, models as needed, to satisfy the request, and passes that data onto the view. That view accepts the direction of the controller, then assembles the final response, starting with a template, and making changes as needed.

Example: Object Structure

The path-controller file loads the application library – which contains definitions for the application-level controller, model, and view types – as well as libraries for the needed models and view. Arm will create an object from the path-controller type, and call the “main” method for that new object.
The controller's main method needs to specify any needed models, the view, and tell the view which template to use. Following that, the main method can pull data from models, and push that data to the view, as appropriate. You can perform the entire controller operation within the main method, or break up the operation among additional methods, as needed.

Example: Controller
library_once( '/_libraries/app_myapp.lasso' )
			library_once( '/_models/home_mod.lasso' )
			library_once( '/_views/home_view.lasso' )
			define home_cont => type {
				parent myapp_controller
				public main()::void => {
					.model( 'home' = home_mod )
					.view( home_view )
					.view->template( '/_templates/default.lasso' )
					.view->title( 'Welcome - My Local School' )
					.view->bannertext( 'Welcome to Our School' )
					.view->mainbody(
						'We’re so glad to have you visit.'
					)

The path-view inherits a lot of functionality from the arm-level view type. For example, without modification, the 'title' method will automatically change the contents of the "< title > … < /title >" container within the template. And, any unknown method will replace a similarly named placeholder in the template, with its first parameter.

In the controller example above, we told the view to replace both the bannertext and mainbody, placeholders with strings of text. But, we need the mainbody-text to be surrounded with HTML paragraph tags. It's good practice, to the extent possible, to not use structural tags, like HTML, in the controller, but to leave that to the view. So, we create a mainbody method in the view type that does this for us.

Example: View
define home_view => type {
				parent myapp_view
				public mainbody(package::string)::void => {
					.values->insert( 'mainbody' = '<p>' + 
						encode_html( #package ) + '</p>' 
					)
				}
			}

Templates typically contains only HTML, or some other markup language. It's best practice to keep each template file as a complete and valid document. It's possible to use includes, or Arm's mechanism called fragments, but try to keep each piece complete and valid on its own.
Placeholders within the template look similar to HTML comments. They take the form
, with the asterisks trailing the opening bracket denoting that this is an Arm-comment, and the leading dollar-sign denoting the placeholder name. By the way, any Arm-comment, meaning any structure similar to will be automatically removed before the results are sent to the client.

Example: Template
<!DOCTYPE html>
		<html lang="en">
			<head>
				<meta charset="utf-8">
				<title>Untitled</title>
			</head>
			<body>
				<div id="page">
					<header id="banner">
						<h1><!--* $bannertext --></h1>
					</header>
					<section id="mainbody">
						<!--* $mainbody -->
					</section>
					<nav id="nav">
						<!--* $nav -->
					</nav>

As stated earlier, Lasso-code can be added directly into the template, for example: [include( 'somefile.lasso' )]. If you do not want this, you can turn this feature off by using the -nolasso keyword when specifying the template. For example: .view->template(
'/_templates/default.lasso', -nolasso ).
The model may have as many custom methods as it needs to return the data that might be requested by the controller. As such, there isn't much of a pattern to the model, other than the inheritance from the model type on the application layer.

Example: Model
		define users_mod => type {
			parent mylocalschool_model
			public columns(params::staticarray = staticarray)::pair => { ... }
			public list(
				-sortfield::string = '',
				-sortorder::string = 'ascending'
			)::staticarray => { ... }
			public create(params::staticarray) => { ... }
			public show(key::string)::pair => { ... }
			public update(params::staticarray, -key::string)::boolean => { ... }
			public delete(key::string)::boolean => { ... }
		}

The key points of the file structure are the name of the _controllers directory, and the name of the individual controller files, since these are discovered dynamically by the Arm framework. However, it should be best practice to have a standard directory and file structure. Arm's core directories all begin with an underscore character. This both groups them together, and establishes a signature look to an Arm-based site.

Example: File structure

ArmSetup

ArmSetup is a command line utility written in Lasso, that asks a few direct questions about the web application you want to create; and generates in seconds, a scaffold from which you can develop further. The assistant not only speeds development, but supplies a custom configuration of features. Which, allows the Arm framework to provide everything you want, but nothing you don't need.
Plugins are a key feature of the ArmSetup assistant. They enable third-party expansion of the Arm feature set, and also permit further development of the assistant, without changes to the core script.

Example: Object structure

When you first download the Arm source code, the directory contains docs, license, a ReadMe file, a Plugins directory, a SupportFiles directory, and the ArmSetup script.

Example: File structure

Demonstration

The best way to understand the ArmSetup assistant, is to try the ArmSetup assistant. Download a copy of the Arm source code. Open a terminal window. Navigate into the downloaded folder. And, type in "sudo lasso9 ArmSetup". Read each question, and type in your answer. When you're finished, you'll have a customized code scaffold, ready for further development.

Roadmap

Arm itself has been evolving for sometime. By contrast, the ArmSetup assistant is a relatively new piece of code, having been started just this January. While Arm will certainly be growing in the next several months, ArmSetup is where the next big strides will happen. ArmSetup just had plugin's added, and that API needs additional work. An SDK that would encourage additional developers to start developing plugins would be a logical following step.

With a new API, and SDK, additional plugins would help expand the head start developers can gain by using ArmSetup. The existing CRUD plugin could use expansion on the nature of the resulting code. An Authentication/Authorization plugin, and a CMS plugin are already in development. Additional ideas, votes, and comments, would be greatly appreciated.
Ultimately, the plugin API should support a skin of ArmSetup, that would provide a graphical interface. This would bring the development full circle, back to the first item under "philosophy"; that Arm should promote as gentle a learning curve as possible.

Where do I get Arm?

The latest source code for Arm and ArmSetup, both stable and bleeding edge, can be downloaded starting now, from GitHub. Just go to https://github.com/dburchard/arm. If you're not familiar with GitHub, just click on the tab labeled "ZIP".

License

Copyright © 2012 Douglas Burchard
Arm is released under three licenses: MIT, BSD, and LGPL. You may pick the license that best suits your development needs. See the LICENSE file accompanying the download for more information.

About Douglas Burchard

Douglas Burchard has been creating professional data-driven web applications since 1996. Doug has a background in graphic design, and an interest in web usability, accessibility, and security.
Specialties include: Lasso (all versions), MySQL(4/5), HTML5, CSS3, jQuery, Apache(1.3/2.x), and the Arm framework. As well as, online and offline professional education in small to medium classroom settings, outdoor skills-based learning, and emergency response in wilderness environments.
When not developing online solutions, Doug spends time with his wife and son camping, hiking, fishing, and skiing. Doug also volunteers with the Summit-at-Snoqualmie Central Ski Patrol, Ski Patrol Rescue Team, and King County Search And Rescue as an EMT-B, an OEC Technician, an instructor for EMT, Survival, and Search Management, and oversees the organization's primary fundraiser.

Douglas Burchard
15024 NE 66th Street
Redmond, WA  98052
http://www.douglasburchard.com/
solutions@douglasburchard.com
206/227-8161 (M-F, 9 AM-4 PM PST)
 

Author: Douglas Burchard
Created: 26 May 2012
Last Modified: 5 Jun 2012

Comments

No comments found
You must be logged in to comment.

Please note that periodically LassoSoft will go through the notes and may incorporate information from them into the documentation. Any submission here gives LassoSoft a non-exclusive license and will be made available in various formats to the Lasso community.

LassoSoft Inc. > Home

 

 

©LassoSoft Inc 2014 | Web Development by Treefrog Inc | PrivacyLegal terms and Shipping | Contact LassoSoft