webmcp

annotate doc/autodoc-header.htmlpart @ 525:8c9bcfc22faa

Revised "Installation" section of documentation
author jbe
date Tue Aug 22 03:26:51 2017 +0200 (2017-08-22)
parents 50746f1e8a43
children fe9932334bae
rev   line source
jbe@509 1 <HTML>
jbe/bsw@0 2 <head>
jbe@381 3 <script type="text/javascript">
jbe@390 4 var expandedSections = {};
jbe@390 5 function toggleSection(ident) {
jbe@390 6 var element = document.getElementById('autodoc_details_' + ident);
jbe@390 7 if (element) {
jbe@390 8 if (expandedSections[ident]) {
jbe@390 9 element.style.display = 'none';
jbe@390 10 delete expandedSections[ident];
jbe@390 11 } else {
jbe@390 12 element.style.display = '';
jbe@390 13 expandedSections[ident] = true;
jbe@390 14 }
jbe@381 15 }
jbe@390 16 }
jbe@391 17 var inProgress = false;
jbe@390 18 window.onload = window.onhashchange = function() {
jbe@391 19 if (inProgress) return;
jbe@390 20 for (var ident in expandedSections) toggleSection(ident);
jbe@390 21 var hash = window.location.hash;
jbe@390 22 if (hash) {
jbe@390 23 toggleSection(hash.replace(/^#/, ''));
jbe@391 24 inProgress = true;
jbe@391 25 window.location.hash = hash; // required after collapsing/expanding
jbe@391 26 inProgress = false;
jbe@390 27 }
jbe@389 28 };
jbe@381 29 </script>
jbe/bsw@0 30 <style>
jbe/bsw@0 31 body {
jbe/bsw@0 32 font-family: "Liberation Sans", sans-serif;
jbe/bsw@0 33 font-size: 11pt;
jbe/bsw@0 34 padding-bottom: 5ex;
jbe/bsw@0 35 }
jbe/bsw@0 36 .warning {
jbe/bsw@0 37 color: #ff0000;
jbe/bsw@0 38 }
jbe/bsw@0 39 h1, h2 {
jbe/bsw@0 40 font-family: "Liberation Serif", Georgia, serif;
jbe/bsw@0 41 }
jbe/bsw@0 42 h2 {
jbe/bsw@0 43 margin-bottom: 0.3ex;
jbe/bsw@0 44 }
jbe/bsw@0 45 p {
jbe@507 46 margin-bottom: 1ex;
jbe/bsw@0 47 line-height: 130%;
jbe/bsw@0 48 }
jbe/bsw@0 49 tt, pre {
jbe/bsw@0 50 font-size: 10pt;
jbe/bsw@0 51 }
jbe/bsw@0 52 tt {
jbe/bsw@0 53 font-weight: bold;
jbe/bsw@0 54 white-space: nowrap;
jbe/bsw@0 55 }
jbe/bsw@0 56 .autodoc_entry {
jbe/bsw@0 57 margin-top: 1ex;
jbe/bsw@0 58 margin-bottom: 1ex;
jbe/bsw@0 59 }
jbe/bsw@0 60 .autodoc_comment_tail {
jbe/bsw@0 61 font-style: italic;
jbe/bsw@0 62 }
jbe/bsw@0 63 .autodoc_entry .short_synopsis {
jbe/bsw@0 64 cursor: pointer;
jbe/bsw@0 65 }
jbe@507 66 .AUTODOC_details {
jbe/bsw@0 67 padding-left: 1em;
jbe/bsw@0 68 padding-right: 1em;
jbe/bsw@0 69 border: 1px solid #777;
jbe/bsw@0 70 }
jbe/bsw@0 71 .autodoc_synopsis {
jbe/bsw@0 72 font-weight: bold;
jbe/bsw@0 73 }
jbe/bsw@0 74 .autodoc_synopsis .autodoc_comment_tail {
jbe/bsw@0 75 font-weight: normal;
jbe/bsw@0 76 color: #008000;
jbe/bsw@0 77 }
jbe/bsw@0 78 .autodoc_entry .autodoc_comment {
jbe/bsw@0 79 color: #400080;
jbe/bsw@0 80 }
jbe/bsw@0 81 .autodoc_source {
jbe/bsw@0 82 color: #505050;
jbe/bsw@0 83 }
jbe/bsw@0 84 </style>
jbe@446 85 <title>WebMCP 2.1.0 Documentation</title>
jbe/bsw@0 86 </head>
jbe/bsw@0 87 <body>
jbe@446 88 <h1>WebMCP 2.1.0 Documentation</h1>
jbe/bsw@0 89 <p>
jbe@278 90 WebMCP is a web development framework based on the Lua programming language (read more about Lua <a href="http://www.lua.org/about.html">here</a>).
jbe/bsw@0 91 </p>
jbe/bsw@0 92 <h2>Requirements</h2>
jbe/bsw@0 93 <p>
jbe@387 94 WebMCP has been developed on Linux and FreeBSD. Using it with Mac&nbsp;OS&nbsp;X is untested as of yet; Microsoft Windows is not supported. Beside the operating system, the only mandatory dependencies for WebMCP are the <a href="http://www.lua.org/">programming language Lua</a> version 5.2 or 5.3, the <a href="http://www.public-software-group.org/moonbridge">Moonbridge Network Server for Lua Applications</a> version 1.0.1 or higher, <a href="http://www.postgresql.org/">PostgreSQL</a> version 8.2 or higher, and a C compiler.
jbe/bsw@0 95 </p>
jbe/bsw@0 96 <h2>Installation</h2>
jbe/bsw@0 97 <p>
jbe@525 98 Please read the following instructions carefully to avoid problems during installation.
jbe@507 99 </p>
jbe@525 100 <ol>
jbe@525 101 <li>Download and compile the <a href="http://www.public-software-group.org/moonbridge">Moonbridge Network Server for Lua Applications</a> (follow the README file of Moonbridge).</li>
jbe@525 102 <li>Optional: Ensure that the <tt>moonbridge</tt> binary is within the search path for binaries.</li>
jbe@525 103 <li>Optional: Ensure that the <tt>moonbridge_http.lua</tt> file is covered by Lua's <a href="https://www.lua.org/manual/5.3/manual.html#pdf-package.path">package path</a> (see Lua's <a href="https://www.lua.org/manual/5.3/manual.html#pdf-package.searchpath">search path documentation</a> on how to format the <tt>LUA_PATH</tt> environment variable).</li>
jbe@525 104 <li>Download <a href="http://www.public-software-group.org/webmcp">WebMCP</a>.</li>
jbe@525 105 <li>Enter WebMCP's unpacked source code directory and execute the command "<tt>make</tt>".</li>
jbe@525 106 <li>If you experience problems during step&nbsp;3, edit the <tt>Makefile.options</tt> file and repeat step&nbsp;3.</li>
jbe@525 107 <li>The <tt>framework/</tt> directory (or the <tt>framework.precompiled</tt> directory if you want to use precompiled code) is WebMCP's framework base directory now. It may be copied to any other directory of your choice (but make sure to follow links, e.g. using <tt>cp -L -R</tt>, when copying the directory to a different place).</li>
jbe@525 108 <li>If optional step&nbsp;3 has been skipped, ensure that Moonbridge's <tt>moonbridge_http.lua</tt> file is soft-linked or copied to the <tt>lib/</tt> directory of the framework's base directory.</li>
jbe@525 109 </li>
jbe@525 110 </ol>
jbe@507 111 <h2>Configuration, initializers, and request handling</h2>
jbe@507 112 <p>
jbe@523 113 WebMCP uses the <a href="http://www.public-software-group.org/moonbridge">Moonbridge Network Server</a> to handle HTTP requests. The Moonbridge Network Server listens to a TCP port and passes control to WebMCP by calling <a href="#request.handler"><tt>request.handler(...)</tt></a> for each request. However, before any request is processed, WebMCP will initialize the environment. This initialization includes tasks such as
jbe@507 114 </p>
jbe@507 115 <ul>
jbe@507 116 <li>loading libraries,</li>
jbe@507 117 <li>configuring the database connection or the application,</li>
jbe@507 118 <li>connecting to the database,</li>
jbe@507 119 <li>etc.</li>
jbe@507 120 </ul>
jbe@507 121 <p>
jbe@507 122 For each request, it is also possible to execute filters. Filters can be used to
jbe@278 123 </p>
jbe@507 124 <ul>
jbe@507 125 <li>
jbe@521 126 restrict access for certain requests, e.g. by performing redirects or raising errors,
jbe@507 127 </li>
jbe@507 128 <li>
jbe@507 129 perform tasks that are common for different requests, e.g.
jbe@507 130 <ul>
jbe@521 131 <li>execute certain database requests,</li>
jbe@507 132 <li>prepare a menu on the website,</li>
jbe@507 133 <li>&hellip;</li>
jbe@507 134 </ul>
jbe@507 135 </li>
jbe@507 136 </ul>
jbe@278 137 <p>
jbe@524 138 Filters and initializers are created by adding files in the application's directory structure. The filename determines the execution order of otherwise equally ranked initializers and/or filters. It is a common idiom to start the filename of a filter or initializer with a two digit number to be easily able to change the execution order when desired. Filters and initializers are executed both before and after a request. Each file must contain an <a href="#execute.inner"><tt>execute.inner()</tt></a> command. The part before that command is executed before the request, and the part after that command is executed after the request.
jbe@507 139 </p>
jbe@507 140 <p>
jbe@507 141 The Moonbridge server creates forks (i.e. clones) of the application server process (i.e. the whole Lua engine including all libraries and variables) in order to handle concurrent requests. Certain initializations may be performed before forking, other initializations must be performed after forking. For this purpose, WebMCP allows an application to provide so-called "pre-fork" and "post-fork" initializers. The application's configuration files as well as its pre-fork initializers are executed before forking. The application's post-fork initializers are executed after forking. In particular, any libraries that open file or network handles during initialization must not be loaded before the server process is forked. Opening database connections must be performed after forking as well. WebMCP follows the following execution order (directory structure is explained further down):
jbe@278 142 </p>
jbe@278 143 <ol>
jbe@278 144 <li>
jbe@520 145 Initialization code of <tt>mcp.lua</tt> in the <tt>bin/</tt> directory of the framework, including:
jbe@520 146 <ul>
jbe@520 147 <li>Initialization of WebMCP's autoloader in <tt>mcp.lua</tt> (in the <tt>bin/</tt> directory of the framework),</li>
jbe@520 148 <li>Execution of <tt>env/__init.lua</tt> (both relative to the framework and, if existent, relative to the application base directory)</li>
jbe@520 149 <li>Loading of most of WebMCP's libraries (excluding "multirand" library, which must not be loaded prior to forking);</li>
jbe@520 150 </ul>
jbe@278 151 </li>
jbe@278 152 <li>
jbe@520 153 Executing the selected configuration file: <tt>config/</tt><i>configuration_name</i><tt>.lua</tt>;
jbe@278 154 </li>
jbe@278 155 <li>
jbe@520 156 Executing all pre-fork initializers (both those in the <tt>app/_prefork/</tt> and those in the <tt>app/</tt><i>application_name</i><tt>/_prefork/</tt> directory) until call of <tt>execute.inner()</tt> within each initializer;
jbe@278 157 </li>
jbe@278 158 <li>
jbe@520 159 The Moonbridge Network Server forks the process (i.e. cloning the whole Lua machine);<br />
jbe@278 160 <span style="color: red">Note: no file handles or network connections must be opened prior to this point!</span>
jbe@278 161 </li>
jbe@278 162 <li>
jbe@520 163 Loading WebMCP's "multirand" library;
jbe@281 164 </li>
jbe@281 165 <li>
jbe@520 166 Executing all post-fork initializers (both those in the <tt>app/_postfork/</tt> and those in the <tt>app/</tt><i>application_name</i><tt>/_postfork/</tt> directory) until call of <tt>execute.inner()</tt> within each initializer;
jbe@278 167 </li>
jbe@278 168 <li>
jbe@278 169 For each request:
jbe@278 170 <ul>
jbe@278 171 <li>
jbe@520 172 Execution of all applicable filters until call of <tt>execute.inner()</tt> within each filter,
jbe@278 173 </li>
jbe@278 174 <li>
jbe@520 175 Handling of the request by calling the appropriate view or action,
jbe@278 176 </li>
jbe@278 177 <li>
jbe@520 178 Resuming execution of all filters in reverse order from that position where <tt>execute.inner()</tt> had been called;
jbe@278 179 </li>
jbe@278 180 </ul>
jbe@278 181 </li>
jbe@278 182 <li>
jbe@520 183 Resuming execution of all post-fork initializers in reverse order from that position where <tt>execute.inner()</tt> had been called;
jbe@278 184 </li>
jbe@278 185 <li>
jbe@520 186 Resuming execution of all pre-fork initializers in reverse order from that position where <tt>execute.inner()</tt> had been called.
jbe@278 187 </li>
jbe@278 188 </ol>
jbe/bsw@0 189 </p>
jbe@439 190 <p>
jbe@509 191 As a minimum configuration, the used configuration file or pre-fork initializer should at least contain a <a href="#listen"><tt>listen{...}</tt></a> call, e.g.:
jbe@439 192 </p>
jbe@439 193 <pre>
jbe@439 194 listen{
jbe@439 195 { proto = "tcp", host = "::", port = 8080 },
jbe@439 196 { proto = "tcp", host = "0.0.0.0", port = 8080 }
jbe@439 197 }
jbe@507 198 execute.inner() -- only use this line if done in pre-fork initializer</pre>
jbe/bsw@0 199 <h2>Using the atom library</h2>
jbe/bsw@0 200 <p>
jbe/bsw@0 201 Lua itself has only very few built-in data types. The atom library gives support for extra data types. Currently the following extra data types are provided:
jbe/bsw@0 202 </p>
jbe/bsw@0 203 <ul>
jbe@509 204 <li><a href="#atom.fraction:new">atom.fraction</a></li>
jbe@509 205 <li><a href="#atom.date:new">atom.date</a></li>
jbe@509 206 <li><a href="#atom.time:new">atom.time</a></li>
jbe@509 207 <li><a href="#atom.timestamp:new">atom.timestamp (date and time combined in one data type)</a></li>
jbe/bsw@0 208 </ul>
jbe/bsw@0 209 <p>
jbe/bsw@0 210 In addition the following pseudo-types are existent, corresponding to Lua's base types:
jbe/bsw@0 211 </p>
jbe/bsw@0 212 <ul>
jbe/bsw@0 213 <li>atom.boolean</li>
jbe/bsw@0 214 <li>atom.string</li>
jbe/bsw@0 215 <li>atom.integer</li>
jbe/bsw@0 216 <li>atom.number</li>
jbe/bsw@0 217 </ul>
jbe/bsw@0 218 <p>
jbe/bsw@0 219 Both atom.integer and atom.number refer to Lua's base type &ldquo;number&rdquo;.
jbe/bsw@0 220 </p>
jbe/bsw@0 221 <p>
jbe@514 222 New values of atom data types are created by either calling <tt>atom.</tt><i>type</i><tt>:load(string_representation)</tt> or by calling <tt>atom.</tt><i>type</i><tt>{...}</tt>, e.g. <tt>atom.date{year=1970, month=1, day=1}</tt>. Note that <tt>atom.date{...}</tt> is a shortcut for <tt><a href="#atom.date:new">atom.date:new</a>{...}</tt>. You can dump any atom value as a string by calling <a href="#atom.dump"><tt>atom.dump(value)</tt></a> and later reload it with <tt>atom.</tt><i>type</i><tt>:load(string)</tt>.
jbe/bsw@0 223 </p>
jbe/bsw@0 224 <h2>Using the Object-Relational Mapper &ldquo;mondelefant&rdquo;</h2>
jbe/bsw@0 225 <p>
jbe@278 226 The library &ldquo;mondelefant&rdquo; shipping with WebMCP can be used to access PostgreSQL databases. It also serves as an Object-Relational Mapper (ORM). The database connection is usually configured in the config file (e.g. in <tt>config/devel.lua</tt>):
jbe@278 227 </p>
jbe@278 228 <pre>
jbe@439 229 config.db = { engine="postgresql", dbname="webmcp_demo" }</pre>
jbe@278 230 <p>
jbe@278 231 In addition to configuring the database, it must be opened within a post-fork initializer (e.g. in <tt>app/_postfork/01_database.lua</tt>):
jbe/bsw@0 232 </p>
jbe/bsw@0 233 <pre>
jbe@509 234 _G.db = assert(<a href="#mondelefant.connect">mondelefant.connect</a>(config.db))
jbe@509 235 function mondelefant.class_prototype:<a href="#db_class:get_db_conn">get_db_conn</a>() return db end
jbe@439 236 execute.inner()</pre>
jbe/bsw@0 237 <p>
jbe@515 238 The parameters for <tt>mondelefant.connect</tt> are directly passed to PostgreSQL's client library libpq. See PostgreSQL's documentation for information about <a href="https://www.postgresql.org/docs/9.6/static/libpq-connect.html#LIBPQ-PARAMKEYWORDS">supported parameters</a>.
jbe/bsw@0 239 </p>
jbe/bsw@0 240 <p>
jbe/bsw@0 241 To define a model to be used within a WebMCP application, create a file named with the name of the model and <tt>.lua</tt> as extension in the <tt>model/</tt> directory of your application. The most basic definition of a model (named &ldquo;movie&rdquo; in this example) is:
jbe/bsw@0 242 </p>
jbe/bsw@0 243 <pre>
jbe@509 244 Movie = <a href="#mondelefant.new_class">mondelefant.new_class</a>()
jbe/bsw@0 245 Movie.table = 'movie'</pre>
jbe/bsw@0 246 <p>
jbe/bsw@0 247 Note: Model classes are always written CamelCase, while the name of the file in <tt>model/</tt> is written lower_case.
jbe/bsw@0 248 </p>
jbe/bsw@0 249 <p>
jbe/bsw@0 250 To select objects from the database, the mondelefant library provides a selector framework:
jbe/bsw@0 251 </p>
jbe/bsw@0 252 <pre>
jbe@509 253 local s = Movie:<a href="#db_class:new_selector">new_selector</a>()
jbe@509 254 s:<a href="#db_selector:add_where">add_where</a>{ 'id = ?', param.get_id() }
jbe@509 255 s:<a href="#db_selector:single_object_mode">single_object_mode</a>() -- return single object instead of list
jbe@509 256 local movie = s:<a href="#db_selector:exec">exec</a>()</pre>
jbe/bsw@0 257 <p>
jbe/bsw@0 258 A short form of the above query would be:
jbe/bsw@0 259 </p>
jbe/bsw@0 260 <pre>
jbe/bsw@0 261 local movie = Movie:new_selector():add_where{ 'id = ?', param.get_id() }:single_object_mode():exec()</pre>
jbe/bsw@0 262 <p>
jbe/bsw@0 263 For more examples about how to use the model system, please take a look at the demo application.
jbe/bsw@0 264 </p>
jbe/bsw@0 265 <h2>The Model-View-Action (MVA) concept</h2>
jbe/bsw@0 266 <p>
jbe/bsw@0 267 As opposed to other web application frameworks, WebMCP does not use a Model-View-Controller (MVC) concept, but a Model-View-Action (MVA) concept.
jbe/bsw@0 268 </p>
jbe/bsw@0 269 <h3>Models</h3>
jbe/bsw@0 270 <p>
jbe@513 271 The models in MVA are like the models in MVC; they are used to access data, which is stored in a relational database (PostgreSQL), in an object oriented way. Methods provided by the corresponding classes can be used to alter stored objects or execute any other associated program code. Models are usually defined in a file with a lowercase filename ending with "<tt>.lua</tt>" in the <tt>models/</tt> directory of the application. The corresponding model name (i.e. class name) must be written in CamelCase, e.g. "<tt>models/my_model.lua</tt>" should define a model class named "<tt>MyModel</tt>". The simplest model is created by calling <a href="#mondelefant.new_class"><tt>mondelefant.new_class()</tt></a> and subsequently setting the <a href="#db_class.table"><tt>table</tt></a> attribute of the returned class.
jbe@509 272 </p>
jbe@509 273 <pre>
jbe@509 274 -- filename: model/customer_receipt.lua
jbe@509 275 CustomerReceipt = mondelefant.new_class()
jbe@509 276 CustomerReceipt.table = "custreceipt"</pre>
jbe@509 277 <p>
jbe@509 278 Methods such as <a href="#db_class:add_reference"><tt>:add_reference(...)</tt></a> can be used to further modify or extend the class.
jbe/bsw@0 279 </p>
jbe/bsw@0 280 <h3>Views</h3>
jbe/bsw@0 281 <p>
jbe@513 282 The views in the MVA concept are different from the views in the MVC concept. As WebMCP has no controllers, the views are responsible for processing the GET/POST parameters from the webbrowser, fetching the data to be displayed, and creating the output by directly writing HTML to slots of a layout (see <a href="#slot.select"><tt>slot.select(...)</tt></a>, <a href="#slot.put"><tt>slot.put(...)</tt></a>, and <a href="#slot.put_into"><tt>slot.put_into(...)</tt></a> or by calling helper functions for the user interface (those functions beginning with "<tt>ui.</tt>"). Views are stored in files with the file path "<tt>app/</tt><i>application_name</i><tt>/</tt><i>module_name</i><tt>/</tt><i>view_name</i><tt>.lua</tt>". When their corresponding URL, e.g. "<tt>http://</tt><i>hostname</i><tt>:</tt><i>port</i><tt>/</tt><i>module_name</i><tt>/</tt><i>view_name</i><tt>.html</tt>", is requested, the code in that file gets executed (after calling appropriate filters). After the execution of the view has finished (and after all filters have finished their execution too), the slot data will be inserted into placeholder sections in the selected layout file. The layout file defaults to "<tt>app/</tt><i>application_name</i><tt>/_layout/default.html</tt>" but may be changed using the <a href="#slot.set_layout"><tt>slot.set_layout(...)</tt></a> function.
jbe/bsw@0 283 </p>
jbe/bsw@0 284 <h3>Actions</h3>
jbe/bsw@0 285 <p>
jbe@509 286 Actions are similar to views, but supposed to change data in the database, hence only callable by HTTP POST requests. They are also responsible for processing the POST parameters from the webbrowser. They can modify the database, but instead of rendering a page to be displayed, they just return a status code string (via Lua's <tt>return</tt> statement, where <tt>true</tt> can also be used instead of "<tt>ok</tt>", and <tt>false</tt> instead of "<tt>error</tt>"). Depending on the status string there will be an internal forward or an HTTP 303 redirect to a view. When calling an action via a POST request, additional POST parameters, which are usually added by hidden form fields, determine the view to be displayed for each status string returned by the action. See the <tt>routing</tt> parameter to the <a href="#ui.form"><tt>ui.form{...}</tt></a> function for further details.
jbe/bsw@0 287 </p>
jbe@510 288 <h2>Layouts</h2>
jbe@510 289 <p>
jbe@510 290 Templates for HTML documents to be returned by views are stored at the path "<tt>app/</tt><i>application_name</i><tt>/_layout/</tt><i>layout_name</i><tt>.html</tt>", relative to the application base path. The default layout name is "<tt>default</tt>". For system errors, the layout name "<tt>system_error</tt>" is used. A sample layout is given as follows:
jbe@510 291 </p>
jbe@510 292 <pre>
jbe@510 293 &lt;!DOCTYPE HTML&gt;
jbe@510 294 &lt;html&gt;
jbe@510 295 &lt;head&gt;
jbe@510 296 &lt;title&gt;&lt!-- WEBMCP SLOTNODIV title --&gt;&lt;/title&gt;
jbe@510 297 &lt;link rel="stylesheet" type="text/css" media="screen" href="__BASEURL__/static/style.css"/&gt;
jbe@510 298 &lt;/head&gt;
jbe@510 299 &lt;body&gt;
jbe@510 300 &lt;!-- WEBMCP SLOT content --&gt;
jbe@510 301 &lt;/body&gt;
jbe@510 302 &lt;/html&gt;</pre>
jbe@510 303 <p>
jbe@510 304 The following elements in a layout file get replaced automatically:
jbe@510 305 </p>
jbe@510 306 <ul>
jbe@510 307 <li><tt>__BASEURL__</tt> gets replaced with the application's base web address.</li>
jbe@510 308 <li><tt>&lt;!-- WEBMCP SLOT </tt><i>slot_name</i><tt> --&gt;</tt> gets, if the slot is not empty, replaced with a <tt>&lt;div&gt;</tt> element (with the <tt>id</tt> attribute set to "<tt>slot_</tt><i>slotname</i>") that contains the slot's content.</li>
jbe@510 309 <li><tt>&lt;!-- WEBMCP SLOTNODIV </tt><i>slot_name</i><tt> --&gt;</tt> gets replaced with the slot's content (without wrapping it in an additional <tt>&lt;div&gt;</tt> element).</li>
jbe@510 310 </ul>
jbe@511 311 <h2>Internationalization/Localization</h2>
jbe@511 312 <p>
jbe@511 313 To translate certain strings in your application, simply use the <a href="#_">underscore function</a>. A language can be selected with <tt><a href="#locale.set">locale.set</a>{lang = "code"}</tt> where <tt>code</tt> is a language code. The translations for strings are expected to be contained in files "<tt>locale/translations.</tt><i>language_code</i><tt>.lua</tt>". These files should return a table that maps strings to their corresponding translation:
jbe@511 314 </p>
jbe@511 315 <pre>
jbe@511 316 return{
jbe@511 317 ["Are you sure?"] = "Bist Du sicher?";
jbe@511 318 ["User '#{name}' created"] = "Benutzer '#{name}' created";
jbe@511 319 }</pre>
jbe@511 320 <p>
jbe@511 321 Such translation files can be automatically created with the <tt>langtool.lua</tt> program, found in the framework's <tt>bin/</tt> directory.
jbe@511 322 </p>
jbe@518 323 <h2>Global variables and the environment</h2>
jbe@518 324 <p>
jbe@518 325 To avoid accidental programming errors, WebMCP forbids setting of global variables by default. This is overridden by using the prefix "<tt>_G.</tt>" (<a href="#_G">see reference</a>) when setting the variable, e.g. <tt>_G.myvar = 7</tt>, or by setting the variable in a file with the same name of the global varaible (but suffixed with "<tt>.lua</tt>") in the <tt>env/</tt> directory of the framework or application. Note, however, that the lifetime of global variables is not predictable as it depends on process recycling of the Moonbridge webserver (one fork will handle more than one request) and because there may be multiple forks of the Lua machine which all have their own global variable space (there is usually more than one fork).
jbe@518 326 </p>
jbe@518 327 <p>
jbe@519 328 If an application needs to store request related data, the global table <a href="#app"><tt>app</tt></a> should be used (e.g. <tt>app.myvar = true</tt> instead of <tt>_G.myvar = true</tt>). The <tt>app</tt> table gets automatically initialized (i.e. emptied) for each request.
jbe@519 329 </p>
jbe@519 330 <p>
jbe@518 331 Global variables are still useful when providing access to libraries, for example. WebMCP automatically loads certain libraries and functions though an autoloader mechanism. On read-accessing any unknown variable, WebMCP will search the framework's and application's <tt>env/</tt> directories for an appropriate file (e.g. "<tt>my_func.lua</tt> if you invoke "<tt>my_func()</tt>") or a matching directory (e.g. "<tt>my_module/</tt> if you access "<tt>my_module.my_func()</tt>). In case of an existing directory in <tt>env/</tt>, an empty table with autoloading capabilities is automatically created as global variable with the name of the directory. The autoloading mechanism allows directories to contain further files which can be used to initialize variables within that table when accessed. Directories can also contain a special file called "<tt>__init.lua</tt>" that always gets executed when the table is accessed for the first time. The <tt>env/</tt> root directory can also contain a file ("<tt>env/__init__.lua</tt>") which gets executed before any configuration is loaded.
jbe@518 332 </p>
jbe@518 333 <p>
jbe@519 334 A good place to store utility functions is a global table called <tt>util</tt>. This table will be automatically accessible if you create a <tt>env/util/</tt> directory in your WebMCP application. To provide a function <tt>util.myfunc(...)</tt> simply create a file <tt>env/util/myfunc.lua</tt>, with the following function definition:
jbe@518 335 </p>
jbe@519 336 <pre>
jbe@519 337 -- filename: env/util/myfunc.lua
jbe@519 338 function util.myfunc()
jbe@519 339 slot.put_into("hello", "Hello World!")
jbe@519 340 end</pre>
jbe/bsw@0 341 <h2>Directory structure of a WebMCP application</h2>
jbe@513 342 <p>
jbe@513 343 Summarizing information from the previous section, we get the following directory structure for a WebMCP application:
jbe@513 344 </p>
jbe/bsw@0 345 <ul>
jbe/bsw@0 346 <li>
jbe/bsw@0 347 Base Directory
jbe/bsw@0 348 <ul>
jbe/bsw@0 349 <li>
jbe/bsw@0 350 <tt>app/</tt>
jbe/bsw@0 351 <ul>
jbe@510 352 <li><tt>_prefork/</tt></li>
jbe@510 353 <li><tt>_postfork/</tt></li>
jbe/bsw@0 354 <li>
jbe@510 355 <tt>main/</tt> (typically "main" is the only application)
jbe@278 356 <ul>
jbe@510 357 <li><tt>_prefork/</tt></li>
jbe@510 358 <li><tt>_postfork/</tt></li>
jbe@510 359 <li><tt>_filter/</tt></li>
jbe@510 360 <li><tt>_filter_action/</tt></li>
jbe@510 361 <li><tt>_filter_view/</tt></li>
jbe@510 362 <li><tt>_layout/</tt></li>
jbe@278 363 <li>
jbe@510 364 <tt>index/</tt> (module "index" is the default module)
jbe/bsw@0 365 <ul>
jbe/bsw@0 366 <li>
jbe/bsw@0 367 <tt>_action/</tt>
jbe/bsw@0 368 <ul>
jbe@510 369 <li><i>action_name</i><tt>.lua</tt></li>
jbe@510 370 <li><i>another_action_name</i><tt>.lua</tt></li>
jbe/bsw@0 371 <li>&hellip;</li>
jbe/bsw@0 372 </ul>
jbe/bsw@0 373 </li>
jbe@510 374 <li><tt>index.lua</tt> (view "index" of module "index" is the default view)</li>
jbe@510 375 <li><i>other_view_name</i><tt>.lua</tt></li>
jbe/bsw@0 376 <li>&hellip;</li>
jbe/bsw@0 377 </ul>
jbe/bsw@0 378 </li>
jbe/bsw@0 379 <li>
jbe/bsw@0 380 <i>other_module_name</i><tt>/</tt>
jbe@510 381 <ul><li>&hellip;</li></ul>
jbe/bsw@0 382 </li>
jbe/bsw@0 383 </ul>
jbe/bsw@0 384 </li>
jbe/bsw@0 385 <li>
jbe/bsw@0 386 <i>other_application_name</i><tt>/</tt>
jbe/bsw@0 387 <ul>
jbe/bsw@0 388 <li>&hellip;</li>
jbe/bsw@0 389 </ul>
jbe/bsw@0 390 </li>
jbe/bsw@0 391 </ul>
jbe/bsw@0 392 </li>
jbe/bsw@0 393 <li>
jbe/bsw@0 394 <tt>config/</tt>
jbe/bsw@0 395 <ul>
jbe@510 396 <li><tt>development.lua</tt> (e.g. to be used for development purposes)</li>
jbe@510 397 <li><tt>production.lua</tt> (e.g. to be used for production)</li>
jbe@510 398 <li><i>other_config_name</i><tt>.lua</tt></li>
jbe/bsw@0 399 <li>&hellip;</li>
jbe/bsw@0 400 </ul>
jbe/bsw@0 401 </li>
jbe/bsw@0 402 <li>
jbe/bsw@0 403 <tt>db/</tt>
jbe/bsw@0 404 <ul>
jbe@510 405 <li><tt>schema.sql</tt> (not used by WebMCP, but may be used to initialize a database)</li>
jbe/bsw@0 406 </ul>
jbe/bsw@0 407 </li>
jbe/bsw@0 408 <li>
jbe@518 409 <tt>env/</tt>
jbe@518 410 <ul>
jbe@518 411 <li><tt>__init.lua</tt></li>
jbe@519 412 <li><i>some_global_variable_name</i><tt>.lua</tt></li>
jbe@518 413 <li>
jbe@519 414 <i>another_global_variable_name</i><tt>/</tt>
jbe@518 415 <ul>
jbe@518 416 <li><tt>__init.lua</tt></li>
jbe@518 417 <li><i>attribute_name</i><tt>.lua</tt></li>
jbe@518 418 <li>
jbe@518 419 <i>another_attibute_name</i><tt>/</tt>
jbe@518 420 <ul><li>&hellip;</li></ul>
jbe@518 421 </li>
jbe@518 422 </ul>
jbe@518 423 </li>
jbe@518 424 </ul>
jbe@518 425 <li>
jbe@510 426 <tt>locale/</tt> (translation files used by the <a href="#_">underscore function</a>")
jbe/bsw@0 427 <ul>
jbe/bsw@0 428 <li>
jbe/bsw@0 429 <tt>translations.de.lua</tt>
jbe/bsw@0 430 </li>
jbe/bsw@0 431 <li>
jbe/bsw@0 432 <tt>translations.en.lua</tt>
jbe/bsw@0 433 </li>
jbe/bsw@0 434 <li>
jbe/bsw@0 435 <tt>translations.</tt><i>languagecode</i><tt>.lua</tt>
jbe/bsw@0 436 </li>
jbe/bsw@0 437 <li>&hellip;</li>
jbe/bsw@0 438 </ul>
jbe/bsw@0 439 </li>
jbe/bsw@0 440 <li>
jbe/bsw@0 441 <tt>model/</tt>
jbe/bsw@0 442 <ul>
jbe/bsw@0 443 <li>
jbe@510 444 <i>model_name</i><tt>.lua</tt> (code must create a model class in camel case, e.g. "<tt>ModelName</tt>" if the file name is "<tt>model_name.lua</tt>")
jbe/bsw@0 445 </li>
jbe/bsw@0 446 <li>
jbe/bsw@0 447 <i>another_model_name</i><tt>.lua</tt>
jbe/bsw@0 448 </li>
jbe/bsw@0 449 <li>&hellip;</li>
jbe/bsw@0 450 </ul>
jbe/bsw@0 451 </li>
jbe/bsw@0 452 <li>
jbe/bsw@0 453 <tt>static/</tt>
jbe/bsw@0 454 <ul>
jbe/bsw@0 455 <li>&hellip; (images, javascript, ...)</li>
jbe/bsw@0 456 </ul>
jbe/bsw@0 457 </li>
jbe/bsw@0 458 <li>
jbe@510 459 <tt>tmp/</tt> (needs to be writable by the user executing WebMCP)
jbe/bsw@0 460 </li>
jbe/bsw@0 461 </ul>
jbe/bsw@0 462 </li>
jbe/bsw@0 463 </ul>
jbe@278 464 <h2>Starting your application</h2>
jbe@278 465 <p>
jbe@513 466 Ensure that the <tt>moonbridge</tt> binary is within your system's search path and that the <tt>moonbridge_http.lua</tt> file is included in the LUA_PATH or linked into the framework's <tt>lib/</tt> directory (alternatively the MOONBR_LUA_PATH option might be set accordingly at compile-time of the Moonbridge Network Server). To start an application, call the <tt>mcp.lua</tt> executable (found in <tt>framework/bin/mcp.lua</tt>) with the following four arguments:
jbe@513 467 </p>
jbe@513 468 <ol>
jbe@513 469 <li>Path of the WebMCP framework directory, e.g. <tt>./framework</tt></li>
jbe@513 470 <li>Path of your application's directory, e.g. <tt>./demo-app</tt></li>
jbe@522 471 <li>Name of your application (usually <tt>main</tt>)</li>
jbe@513 472 <li>Name of configuration (e.g. <tt>devel</tt> to use config/devel.lua)</li>
jbe@513 473 </ol>
jbe@513 474 <p>
jbe@513 475 Alternatively, the <tt>moonbridge</tt> binary may be called directly with the following five arguments:
jbe@278 476 </p>
jbe@278 477 <ol>
jbe@513 478 <li>Path to <tt>mcp.lua</tt>, e.g. <tt>./framework/bin/mcp.lua</tt></li>
jbe@513 479 <li>Path of the WebMCP framework directory, e.g. <tt>./framework</tt></li>
jbe@513 480 <li>Path of your application's directory, e.g. <tt>./demo-app</tt></li>
jbe@522 481 <li>Name of your application (usually <tt>main</tt>)</li>
jbe@513 482 <li>Name of configuration (e.g. <tt>devel</tt> to use config/devel.lua)</li>
jbe@278 483 </ol>
jbe@513 484 <p>
jbe@513 485 Note that the demo application will require a database to be set up prior to starting. Execute the following shell commands first:
jbe@513 486 </p>
jbe@513 487 <pre>
jbe@513 488 createdb webmcp_demo
jbe@513 489 psql -v ON_ERROR_STOP=1 -f demo-app/db/schema.sql webmcp_demo</pre>
jbe/bsw@0 490 <h2>Automatically generated reference for the WebMCP environment</h2>
jbe/bsw@0 491 <ul>

Impressum / About Us