This chapter summarizes some important concepts in Moya, which will be covered more fully in later chapters.
The moya command is a swiss-army knife of tools for development; in addition to running the development server, it can also report settings, check databases, test email, trace URLs, and assist with the minutia of developing a web application.
If Moya is installed, you can run the following command to see the help text:
$ moya -h
In Moya, executable code is written in XML. The Moya language supports many of the constructs found in other high-level languages and although more verbose in terms of characters to type, it can be very readable and easy to work with.
The Moya languages is also extremely extensible. New tags can be implemented in Moya code itself, or via extensions written in Python.
The following Moya code is an implementation of Fizz Buzz in Moya code:
<macro docname="main"><for src="1..100" dst="number"><if test="number % 15 == 0"><echo>FizzBuzz</echo></if><elif test="number % 3 == 0"><echo>Fizz</echo></elif><elif test="number % 5 == 0"><echo>Buzz</echo></elif><else><echo>${number}</echo></else></for></macro>
Or for an alternative, less readable version:
<macro docname="fizzbuzz2"><for src="1..100" dst="number"><echo>${number % 15 == 0 ? 'FizzBuzz' : (number % 3 == 0 ? 'Fizz' : (number % 5 == 0 ? 'Buzz' : number))}</echo></for></macro>
Moya Code may contain expressions which work like most other languages, but with additional syntax for web related tasks, such as url manipulation / encoding, path manipulation, date-time arithmetic etc.
For example, the expression in the following code gets the current price of Bitcoin from an online service:
<echo>${(fromjson:get:"https://www.bitstamp.net/api/ticker/")['ask']}</echo>
A fully featured debugger is built in to Moya. With the Moya debugger you can step through your code, inspect data, and set breakpoints. Code is displayed with beautiful syntax highlighting (if your console supports it).
All web application functionality in Moya is contained in bundle of XML documents, known as a library. Libraries typically contain views which process URLs and generate a response, and may also add features that can be used elsewhere in the project.
Moya is bundled with a number of libraries to handle typical web applications requirements. For example there is a libary to manage users, sessions, forms, comments, remote procedure calls, and many more.
Libraries self contained; the developer will rarely have to do more than mount the library (give it a root URL). Static files may be served directly from the library, without having to copy anything.
There are a number of systems involved in generating a page of html in a modern web application. The following is a list of the major components of a project built with Moya.
A library may define one or more mountpoints, which take an incoming URL and dispatch it to a view which will generate a response. A special syntax called a route is used to match URLs to views and extract parameters.
Here's a simple URL route:
/topic/{topic}/{link}/
This will match a URL of the form /topic/farscape/my-favorite-character/
, and extract a value for topic
(farscape) and link
(my-favorite-character).
In Moya a view is the executable code responsible for generating a response for a given URL. A view will typically retrieve some information from the database, which it then renders in to HTML with via a template, or Moya's content system.
The following is an example of a view taken from the builtin blog library:
<view libname="view.posts-by-month" content="#content.list-posts-by-month"><not-found if="exists:.request.GET.page and not int:.request.GET.page" /><let page="int:.request.GET.page or 1" pagesize=".app.settings.page_size.int"/><datetime dst="start" year="${url.year}" month="${url.month}"/><catch exception="date-time.*"><not-found /></catch><db:query model="#Post" dst="posts" orderby="-published_date"filter="#Post.published_date gte start and #Post.published_date lt start.next_month"/></view>
Moya simplifies databases with models and database expressions. Models map database tables on to simple objects and types. Database expressions build queries without the need for SQL.
Here's an example of a model definition:
<model xmlns="http://moyaproject.com/db" name="Post" libname="Post" repr="Post: ${slug}"><foreign-key model="auth#User" name="owner" null="yes" /><string name="title" length="100" null="no" /><string name="slug" length="100" null="no" unique="yes" /><boolean name="published" default="no" /><date-time name="published_date" null="yes" /><text name="content" null="no" default="" /></model>
Here's an example of a query for the above model:
<db:query dst="newer_posts" model="#Post" orderby="published_date"filter="#Post.published_date gt post.published_date" />
The filter
attribute in the code above is an example of a database expression.
Moya templates are text files with a simple – but powerful – markup that transforms data in to HTML (typically). The syntax used in Moya templates borrows heavily from Django and Jinja, but with some differences to compliment Moya Code.
The following is an example of Moya template code:
<!-- List of crew onboard Moya --><ul>{% for species, crew in moya %}<li>${title:crew} is a ${species}</li>{% endfor %}</ul>
The Moya template language supports many tags, with a clean, consistent syntax and the same expressions used elsewhere in Moya.
Templates are powerful tools for building html, but are not particularly good at managing the layout of pages which are typically built from many smaller components. Moya's answer to this issue is content – a high level description of a page defined in Moya code.
Content assembles a page from components, or widgets. A widget can pull in associated CSS, Javascript, and templates, so that all that is required to add a widget to a page is a single tag.
Here's an example of a content definition, taken from Moya's FAQ (Frequently Asked Questions) library:
<content libname="content.faqlist" template="faqs.html"><title>Frequently Asked Questions</title><section name="body"><for src="faqs" dst="qa"><faq:faq qa="qa" /></for></section></content>
In a globalized world, it is often necessary to support a single website in more than one territory. Moya can display translated text from messages catalogs extracted with the command line app. Localization (currency / data formats formats etc) is also supported.
Forms are a fundamental part of most web applications, and a common source of errors and frustration. Moya forms makes working with forms no harder than it needs to be. Forms created with Moya's form system know how to render themselves as well as validated and process data in a request.
Forms are integrated tightly with the content system and may be rendered in a variety of styles, or customized at the field or form level.
Moya can selectively expose parts of the local filesystem (or other filesystem) to logic code. Code in the project is unable to access any files outside of what the developer has chosen to expose. This is a boon for security, as it is impossible to serve files outside of specified locations.
Moya supports a number of different caching methods; such as local memory, disk based, and memcached servers. These may be mixed and matched as appropriate to optimize expensive code.
Moya makes sending template emails very simple. HTML and / or text emails are rendered with Moya templates, and may contain attachments.
Unit Tests are essential if you want to guarantee a level of quality in your product. Moya can run test suites (written in Moya code) that produce elegant reports to the console or as HTML. Tests ensuring that recent changes to your code don't break the user experience on other pages.
In addition to unit tests, Moya can run preflight checks, which detect common errors and potential problems before the server runs. These can prevent potentially embarrassing issues from being pushed live.