Quickstart Guide to QuarterMaster

Christopher Ross-Gill
April 21, 2007

Contents

Warning

QuarterMaster is still at an early stage of development, and therefore should be used with utmost caution.  It is, however, at a stage where testing and feedback is greatly appreciated.

1. Installation

1.1. Apache

Requires: A working version of REBOL.  REBOL/Core or even REBOL/Base will do; and Mod_Rewrite access is a must.

  1. Copy qm.r to a CGI capable folder
  2. Set permissions (where necessary) to 755
  3. Create a folder for your application, setting permissions to 777.  It’s best if this folder is not available through the HTTPD service.  If you must, consult .htaccess documentation for methods to prevent unwanted access to this folder
  4. Point the shebang line to your REBOL binary
  5. Change the config object after the REBOL header to suit your needs
  6. At your site root, create (or modify) an .htaccess file to include the following:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+) /cgi-bin/qm.r [QSA,L]

That should be enough to start.

1.2. Cheyenne

Currently this does not work with the .exe version of Cheyenne.

  1. Copy qm.r to the root directory as defined in http.cfg
  2. Copy mod-qm.r to Cheyenne’s mods/ folder
  3. In the modules block in http.cfg, switch static for qm
  4. In handlers/CGI.r change the line that reads soc/path-info: join data/in/path data/in/target to soc/path-info: data/in/url
    (this may not be necessary in later versions of Cheyenne)
  5. In qm.r, change the config object after the REBOL header to suit your needs

2. Applications

An application consists of Model, View and Controller components, contained within their relative subfolders:

my-application/
+-- models/
views/
controllers/

Note: Ensure that in QM’s config, the “system” file space points to /path/to/my-application/.  The component subdirectories should exist before invoking QM.

2.1. Controllers

Controllers evaluate user requests, communicates with the Model, then selects the appropriate View.  The particular Controller is determined by the request URI:

http://a-site.net/pages/welcome

This URI would invoke the ‘pages’ Controller.

controllers/pages.r

A controller is a REBOL file that contains: a router and some actions.  It can also contain helper functions related to that controller:

REBOL [
title: "Pages Controller"
type: 'controller
default: "welcome"
]
 
event "prepare" does [
welcome-message: "Welcome!"
]
 
action "welcome" does [
render %welcome.rsp
]
 
action "hello" does [
redirect-to %/pages/welcome
]
 
action "contact" does []

Left untouched, an action automatically invokes a View with the corresponding name.  In this case, the ‘contact’ action renders %contact.rsp

2.2. Views

Views primarily consist of RSP pages, though other pre-processors can be used.  The Views folder contains subfolders that correspond to controllers, containing files that correspond to actions:

views/
+-- pages/
+-- welcome.rsp
contact.rsp

Documenting RSP is beyond the scope of this introduction.  A sample for %welcome.rsp might be:

<html>
<head><title>Welcome</title></head>
<body>
<h1>Welcome!</h1>
<p>Welcome this fine <%= form-date now "%A" %>!</p>
</body>
</html>

2.3. Models

By default, QuarterMaster uses a flat-file, single-table DBMS.  Records are manipulated using the Active Record pattern.

What it lacks in sophistication, it makes up for in flexibility.  Each record is assigned its own subdirectory that can be used to store all manner of related files.  Tables are defined in the models folder:

models/
+-- pages.r
users.r

A definition includes a router (id->folder), key indices, active record methods.

REBOL [
title: "Pages Database"
type: 'roughcut
]
 
record: make record [
get-web-content: does [
read path/web-content.html
]
]
 
index: [name tags] ; indexing is not yet implemented

Once a definition exists within the Model folder, you can go straight to work:

page: select pages "welcome"
page/get-web-content
notes: select pages [where tags = "notes"] ; queries are not yet implemented
map notes func [page][page/get-web-content]
close pages

3. Key Features

3.1. Environment

Sandbox

File sandboxes are built into QM.  The sandbox method used by QM restricts access to predefined folders.  It will prevent access to parent folders or attempts to save files with special characters.

err404: read qm://system/views/errors/not-found.rsp
logo: read/binary qm://site/images/logo.png
Intuitive HTTP Response

Natural polymorphic publishing functions:

render "This"
render/as read/binary qm://site/images/logo.png image/png
render %welcome.rmd ; REBOL MakeDoc
render/status %errors/not-found.rsp 404
redirect-to %/this/page
redirect-to http://rebol.com
External Helpers
>> know %make-doc/scanner.r

qm://root/support/make-doc/scanner.r

REBOL [
Title: "Make-Doc Scanner"
Exports: [scan-doc]
]
 
...

3.2. Data Driven Helpers

Functions that assist data-driven operations:

Pagination

Pagination allows you to extract a section from a data source in order to browse data in bite sizes:

>> pages: paginate wiki 1
>> ? pages
PAGES is an object of value:
last integer! 1
current integer! 1
next logic! false
previous logic! false
records block! length: 2
offset integer! 0
upper block! length: 0
lower block! length: 0
start logic! true
end logic! true

More to follow…

Form-Date

A variation of strfdate:

form-date now "%A %d"
Import

Data import and validation:

import [one "1" two "2.0"][
one: integer! is less-than 2
two: decimal! three: opt integer!
]

Yields:

[one 1 two 2.0 three none]
Map-Each

Quickly transform a block:

map-each [num name][1 "one" 2 "two" 3 "three"][
num: num * num name: uppercase name
]

Yields:

[1 "ONE" 4 "TWO" 9 "THREE"]
System-Wide Link Dialect

Paths are evaluated and transformed to links:

redirect-to wiki/show/(page-name)
<%: a wiki/show/(page-name) %><%= page-name %></a>
<%: form blog/new %>