<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Ari Lerner</title>
  <link href="http://willcodeforfoo.com/atom.xml" rel="self"/>
  <link href="http://willcodeforfoo.com/"/>
  <updated>2010-05-31T22:48:52-07:00</updated>
  <id>http://willcodeforfoo.com/</id>
  <author>
    <name>Ari Lerner</name>
    <email>hello@willcodeforfoo.com</email>
  </author>
  
    <entry>
      <title>Neotoma - Super powerful parsing for erlang</title>
      <link href="http://willcodeforfoo.com/2010/04/21/neotoma"/>
      <updated>2010-04-21T00:00:00-07:00</updated>
      <id>http://willcodeforfoo.com/2010/04/21/neotoma</id>
      <content type="html">&lt;h3 id='erlang_strings_are_painful'&gt;Erlang strings are painful&lt;/h3&gt;

&lt;p&gt;Oh it&amp;#8217;s so true. The pain is super apparent, especially when trying to parse configuration files. The traditional way to parse a configuration file that is not in the erlang format can be pretty hard to do. For instance, for &lt;a href='http://github.com/auser/beehive'&gt;beehive&lt;/a&gt;, the application configuration template looks like:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='c1'&gt;# Config file&lt;/span&gt;
&lt;span class='c1'&gt;# For example, a rack app&lt;/span&gt;
&lt;span class='l-Scalar-Plain'&gt;bundle&lt;/span&gt;&lt;span class='p-Indicator'&gt;:&lt;/span&gt; &lt;span class='l-Scalar-Plain'&gt;echo &amp;quot;Bundle java stuff&amp;quot;&lt;/span&gt;
&lt;span class='l-Scalar-Plain'&gt;start&lt;/span&gt;&lt;span class='p-Indicator'&gt;:&lt;/span&gt; &lt;span class='l-Scalar-Plain'&gt;/bin/rackstart.sh&lt;/span&gt;
&lt;span class='c1'&gt;# etc. etc.&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Originally, this was parsed in lex/yacc and consumed in c++ (shudder). The code for that is available buried deep within the history of &lt;a href='http://github.com/auser/babysitter'&gt;babysitter&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A traditional parser would look something like this:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;  &lt;span class='o'&gt;-&lt;/span&gt;&lt;span class='n'&gt;module&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;config_parser&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;
  &lt;span class='o'&gt;-&lt;/span&gt;&lt;span class='n'&gt;export&lt;/span&gt; &lt;span class='p'&gt;([&lt;/span&gt;&lt;span class='n'&gt;file&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;]).&lt;/span&gt;

  &lt;span class='o'&gt;-&lt;/span&gt;&lt;span class='n'&gt;define&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;SEPARATOR&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='sc'&gt;$:&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;

  &lt;span class='n'&gt;file&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Filename&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;ok&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Fd&lt;/span&gt;&lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;file&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;open&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Filename&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;read&lt;/span&gt;&lt;span class='p'&gt;]),&lt;/span&gt;
    &lt;span class='nn'&gt;io&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;setopts&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Fd&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;binary&lt;/span&gt;&lt;span class='p'&gt;]),&lt;/span&gt;
    &lt;span class='n'&gt;for_each_line&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Fd&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='k'&gt;fun&lt;/span&gt; &lt;span class='n'&gt;parse&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;3&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;[]).&lt;/span&gt;

  &lt;span class='n'&gt;for_each_line&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Device&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Proc&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Count&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Accum&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nn'&gt;io&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;get_line&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Device&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='k'&gt;of&lt;/span&gt;
      &lt;span class='n'&gt;eof&lt;/span&gt;  &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nn'&gt;file&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;close&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Device&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt; &lt;span class='nv'&gt;Accum&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
      &lt;span class='nv'&gt;Line&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
        &lt;span class='nv'&gt;NewAccum&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nv'&gt;Proc&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Line&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Count&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Accum&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt; 
        &lt;span class='n'&gt;for_each_line&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Device&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Proc&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Count&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;NewAccum&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;

  &lt;span class='n'&gt;parse&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Line&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Count&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Acc&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;peg_parse&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Line&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Count&lt;/span&gt;&lt;span class='p'&gt;)|&lt;/span&gt;&lt;span class='nv'&gt;Acc&lt;/span&gt;&lt;span class='p'&gt;].&lt;/span&gt;

  &lt;span class='c'&gt;% START PEG PARSING&lt;/span&gt;
  &lt;span class='n'&gt;peg_parse&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Line&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Count&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='nv'&gt;Field&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;X&lt;/span&gt;&lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;parse_line&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Line&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;[],&lt;/span&gt; &lt;span class='p'&gt;[]),&lt;/span&gt;
    &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nv'&gt;Field&lt;/span&gt; &lt;span class='k'&gt;of&lt;/span&gt;
      &lt;span class='n'&gt;comment&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;ok&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
      &lt;span class='nv'&gt;X&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nn'&gt;io&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;format&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;[&lt;/span&gt;&lt;span class='si'&gt;~p&lt;/span&gt;&lt;span class='s'&gt;] &lt;/span&gt;&lt;span class='si'&gt;~p&lt;/span&gt;&lt;span class='s'&gt;:&lt;/span&gt;&lt;span class='si'&gt;~p~n&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;Count&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Field&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;X&lt;/span&gt;&lt;span class='p'&gt;])&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;

  &lt;span class='c'&gt;% Top&lt;/span&gt;
  &lt;span class='c'&gt;% Strip comments&lt;/span&gt;
  &lt;span class='n'&gt;parse_line&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class='sc'&gt;$#&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;_&lt;/span&gt;&lt;span class='nv'&gt;Rest&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='n'&gt;binary&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;[],&lt;/span&gt; &lt;span class='p'&gt;_&lt;/span&gt;&lt;span class='nv'&gt;Acc&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;comment&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;[]};&lt;/span&gt;
  &lt;span class='c'&gt;% Is this the field?&lt;/span&gt;
  &lt;span class='n'&gt;parse_line&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class='no'&gt;?SEPARATOR&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Rest&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='n'&gt;binary&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;_&lt;/span&gt;&lt;span class='nv'&gt;Field&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Acc&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;parse_line&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Rest&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nn'&gt;lists&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;reverse&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Acc&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt; &lt;span class='p'&gt;[]);&lt;/span&gt;
  &lt;span class='n'&gt;parse_line&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class='nv'&gt;Char&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Rest&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='n'&gt;binary&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Field&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Acc&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;parse_line&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Rest&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Field&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;Char&lt;/span&gt;&lt;span class='p'&gt;|&lt;/span&gt;&lt;span class='nv'&gt;Acc&lt;/span&gt;&lt;span class='p'&gt;]);&lt;/span&gt;
  &lt;span class='n'&gt;parse_line&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;&amp;lt;&amp;lt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Field&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Acc&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='nv'&gt;Field&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nn'&gt;lists&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;reverse&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Acc&lt;/span&gt;&lt;span class='p'&gt;)};&lt;/span&gt;
  &lt;span class='n'&gt;parse_line&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class='sc'&gt;$\n&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Field&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Acc&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='nv'&gt;Field&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nn'&gt;lists&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;reverse&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Acc&lt;/span&gt;&lt;span class='p'&gt;)}.&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I&amp;#8217;ll only touch on the basics of what that is here (so if you want to skip it, just go to the next section).&lt;/p&gt;

&lt;p&gt;Basically we open a file descriptor to the file and tell it to read in the binary format (a little faster and less work on the vm). For every line, we go through character by character and examine based on the position and context that the character is in and store the value in the context where it appears. Later we&amp;#8217;ll come back (notice where the io:format is?) and store it in some meaningful way. This is just a demo. If there is enough interest, I can finish it and post it here. Otherwise, I won&amp;#8217;t spend more time on it as there is a better way.&lt;/p&gt;

&lt;h3 id='introducing_neotoma'&gt;Introducing Neotoma&lt;/h3&gt;

&lt;p&gt;&lt;a href='http://github.com/seancribbs/neotoma'&gt;Neotoma&lt;/a&gt;, a project by Sean Cribbs that makes &lt;a href='http://en.wikipedia.org/wiki/Parsing_expression_grammar'&gt;PEG&lt;/a&gt; parsing in erlang easy. It&amp;#8217;s a nifty tool that generates an unambiguous parser that generates a parse tree. Don&amp;#8217;t try to use this to create a parser to examine natural languages though, it&amp;#8217;s not an CFG (context free grammar) parser.&lt;/p&gt;

&lt;p&gt;There aren&amp;#8217;t too many resources available yet through &lt;a href='http://google.com'&gt;google.com&lt;/a&gt;, so after some head scratching and pm&amp;#8217;ing with Sean Cribbs, the author, I was able to sketch the parser to dig out the parse tree for the grammar in a ridiculously little amount of code.&lt;/p&gt;

&lt;p&gt;Before we get into the PEG grammar, there are a few basic pieces of terminology that you need to know.&lt;/p&gt;

&lt;h3 id='terminal_symbols'&gt;Terminal symbols&lt;/h3&gt;

&lt;p&gt;There are two disjoint sets of items called &lt;strong&gt;terminal symbols&lt;/strong&gt;. These are basic pieces (or atoms) of a grammar. There are two types of terminals, the non-terminal and the terminal symbol. They must be, by necessity disjoint sets of symbols for a valid grammar. The reason will become apparent shortly.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;non-terminal symbol&lt;/strong&gt; - Symbol representing a &amp;#8216;variable&amp;#8217; in a grammar. These are symbols that can be replaced by other elements of the grammar.&lt;/li&gt;

&lt;li&gt;&lt;strong&gt;terminal symbol&lt;/strong&gt; - Symbols that cannot be broken down any further, but that can be consumed by non-terminals.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let&amp;#8217;s look at an example. These are two non-terminals that describe a signed integer in the &lt;a href='http://en.wikipedia.org/wiki/Backus–Naur_Form'&gt;BNF&lt;/a&gt; form of a grammar: &lt;div class='highlight'&gt;&lt;pre&gt;  &amp;lt;integer&amp;gt; ::&lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;-&amp;#39;&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &amp;lt;digit&amp;gt; &lt;span class='o'&gt;{&lt;/span&gt;&amp;lt;digit&amp;gt;&lt;span class='o'&gt;}&lt;/span&gt;
  &amp;lt;digit&amp;gt; ::&lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;0&amp;#39;&lt;/span&gt; | &lt;span class='s1'&gt;&amp;#39;1&amp;#39;&lt;/span&gt; | &lt;span class='s1'&gt;&amp;#39;2&amp;#39;&lt;/span&gt; | &lt;span class='s1'&gt;&amp;#39;3&amp;#39;&lt;/span&gt; | &lt;span class='s1'&gt;&amp;#39;4&amp;#39;&lt;/span&gt; | &lt;span class='s1'&gt;&amp;#39;5&amp;#39;&lt;/span&gt; | &lt;span class='s1'&gt;&amp;#39;6&amp;#39;&lt;/span&gt; | &lt;span class='s1'&gt;&amp;#39;7&amp;#39;&lt;/span&gt; | &lt;span class='s1'&gt;&amp;#39;8&amp;#39;&lt;/span&gt; | &lt;span class='s1'&gt;&amp;#39;9&amp;#39;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;The integer and the digit are the non-terminals, while the 0-9 and - are the terminal symbols.&lt;/p&gt;

&lt;h2 id='peg_grammars'&gt;PEG grammars&lt;/h2&gt;

&lt;p&gt;A &amp;#8220;parsing expression grammar&amp;#8221;, or PEG is an formal description of an analytic language model that describes a set of rules for recognizing strings and their context in the language. For instance, in the English language a proper declarative sentence requires a subject and a predicate&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;  My name is Mary.
    &amp;lt;subject&amp;gt; = My name
    &amp;lt;predicate&amp;gt; = is Mary
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Although you should never use a PEG to parse natural language (use a &lt;a href='http://en.wikipedia.org/wiki/Backus-Naur_form'&gt;Backus-Naur Form&lt;/a&gt;), the corresponding PEG would look something like (incomplete, but only used for example):&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;  &lt;span class='c'&gt;% Psst, a Neotoma PEG for the sentence &amp;quot;My name is Mary&amp;quot;&lt;/span&gt;
  &lt;span class='n'&gt;declarative_sentence&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='n'&gt;predicate&lt;/span&gt; &lt;span class='n'&gt;noun&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;.&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
  &lt;span class='n'&gt;predicate&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;My name&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
  &lt;span class='n'&gt;noun&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;is Mary&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This is a VERY basic PEG parser. What does all this mean? Well&amp;#8230;&lt;/p&gt;

&lt;h2 id='introducing_neotoma'&gt;Introducing Neotoma&lt;/h2&gt;

&lt;p&gt;Let&amp;#8217;s look at the simplest possible grammar for describing the exact same thing, a signed integer.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;  &lt;span class='n'&gt;rule&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='nv'&gt;Decimal&lt;/span&gt; &lt;span class='err'&gt;~&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
  &lt;span class='nv'&gt;Decimal&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='o'&gt;-&lt;/span&gt;&lt;span class='mi'&gt;9&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;&lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='err'&gt;`&lt;/span&gt;&lt;span class='nb'&gt;list_to_integer&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Node&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='err'&gt;`&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;That&amp;#8217;s it? Yep. This might look a little confusing, but don&amp;#8217;t worry, I&amp;#8217;ll explain what&amp;#8217;s happening here. First, look at the `Decimal` rule. That says that any digit 0 through 9 will be consumed by this rule. The stuff in the &amp;#8220; will be what happens to the matched number. We&amp;#8217;ll get back to that soon. The `rule` non-terminal will &amp;#8216;take&amp;#8217; the Decimal rule in. This won&amp;#8217;t do anything interesting yet, other than say that the rule will contain an integer. Let&amp;#8217;s change that:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;  &lt;span class='n'&gt;additive&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='n'&gt;multitative&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;+&amp;quot;&lt;/span&gt; &lt;span class='n'&gt;additive&lt;/span&gt; &lt;span class='o'&gt;/&lt;/span&gt; &lt;span class='n'&gt;multitative&lt;/span&gt; &lt;span class='err'&gt;~&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
  &lt;span class='n'&gt;multitative&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='n'&gt;primary&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;*&amp;quot;&lt;/span&gt; &lt;span class='n'&gt;multitative&lt;/span&gt; &lt;span class='o'&gt;/&lt;/span&gt; &lt;span class='n'&gt;primary&lt;/span&gt; &lt;span class='err'&gt;~&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
  &lt;span class='n'&gt;primary&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;(&amp;quot;&lt;/span&gt; &lt;span class='n'&gt;additive&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;)&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;/&lt;/span&gt; &lt;span class='n'&gt;decimal&lt;/span&gt; &lt;span class='err'&gt;~&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
  &lt;span class='n'&gt;decimal&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='o'&gt;-&lt;/span&gt;&lt;span class='mi'&gt;9&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;&lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='err'&gt;`&lt;/span&gt;&lt;span class='nb'&gt;list_to_integer&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Node&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='err'&gt;`&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This shouldn&amp;#8217;t be too hard to understand from the rule above, but there are two new things in these rules. First, the stuff that happens in between the &amp;#8220; is the semantic part of the parse tree. Sean calls this the &amp;#8216;transformation&amp;#8217; of the grammar. What it does is stuff all the matches of the rules into a variable called `Node`. From there, you can do basically what you want with what the transformation returns (so long as the rules that use it understand it). If instead of putting stuff in &amp;#8220; at the end of a rule definition, you put a `~`, this says return the Node variable untouched.&lt;/p&gt;

&lt;p&gt;The second new introduction in this set of rules is the `/`. This an `or` statement. It&amp;#8217;s a precedence-based &amp;#8216;or&amp;#8217;. So, for our rules above, the primary terminal can either be an additive surrounded by parenthesis OR a decimal. Note, I said that precedence is denoted here. The first item in the list is the first item matched. It&amp;#8217;s always a good idea (even the author Sean Cribbs suggests) to try to match the longest rule possible. &lt;strong&gt;Precedence is important.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Alright, so remember the very incomplete code example from above that didn&amp;#8217;t do anything yet, that looks ugly and is exactly 37 lines long? Well, here is a very complete &lt;em&gt;Neotoma&lt;/em&gt; version that can parse the entire file:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;  &lt;span class='c'&gt;% This is the PEG compiler for babysitter configuration files&lt;/span&gt;
  &lt;span class='n'&gt;config_element&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='n'&gt;ws&lt;/span&gt;&lt;span class='err'&gt;?&lt;/span&gt; &lt;span class='n'&gt;elem_list&lt;/span&gt; &lt;span class='n'&gt;ws&lt;/span&gt;&lt;span class='err'&gt;?&lt;/span&gt; &lt;span class='err'&gt;`&lt;/span&gt;&lt;span class='nn'&gt;list_utils&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;merge_proplists&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Node&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='err'&gt;`&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
  &lt;span class='n'&gt;elem_list&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='nn'&gt;head&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;elem&lt;/span&gt; &lt;span class='nn'&gt;tail&lt;/span&gt;&lt;span class='p'&gt;:(&lt;/span&gt;&lt;span class='n'&gt;ws&lt;/span&gt;&lt;span class='err'&gt;?&lt;/span&gt; &lt;span class='n'&gt;elem&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;*&lt;/span&gt; &lt;span class='err'&gt;`&lt;/span&gt;
    &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nv'&gt;Node&lt;/span&gt; &lt;span class='k'&gt;of&lt;/span&gt;
      &lt;span class='p'&gt;[]&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='p'&gt;[];&lt;/span&gt;
      &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='p'&gt;[];&lt;/span&gt;
      &lt;span class='p'&gt;_&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class='nv'&gt;Head&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;proplists&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;get_value&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;head&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Node&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt;
        &lt;span class='nv'&gt;Tail&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;R&lt;/span&gt; &lt;span class='p'&gt;||&lt;/span&gt; &lt;span class='p'&gt;[_,&lt;/span&gt;&lt;span class='nv'&gt;R&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='nn'&gt;proplists&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;get_value&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;tail&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Node&lt;/span&gt;&lt;span class='p'&gt;)],&lt;/span&gt;
        &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;Head&lt;/span&gt;&lt;span class='p'&gt;|&lt;/span&gt;&lt;span class='nv'&gt;Tail&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
  &lt;span class='err'&gt;`&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
  &lt;span class='n'&gt;elem&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='n'&gt;hook_elem&lt;/span&gt; &lt;span class='o'&gt;/&lt;/span&gt; &lt;span class='n'&gt;action_elem&lt;/span&gt; &lt;span class='err'&gt;~&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
  &lt;span class='n'&gt;hook_elem&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='n'&gt;action&lt;/span&gt; &lt;span class='n'&gt;&amp;#39;.&amp;#39;&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;bef&lt;/span&gt; &lt;span class='o'&gt;/&lt;/span&gt; &lt;span class='n'&gt;aft&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='n'&gt;&amp;#39;:&amp;#39;&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt; &lt;span class='err'&gt;\&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;&lt;span class='o'&gt;*&lt;/span&gt; &lt;span class='n'&gt;string&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;crlf&lt;/span&gt; &lt;span class='o'&gt;/&lt;/span&gt; &lt;span class='o'&gt;!&lt;/span&gt;&lt;span class='p'&gt;.)&lt;/span&gt; &lt;span class='err'&gt;`&lt;/span&gt;
    &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='nn'&gt;lists&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;nth&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Node&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt; 
      &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='nn'&gt;lists&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;nth&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;3&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Node&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt; &lt;span class='nn'&gt;lists&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;flatten&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nn'&gt;lists&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;nth&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;6&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Node&lt;/span&gt;&lt;span class='p'&gt;))}&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
  &lt;span class='err'&gt;`&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
  &lt;span class='n'&gt;action_elem&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='n'&gt;action&lt;/span&gt; &lt;span class='n'&gt;&amp;#39;:&amp;#39;&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt; &lt;span class='err'&gt;\&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;&lt;span class='o'&gt;*&lt;/span&gt; &lt;span class='n'&gt;string&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;crlf&lt;/span&gt; &lt;span class='o'&gt;/&lt;/span&gt; &lt;span class='o'&gt;!&lt;/span&gt;&lt;span class='p'&gt;.)&lt;/span&gt; &lt;span class='err'&gt;`&lt;/span&gt;
    &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='nn'&gt;lists&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;nth&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Node&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt; 
      &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;command&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nn'&gt;lists&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;flatten&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nn'&gt;lists&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;nth&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;4&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Node&lt;/span&gt;&lt;span class='p'&gt;))}&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
  &lt;span class='err'&gt;`&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;

  &lt;span class='n'&gt;action&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;bundle&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;/&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;mount&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;/&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;run&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;/&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;unmount&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;/&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;cleanup&amp;quot;&lt;/span&gt; &lt;span class='err'&gt;`&lt;/span&gt;&lt;span class='nn'&gt;erlang&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='nb'&gt;list_to_atom&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nn'&gt;lists&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;flatten&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Node&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;&lt;span class='err'&gt;`&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
  &lt;span class='n'&gt;ws&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;comment&lt;/span&gt; &lt;span class='o'&gt;/&lt;/span&gt; &lt;span class='n'&gt;space&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;*&lt;/span&gt; &lt;span class='err'&gt;`&lt;/span&gt;&lt;span class='p'&gt;{}&lt;/span&gt;&lt;span class='err'&gt;`&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
  &lt;span class='c'&gt;% Atoms&lt;/span&gt;
  &lt;span class='n'&gt;bef&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;before&amp;quot;&lt;/span&gt; &lt;span class='err'&gt;`&lt;/span&gt;&lt;span class='n'&gt;pre&lt;/span&gt;&lt;span class='err'&gt;`&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
  &lt;span class='n'&gt;aft&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;after&amp;quot;&lt;/span&gt; &lt;span class='err'&gt;`&lt;/span&gt;&lt;span class='n'&gt;post&lt;/span&gt;&lt;span class='err'&gt;`&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;

  &lt;span class='n'&gt;string&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='n'&gt;bracketed_string&lt;/span&gt; &lt;span class='o'&gt;/&lt;/span&gt; &lt;span class='n'&gt;nonbracketed_string&lt;/span&gt; &lt;span class='err'&gt;~&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
  &lt;span class='n'&gt;nonbracketed_string&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;!&lt;/span&gt;&lt;span class='n'&gt;crlf&lt;/span&gt; &lt;span class='p'&gt;.)&lt;/span&gt;&lt;span class='o'&gt;*&lt;/span&gt; &lt;span class='err'&gt;~&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
  &lt;span class='n'&gt;bracketed_string&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='n'&gt;&amp;#39;{&amp;#39;&lt;/span&gt; &lt;span class='nn'&gt;str&lt;/span&gt;&lt;span class='p'&gt;:(&lt;/span&gt;&lt;span class='o'&gt;!&lt;/span&gt;&lt;span class='n'&gt;&amp;#39;}&amp;#39;&lt;/span&gt; &lt;span class='p'&gt;(.))&lt;/span&gt;&lt;span class='o'&gt;*&lt;/span&gt; &lt;span class='n'&gt;&amp;#39;}&amp;#39;&lt;/span&gt; &lt;span class='err'&gt;`&lt;/span&gt;&lt;span class='nn'&gt;proplists&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;get_value&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;str&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Node&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='err'&gt;`&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;

  &lt;span class='n'&gt;comment&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='n'&gt;&amp;#39;#&amp;#39;&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;!&lt;/span&gt;&lt;span class='n'&gt;crlf&lt;/span&gt; &lt;span class='p'&gt;.)&lt;/span&gt;&lt;span class='o'&gt;*&lt;/span&gt; &lt;span class='n'&gt;crlf&lt;/span&gt; &lt;span class='err'&gt;~&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
  &lt;span class='n'&gt;space&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt; &lt;span class='err'&gt;\&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='err'&gt;\&lt;/span&gt;&lt;span class='n'&gt;n&lt;/span&gt;&lt;span class='err'&gt;\&lt;/span&gt;&lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='err'&gt;\&lt;/span&gt;&lt;span class='n'&gt;r&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='err'&gt;~&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
  &lt;span class='n'&gt;crlf&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;&lt;/span&gt;&lt;span class='se'&gt;\r\n&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;/&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;&lt;/span&gt;&lt;span class='se'&gt;\n&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;&lt;/span&gt; &lt;span class='err'&gt;~&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;That&amp;#8217;s it! Looks like a lot, but it&amp;#8217;s not as bad once you start looking at it. I&amp;#8217;ll leave this as an exercise to look through it for now. Some hints that I picked up to keep in mind either from Sean Cribbs or from working with the code for a while.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;(crlf / !.) at the end of a line means either a newline (note the crlf rule at the bottom) or the EOF character at the end of the file&lt;/li&gt;

&lt;li&gt;The &amp;#8217;!&amp;#8217; means NOT, it&amp;#8217;s a negative look-ahead character, so for example, the nonbracketed_string can be zero or more of any character except the crlf&lt;/li&gt;

&lt;li&gt;The &amp;#8216;string&amp;#8217; rule can be either a string or the stuff inside of {}s. Notice that the bracketed_string comes first in the string rule, this is why precedence matters. Try it the other way&lt;/li&gt;

&lt;li&gt;You can assign &amp;#8216;variables&amp;#8217; to the matches. For instance, look at the bracketed_string rule. The tag is: &amp;#8216;str:&amp;#8217;. This will put the tuple: {str, Value} into the Node variable, so you can pull it out later.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To actually use this, make sure the neotoma.beam is in your code path (or use the -p(a/z) switch to load it) and type:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;  &lt;span class='nn'&gt;neotoma&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;file&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;file.peg&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;If all the syntax is correct, neotoma will generate a parser with the two exported functions `parse/1` and `file/1`, which you can compile and use at your leisure.&lt;/p&gt;

&lt;p&gt;To get a copy of the code discussed in this tutorial in full, clone it from this repository here: &lt;a href='http://github.com/auser/neotoma_template'&gt;http://github.com/auser/neotoma_template&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Some quick links before I go:&lt;/p&gt;

&lt;p&gt;* &lt;a href='http://github.com/seancribbs/neotoma/'&gt;Neotoma source&lt;/a&gt; * &lt;a href='http://www.vimeo.com/7613228'&gt;Video introduction&lt;/a&gt; * &lt;a href='http://en.wikipedia.org/wiki/Parsing_expression_grammar'&gt;Parsing Expression Grammar Wikipedia&lt;/a&gt; * &lt;a href='http://groups.google.com/group/neotoma-erl'&gt;Google group&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks and I hope this helps you figure out Neotoma. Don&amp;#8217;t hesitate to ask.&lt;/p&gt;</content>
    </entry>
  
    <entry>
      <title>Snow Leopard Erlang woes (and the fix!)</title>
      <link href="http://willcodeforfoo.com/2009/10/12/borked-erlang-on-snow-leopard"/>
      <updated>2009-10-12T00:00:00-07:00</updated>
      <id>http://willcodeforfoo.com/2009/10/12/borked-erlang-on-snow-leopard</id>
      <content type="html">&lt;p&gt;After upgrading to &lt;a href='http://www.apple.com/macosx/'&gt;Snow Leopard&lt;/a&gt;, I found my os_mon erlang application exploded in a very ugly error message.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='o'&gt;=&lt;/span&gt;CRASH &lt;span class='nv'&gt;REPORT&lt;/span&gt;&lt;span class='o'&gt;====&lt;/span&gt; 12-Oct-2009::23:29:20 &lt;span class='o'&gt;===&lt;/span&gt;
  crasher:
    initial call: memsup:init/1
    pid: &amp;lt;0.76.0&amp;gt;
    registered_name: memsup
    exception &lt;span class='nb'&gt;exit&lt;/span&gt;: &lt;span class='o'&gt;}&lt;/span&gt;,
                     &lt;span class='o'&gt;[{&lt;/span&gt;memsup,get_memory_usage,1&lt;span class='o'&gt;}&lt;/span&gt;,
                      &lt;span class='o'&gt;{&lt;/span&gt;memsup,&lt;span class='s1'&gt;&amp;#39;-handle_info/2-fun-0-&amp;#39;&lt;/span&gt;,2&lt;span class='o'&gt;}]}&lt;/span&gt;
      in &lt;span class='k'&gt;function  &lt;/span&gt;gen_server:terminate/6
    ancestors: &lt;span class='o'&gt;[&lt;/span&gt;os_mon_sup,&amp;lt;0.46.0&amp;gt;&lt;span class='o'&gt;]&lt;/span&gt;
    messages: &lt;span class='o'&gt;[]&lt;/span&gt;
    links: &lt;span class='o'&gt;[&lt;/span&gt;&amp;lt;0.47.0&amp;gt;&lt;span class='o'&gt;]&lt;/span&gt;
    dictionary: &lt;span class='o'&gt;[]&lt;/span&gt;
    trap_exit: &lt;span class='nb'&gt;true&lt;/span&gt;
&lt;span class='nb'&gt;    &lt;/span&gt;status: running
    heap_size: 233
    stack_size: 24
    reductions: 172
  neighbours:
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;After some investigation, it turns out that Snow Leopard changed their output on vm_stat, the tool to look at the memory available on the system. The new output added the line:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;Pages speculative:                   42219.
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Where the erlang module memsup depends upon that not being there. The &lt;a href='http://www.erlang.org/'&gt;erlang&lt;/a&gt; developers get the ugliness. In any case, the patch looks like:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;--- a/lib/os_mon/src/memsup.erl
+++ b/lib/os_mon/src/memsup.erl
@@ -728,8 +728,12 @@ get_memory_usage&lt;span class='o'&gt;({&lt;/span&gt;unix,darwin&lt;span class='o'&gt;})&lt;/span&gt; -&amp;gt;
        io_lib:fread&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;Pages active:~d.&amp;quot;&lt;/span&gt;, skip_to_eol&lt;span class='o'&gt;(&lt;/span&gt;Str2&lt;span class='o'&gt;))&lt;/span&gt;,
     &lt;span class='o'&gt;{&lt;/span&gt;ok, &lt;span class='o'&gt;[&lt;/span&gt;Inactive&lt;span class='o'&gt;]&lt;/span&gt;,Str4&lt;span class='o'&gt;}&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt;
        io_lib:fread&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;Pages inactive:~d.&amp;quot;&lt;/span&gt;, skip_to_eol&lt;span class='o'&gt;(&lt;/span&gt;Str3&lt;span class='o'&gt;))&lt;/span&gt;,
+         &lt;span class='o'&gt;{&lt;/span&gt;ok, _,Str5&lt;span class='o'&gt;}&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt;
+       io_lib:fread&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;Pages speculative:~d.&amp;quot;&lt;/span&gt;, skip_to_eol&lt;span class='o'&gt;(&lt;/span&gt;Str4&lt;span class='o'&gt;))&lt;/span&gt;,
     &lt;span class='o'&gt;{&lt;/span&gt;ok, &lt;span class='o'&gt;[&lt;/span&gt;Wired&lt;span class='o'&gt;]&lt;/span&gt;,_&lt;span class='o'&gt;}&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt;
-       io_lib:fread&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;Pages wired down:~d.&amp;quot;&lt;/span&gt;, skip_to_eol&lt;span class='o'&gt;(&lt;/span&gt;Str4&lt;span class='o'&gt;))&lt;/span&gt;,
+       io_lib:fread&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;Pages wired down:~d.&amp;quot;&lt;/span&gt;, skip_to_eol&lt;span class='o'&gt;(&lt;/span&gt;Str5&lt;span class='o'&gt;))&lt;/span&gt;,
+  %     &lt;span class='o'&gt;{&lt;/span&gt;ok, &lt;span class='o'&gt;[&lt;/span&gt;Wired&lt;span class='o'&gt;]&lt;/span&gt;,_&lt;span class='o'&gt;}&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt;
+  % io_lib:fread&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;Pages wired down:~d.&amp;quot;&lt;/span&gt;, skip_to_eol&lt;span class='o'&gt;(&lt;/span&gt;Str4&lt;span class='o'&gt;))&lt;/span&gt;,
     &lt;span class='nv'&gt;NMemUsed&lt;/span&gt;  &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;Wired + Active + Inactive&lt;span class='o'&gt;)&lt;/span&gt; * 4000,
     &lt;span class='nv'&gt;NMemTotal&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; NMemUsed + Free * 4000,
     &lt;span class='o'&gt;{&lt;/span&gt;NMemUsed,NMemTotal&lt;span class='o'&gt;}&lt;/span&gt;;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Save this to a file, such as /tmp/erlang_patch. Full instructions for upgrading your erlang:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;git clone git://github.com/mfoemmel/erlang-otp.git
&lt;span class='nb'&gt;cd &lt;/span&gt;erlang-otp
patch -l -i /tmp/erlang_patch -p1
./configure --prefix&lt;span class='o'&gt;=&lt;/span&gt;/opt/erlang --enable-hipe
make
make install
&lt;span class='nb'&gt;export &lt;/span&gt;&lt;span class='nv'&gt;PATH&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;/opt/erlang/bin:&lt;span class='nv'&gt;$PATH&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;After that, you should be able to start os_mon:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;erl
1&amp;gt; application:start&lt;span class='o'&gt;(&lt;/span&gt;sasl&lt;span class='o'&gt;)&lt;/span&gt;.
2&amp;gt; application:start&lt;span class='o'&gt;(&lt;/span&gt;os_mon&lt;span class='o'&gt;)&lt;/span&gt;.
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;If it starts, you&amp;#8217;re done!&lt;/p&gt;

&lt;p&gt;Hope this helps.&lt;/p&gt;
&lt;small&gt;Fixed typo, thanks to Craig Krigsman&lt;/small&gt;</content>
    </entry>
  
    <entry>
      <title>Getting command-line options into erlang</title>
      <link href="http://willcodeforfoo.com/2009/10/04/erlang-application-variables"/>
      <updated>2009-10-04T00:00:00-07:00</updated>
      <id>http://willcodeforfoo.com/2009/10/04/erlang-application-variables</id>
      <content type="html">&lt;p&gt;So you have your killer erlang application that possibly could make you millions, but it was written in a test environment. Shoot, how do you change that &amp;#8220;on the fly&amp;#8221; at the application runtime? There are a many different ways this can be accomplished. This post will go over the basics of this typical issue.&lt;/p&gt;

&lt;h2 id='application_variables'&gt;Application variables&lt;/h2&gt;

&lt;p&gt;Application variables must be declared in the .app file for your application. For instance:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;application&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;killer_app&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
 &lt;span class='p'&gt;[{&lt;/span&gt;&lt;span class='n'&gt;description&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;The most killer application ever&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;},&lt;/span&gt;
  &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;modules&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;[]},&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;registered&lt;/span&gt;&lt;span class='p'&gt;,[]},{&lt;/span&gt;&lt;span class='n'&gt;applications&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;kernel&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;&lt;span class='n'&gt;stdlib&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;&lt;span class='n'&gt;sasl&lt;/span&gt;&lt;span class='p'&gt;]},&lt;/span&gt;
  &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;env&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;
    &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;key&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;&amp;#39;value&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='c'&gt;% proplist&lt;/span&gt;
        &lt;span class='p'&gt;]&lt;/span&gt;
&lt;span class='p'&gt;...&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;From here, the key is settable from the command-line simply by passing it (with a little erlang idiom): &lt;div class='highlight'&gt;&lt;pre&gt;erl -pa ./ebin -killer_app key &lt;span class='s1'&gt;&amp;#39;new_value&amp;#39;&lt;/span&gt; 
&lt;/pre&gt;
&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;From within the application, this can be fetched by looking it up:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='nv'&gt;Value&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nn'&gt;application&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;get_env&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;killer_app&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;key&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='k'&gt;of&lt;/span&gt;
  &lt;span class='n'&gt;undefined&lt;/span&gt;   &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;&amp;#39;default&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
  &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;ok&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;V&lt;/span&gt;&lt;span class='p'&gt;}&lt;/span&gt;     &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nv'&gt;V&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='environment_variables'&gt;Environment variables&lt;/h2&gt;

&lt;p&gt;Sometimes it&amp;#8217;s just easier and the application runtime environment requires that variables need to be fetched from an environment variable. These are also super easy to lookup, arguably even easier:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='nv'&gt;EnvParam&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;string&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;to_upper&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nn'&gt;erlang&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='nb'&gt;atom_to_list&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;&amp;#39;key&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)),&lt;/span&gt;
&lt;span class='nv'&gt;Value&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nn'&gt;os&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;getenv&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;EnvParam&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='k'&gt;of&lt;/span&gt;
  &lt;span class='n'&gt;false&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nv'&gt;Default&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
  &lt;span class='nv'&gt;E&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nv'&gt;E&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This can obviously be set the standard way an environment variable is set:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='nv'&gt;KEY&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;awesome_value&amp;#39;&lt;/span&gt; erl -pa ./ebin
&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='configuration_file'&gt;Configuration file&lt;/h2&gt;

&lt;p&gt;Other times I just want to set my configuration in a file and be done with it, so that deployment is only dependent upon a change of the configuration file. An application configuration file is a newline separated set of proplists. For instance, it might look like:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;port&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;8080&lt;/span&gt;&lt;span class='p'&gt;}.&lt;/span&gt;
&lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;log_path&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;logs/killer_app.log&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;}.&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;These are pretty easy to look up as well, but it&amp;#8217;s important to note that the variables set here must be in the application configuration file as shown above. Fetching these variables might look something like:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='nv'&gt;Proplists&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nn'&gt;file&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;consult&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;config/config.cfg&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='k'&gt;of&lt;/span&gt;
  &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;ok&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;C&lt;/span&gt;&lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nv'&gt;C&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
  &lt;span class='nv'&gt;O&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nv'&gt;O&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
&lt;span class='nv'&gt;Value&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;proplists&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;get_value&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;key&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Proplists&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I tend to like more niceties than this, don&amp;#8217;t you? When fetching from a configuration file, I tend to use a helper:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='p'&gt;-&lt;/span&gt;&lt;span class='ni'&gt;module&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;config&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;
&lt;span class='p'&gt;-&lt;/span&gt;&lt;span class='ni'&gt;include&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;killer_app.hrl&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;
&lt;span class='p'&gt;-&lt;/span&gt;&lt;span class='ni'&gt;compile&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;export_all&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;

&lt;span class='c'&gt;%%--------------------------------------------------------------------&lt;/span&gt;
&lt;span class='c'&gt;%% Function: Read the config file () -&amp;gt; {ok, Config} | &lt;/span&gt;
&lt;span class='c'&gt;%%                                      {error, Reason}&lt;/span&gt;
&lt;span class='c'&gt;%% Description: Read the configuration data&lt;/span&gt;
&lt;span class='c'&gt;%%--------------------------------------------------------------------&lt;/span&gt;
&lt;span class='nf'&gt;read&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='n'&gt;read_1&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='no'&gt;?CONFIG_FILE&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='k'&gt;of&lt;/span&gt;
    &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;ok&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;C&lt;/span&gt;&lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;ok&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;C&lt;/span&gt;&lt;span class='p'&gt;};&lt;/span&gt;
    &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;error&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;enoent&lt;/span&gt;&lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;error&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;no_file&lt;/span&gt;&lt;span class='p'&gt;};&lt;/span&gt;
    &lt;span class='nv'&gt;Err&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nv'&gt;Err&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;
 
&lt;span class='nf'&gt;read_1&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Location&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nn'&gt;file&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;consult&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Location&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='k'&gt;of&lt;/span&gt;
    &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;ok&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;C&lt;/span&gt;&lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nv'&gt;C&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='nv'&gt;O&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nv'&gt;O&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;
&lt;span class='c'&gt;%%--------------------------------------------------------------------&lt;/span&gt;
&lt;span class='c'&gt;%% Function: get (Key, Config) -&amp;gt; {error, not_found} |&lt;/span&gt;
&lt;span class='c'&gt;%%                                {ok, Value}&lt;/span&gt;
&lt;span class='c'&gt;%% Description: Get the value of a config element&lt;/span&gt;
&lt;span class='c'&gt;%%--------------------------------------------------------------------&lt;/span&gt;
&lt;span class='nb'&gt;get&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Key&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nb'&gt;get&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Key&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;read&lt;/span&gt;&lt;span class='p'&gt;()).&lt;/span&gt;
&lt;span class='nb'&gt;get&lt;/span&gt;&lt;span class='p'&gt;(_&lt;/span&gt;&lt;span class='nv'&gt;Key&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;[])&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;error&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;not_found&lt;/span&gt;&lt;span class='p'&gt;};&lt;/span&gt;
&lt;span class='nb'&gt;get&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Key&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;[{&lt;/span&gt;&lt;span class='nv'&gt;Key&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Value&lt;/span&gt;&lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='p'&gt;|&lt;/span&gt; &lt;span class='p'&gt;_&lt;/span&gt;&lt;span class='nv'&gt;Config&lt;/span&gt;&lt;span class='p'&gt;])&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;ok&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Value&lt;/span&gt;&lt;span class='p'&gt;};&lt;/span&gt;
&lt;span class='nb'&gt;get&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Key&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;[{_&lt;/span&gt;&lt;span class='nv'&gt;Other&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;_&lt;/span&gt;&lt;span class='nv'&gt;Value&lt;/span&gt;&lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='p'&gt;|&lt;/span&gt; &lt;span class='nv'&gt;Config&lt;/span&gt;&lt;span class='p'&gt;])&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class='nb'&gt;get&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Key&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Config&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;By using that, I can simply call:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='nn'&gt;config&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='nb'&gt;get&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;key&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Finally, I hate to clutter my code with all the funkiness of fetching an application variable, so I tend to use a utility that cleans it up pretty nicely.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='p'&gt;-&lt;/span&gt;&lt;span class='ni'&gt;module&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;apps&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;

&lt;span class='p'&gt;-&lt;/span&gt;&lt;span class='ni'&gt;export&lt;/span&gt; &lt;span class='p'&gt;([&lt;/span&gt;&lt;span class='n'&gt;search_for_application_value&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;3&lt;/span&gt;&lt;span class='p'&gt;]).&lt;/span&gt;

&lt;span class='c'&gt;% Find the application config value&lt;/span&gt;
&lt;span class='nf'&gt;search_for_application_value&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Param&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Default&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;App&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nn'&gt;application&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;get_env&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;App&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Param&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='k'&gt;of&lt;/span&gt;
    &lt;span class='n'&gt;undefined&lt;/span&gt;         &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;search_for_application_value_from_config&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Param&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Default&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
    &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;ok&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;undefined&lt;/span&gt;&lt;span class='p'&gt;}&lt;/span&gt;   &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;search_for_application_value_from_config&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Param&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Default&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
    &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;ok&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;V&lt;/span&gt;&lt;span class='p'&gt;}&lt;/span&gt;    &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nv'&gt;V&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;

&lt;span class='nf'&gt;search_for_application_value_from_config&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Param&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Default&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;
	&lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nn'&gt;config&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='nb'&gt;get&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Param&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='k'&gt;of&lt;/span&gt;
		&lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;error&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;_}&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;search_for_application_value_from_environment&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Param&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Default&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
		&lt;span class='nv'&gt;V&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nv'&gt;V&lt;/span&gt;
	&lt;span class='k'&gt;end&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;

&lt;span class='nf'&gt;search_for_application_value_from_environment&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Param&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Default&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class='nv'&gt;EnvParam&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;string&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;to_upper&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nn'&gt;erlang&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='nb'&gt;atom_to_list&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Param&lt;/span&gt;&lt;span class='p'&gt;)),&lt;/span&gt;
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nn'&gt;os&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;getenv&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;EnvParam&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='k'&gt;of&lt;/span&gt;
    &lt;span class='n'&gt;false&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nv'&gt;Default&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='nv'&gt;E&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nv'&gt;E&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Using this, I can simply call and I get built-in defaults for free:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='nv'&gt;AppDir&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;apps&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;search_for_application_value&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;port&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;8080&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;killer_app&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;</content>
    </entry>
  
    <entry>
      <title>AMQP cake with Ruby: Using Ruby and RabbitMQ together</title>
      <link href="http://willcodeforfoo.com/2009/08/04/ruby-amqp-gem"/>
      <updated>2009-08-04T00:00:00-07:00</updated>
      <id>http://willcodeforfoo.com/2009/08/04/ruby-amqp-gem</id>
      <content type="html">&lt;p&gt;There are a bunch of different ways to get connected to &lt;a href='http://www.rabbitmq.com/'&gt;RabbitMQ&lt;/a&gt;. Thankfully the community has somewhat rallied behind the queue messaging system and there are a growing number of clients/libraries to aid in accessing the queue&amp;#8217;s functionality.&lt;/p&gt;

&lt;p&gt;In this post, we&amp;#8217;ll explore the different options for connecting a ruby program to the &lt;a href='http://jira.amqp.org/confluence/'&gt;AMQP&lt;/a&gt;-driven queue server. So, with no further ado:&lt;/p&gt;

&lt;h2 id='amqp_the_grandfather'&gt;AMQP: the grandfather&lt;/h2&gt;

&lt;h3 id='installing'&gt;Installing&lt;/h3&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;gem sources -a http://gems.github.com
sudo gem install tmm1-amqp
&lt;span class='c'&gt;# OR, for the developers in the crowd&lt;/span&gt;
git clone git://github.com/tmm1/amqp.git
rake gem
sudo gem install amqp-*.gem
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now that we&amp;#8217;ve got it installed, let&amp;#8217;s write a quick example to get connected:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='nb'&gt;require&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;rubygems&amp;quot;&lt;/span&gt;
&lt;span class='nb'&gt;require&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;mq&amp;#39;&lt;/span&gt;

&lt;span class='no'&gt;EM&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;run&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
  &lt;span class='no'&gt;AMQP&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;start&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:host&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
    &lt;span class='n'&gt;amq&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;MQ&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;
    &lt;span class='no'&gt;EM&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;add_periodic_timer&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='n'&gt;amq&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;queue&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;noises&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;publish&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;moo&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Exactly as it looks, we&amp;#8217;ll be using &lt;a href='http://rubyeventmachine.com/'&gt;EventMachine&lt;/a&gt; to provide us with a periodic timer. When the timer has been exhausted, the block will be run, in our case we&amp;#8217;ll push the message &amp;#8220;moo&amp;#8221; to the queue named &amp;#8220;noises&amp;#8221; at the RabbitMQ host (in this example, it&amp;#8217;s at localhost).&lt;/p&gt;

&lt;p&gt;Now, let&amp;#8217;s consume a message now. This is nearly straight from the examples/ directory of tmm1-amqp library:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='nb'&gt;require&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;rubygems&amp;quot;&lt;/span&gt;
&lt;span class='nb'&gt;require&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;mq&amp;#39;&lt;/span&gt;

&lt;span class='no'&gt;AMQP&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;start&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:host&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
  &lt;span class='no'&gt;MQ&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;queue&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;noises&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;publish&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;moo&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='no'&gt;MQ&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;queue&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;noises&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;publish&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;quack&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='no'&gt;MQ&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;queue&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;noises&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;publish&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;bark&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  
  &lt;span class='n'&gt;i&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;
  
  &lt;span class='no'&gt;MQ&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;queue&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;noises&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;subscribe&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:ack&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='kp'&gt;true&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;h&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;&lt;span class='n'&gt;m&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;
    &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;i&lt;/span&gt;&lt;span class='o'&gt;+=&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='mi'&gt;3&lt;/span&gt;
      &lt;span class='nb'&gt;puts&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;Shutting down...&amp;#39;&lt;/span&gt;
      &lt;span class='no'&gt;AMQP&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;stop&lt;/span&gt;&lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='no'&gt;EM&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;stop&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;

    &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='no'&gt;AMQP&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;closing?&lt;/span&gt;
      &lt;span class='nb'&gt;puts&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;&lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;m&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt; (ignored, redelivered later)&amp;quot;&lt;/span&gt;
    &lt;span class='k'&gt;else&lt;/span&gt;
      &lt;span class='nb'&gt;puts&lt;/span&gt; &lt;span class='n'&gt;m&lt;/span&gt;
      &lt;span class='n'&gt;h&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;ack&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;  

&lt;span class='c1'&gt;# moo&lt;/span&gt;
&lt;span class='c1'&gt;# quack&lt;/span&gt;
&lt;span class='c1'&gt;# Shutting down...&lt;/span&gt;
&lt;span class='c1'&gt;# bark (ignored, redelivered later)&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;In this example, we&amp;#8217;ve pushed a few sounds to the noises queue and then later subscribe to the queue (and demanding an &lt;b&gt;ack&lt;/b&gt;nowledgement receipt).&lt;/p&gt;

&lt;p&gt;There are alternative methods to pull a message off the queue. For instance, you can use pop (if you don&amp;#8217;t need an &lt;b&gt;ack&lt;/b&gt; of the message):&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='n'&gt;queue&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;pop&lt;/span&gt;&lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;msg&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;
  &lt;span class='k'&gt;unless&lt;/span&gt; &lt;span class='n'&gt;msg&lt;/span&gt;
    &lt;span class='c1'&gt;# queue was empty&lt;/span&gt;
    &lt;span class='nb'&gt;p&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='no'&gt;Time&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;now&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:queue_empty!&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;

    &lt;span class='c1'&gt;# try again in 1 second&lt;/span&gt;
    &lt;span class='no'&gt;EM&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;add_timer&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;){&lt;/span&gt; &lt;span class='n'&gt;queue&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;pop&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
  &lt;span class='k'&gt;else&lt;/span&gt;
    &lt;span class='c1'&gt;# process this message&lt;/span&gt;
    &lt;span class='nb'&gt;p&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='no'&gt;Time&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;now&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;msg&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;

    &lt;span class='c1'&gt;# get the next message in the queue&lt;/span&gt;
    &lt;span class='n'&gt;queue&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;pop&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Up until now, we&amp;#8217;ve only used a queue type called: &lt;em&gt;type&lt;/em&gt;. Now, there are N+1 ways to skin a cat, so let&amp;#8217;s look at sending a queue message everyone who is subscribed to the fanout. First off, to understand how this works, let&amp;#8217;s define a fanout. A fanout in RabbitMQ terminology is like a direct exchange, except that it represents a 1:N message delivery pattern. Now, one more, we need to define a binding as well, you&amp;#8217;ll see why in just a minute. First, a binding, from the RabbitMQ documentation:&lt;/p&gt;
&lt;blockquote&gt;&lt;span class='bqstart'&gt;&amp;#8216;&lt;/span&gt;When you publish a message, you send a "routing key" along with it, that's used by the exchange when it decides which queues to forward a copy of the message on to. The links between exchanges and queues are created through binding, with a "binding pattern" that is used by the exchange when comparing against routing keys.&lt;/blockquote&gt;
&lt;p&gt;Now that we&amp;#8217;ve got that under control, let&amp;#8217;s actually write one. Again, this is nearly directly from the examples/mq/clock.rb if you&amp;#8217;d like to look at a more complete example&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='nb'&gt;require&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;rubygems&amp;quot;&lt;/span&gt;
&lt;span class='nb'&gt;require&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;mq&amp;quot;&lt;/span&gt;

&lt;span class='no'&gt;AMQP&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;start&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:host&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;log&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='n'&gt;args&lt;/span&gt;
    &lt;span class='nb'&gt;p&lt;/span&gt; &lt;span class='n'&gt;args&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;
  
  &lt;span class='n'&gt;clock&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;MQ&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;fanout&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;clock&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='no'&gt;EM&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;add_periodic_timer&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;){&lt;/span&gt;
    &lt;span class='n'&gt;log&lt;/span&gt; &lt;span class='ss'&gt;:publishing&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;time&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;Time&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;now&lt;/span&gt;
    &lt;span class='n'&gt;clock&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;publish&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='no'&gt;Marshal&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;dump&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;time&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
  &lt;span class='p'&gt;}&lt;/span&gt;

  &lt;span class='n'&gt;amq&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;MQ&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;
  &lt;span class='n'&gt;amq&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;queue&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;every second&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;bind&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;amq&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;fanout&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;clock&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;subscribe&lt;/span&gt;&lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;time&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;
    &lt;span class='n'&gt;log&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;every second&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:received&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='no'&gt;Marshal&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;load&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;time&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='p'&gt;}&lt;/span&gt;
  
  &lt;span class='n'&gt;amq&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;MQ&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;
  &lt;span class='n'&gt;amq&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;queue&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;every 5 seconds&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;bind&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;amq&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;fanout&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;clock&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;subscribe&lt;/span&gt;&lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;time&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;
    &lt;span class='n'&gt;time&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;Marshal&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;load&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;time&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='n'&gt;log&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;every 5 seconds&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:received&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;time&lt;/span&gt; &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='n'&gt;time&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;strftime&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;%S&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;to_i&lt;/span&gt;&lt;span class='o'&gt;%&lt;/span&gt;&lt;span class='mi'&gt;5&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;
  &lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Okay, So first off, we created a new fanout and using MQ and EventMachine again, we&amp;#8217;ve created a periodic timer that will publish to the clock fanout (again, a 1:N communication). Then we bind (recall a binding is just a link to the queue&amp;#8217;s &amp;#8220;router&amp;#8221;) to the fanout named &amp;#8220;clock&amp;#8221; and subscribe to it whn there is a new message in the clock queue. Notice we take two differently named queues (one is called &amp;#8220;every second&amp;#8221; and the other &amp;#8220;every 5 seconds&amp;#8221;) and bind them to the same fanout. This works because the fanout provides the 1:N communication again.&lt;/p&gt;

&lt;p&gt;Now, notice that we are only logging if the time mod 5 is zero, or essentially every 5 seconds. However, if we remove that if block, then you&amp;#8217;ll notice that the queue still receives messages. This is because the fanout is publishing the message to &lt;b&gt;EVERYONE&lt;/b&gt; who is subscribed to the fanout. That&amp;#8217;s how the fanout works.&lt;/p&gt;

&lt;p&gt;Now, the AMQP library provides something really kind of neat. You can send &amp;#8220;RPC&amp;#8221; calls across the wire to the queue. How? Let&amp;#8217;s look at another example from the examples/ directory:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='nb'&gt;require&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;rubygems&amp;quot;&lt;/span&gt;
&lt;span class='nb'&gt;require&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;mq&amp;#39;&lt;/span&gt;

&lt;span class='no'&gt;AMQP&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;start&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:host&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;

  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;log&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='n'&gt;args&lt;/span&gt;
    &lt;span class='nb'&gt;p&lt;/span&gt; &lt;span class='n'&gt;args&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;

  &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;HashTable&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;Hash&lt;/span&gt;
    &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;get&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;key&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='nb'&gt;self&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='n'&gt;key&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
    &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;set&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;key&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;value&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='nb'&gt;self&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='n'&gt;key&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;value&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;

  &lt;span class='n'&gt;server&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;MQ&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;rpc&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;hash table node&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='no'&gt;HashTable&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;

  &lt;span class='n'&gt;client&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;MQ&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;rpc&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;hash table node&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='n'&gt;client&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;set&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:now&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;time&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;Time&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;now&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='n'&gt;client&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;get&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:now&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;res&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;
    &lt;span class='n'&gt;log&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;client&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:now&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;res&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:eql?&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;res&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='n'&gt;time&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;

  &lt;span class='n'&gt;client&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;set&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:one&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='n'&gt;client&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;get&lt;/span&gt; &lt;span class='ss'&gt;:one&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;res&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt; 
    &lt;span class='nb'&gt;p&lt;/span&gt; &lt;span class='n'&gt;res&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;
  &lt;span class='n'&gt;client&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;keys&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;res&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;
    &lt;span class='n'&gt;log&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;client&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:keys&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;res&lt;/span&gt;
    &lt;span class='no'&gt;AMQP&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;stop&lt;/span&gt;&lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='no'&gt;EM&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;stop&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;

&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Sweetness. We are taking a HashTable object and storing it&amp;#8217;s in a Marshalled format (thanks to the amqp gem) into the queue. When we pop it out, we get a full object back.&lt;/p&gt;

&lt;p&gt;A few other notes.&lt;/p&gt;

&lt;p&gt;We can create a topic exchange, which is kind of like a fanout, except that instead of 1:N, it&amp;#8217;s N:N. To do this, we&amp;#8217;ll write a mini chat server (well, we&amp;#8217;ll pull it from the very smart blog: http://www.randomhacks.net/articles/2009/05/08/chat-client-ruby-amqp-eventmachine-shoes). Some more quick overhead before we get to the code. When we created the binding before, we set a :key that was equivalent to the name of the queue. We can do better than that and specifically set it to an exact queue channel via the bind method:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='n'&gt;queue&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;bind&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;chat&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:key&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='vg'&gt;$channel&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This sets a binding on the chat queue to match any key with the name of the channel in the chat program. You can set wildcards, and arrays in the key parameter. Now, when we publish a message, we&amp;#8217;ll use the routing key to ensure it gets sent to the right bindings:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='no'&gt;MQ&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;queue&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;chat&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;publish&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot; -&amp;gt; &lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;data&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:routing_key&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='vg'&gt;$channel&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now, on to the entire program:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='nb'&gt;require&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;rubygems&amp;#39;&lt;/span&gt;
&lt;span class='n'&gt;gem&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;amqp&amp;#39;&lt;/span&gt;
&lt;span class='nb'&gt;require&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;mq&amp;#39;&lt;/span&gt;

&lt;span class='k'&gt;unless&lt;/span&gt; &lt;span class='no'&gt;ARGV&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;length&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt;
  &lt;span class='no'&gt;STDERR&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;puts&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Usage: &lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='vg'&gt;$0&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt; &amp;lt;channel&amp;gt; &amp;lt;nick&amp;gt;&amp;quot;&lt;/span&gt;
  &lt;span class='nb'&gt;exit&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='vg'&gt;$channel&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='vg'&gt;$nick&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;ARGV&lt;/span&gt;

&lt;span class='no'&gt;AMQP&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;start&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:host&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
  &lt;span class='vg'&gt;$chat&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;MQ&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;topic&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;chat&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;

  &lt;span class='c1'&gt;# Print any messages on our channel.&lt;/span&gt;
  &lt;span class='n'&gt;queue&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;MQ&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;queue&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='vg'&gt;$nick&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='n'&gt;queue&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;bind&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;chat&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:key&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='vg'&gt;$channel&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='n'&gt;queue&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;subscribe&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;msg&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;
    &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='n'&gt;msg&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;index&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;&lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='vg'&gt;$nick&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;:&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;!=&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;
      &lt;span class='nb'&gt;puts&lt;/span&gt; &lt;span class='n'&gt;msg&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;

  &lt;span class='c1'&gt;# Forward console input to our channel.&lt;/span&gt;
  &lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='nn'&gt;KeyboardInput&lt;/span&gt;
    &lt;span class='kp'&gt;include&lt;/span&gt; &lt;span class='no'&gt;EM&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Protocols&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;LineText2&lt;/span&gt;
    &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;receive_line&lt;/span&gt; &lt;span class='n'&gt;data&lt;/span&gt;
      &lt;span class='vg'&gt;$chat&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;publish&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;&lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='vg'&gt;$nick&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;: &lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;data&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
                    &lt;span class='ss'&gt;:routing_key&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='vg'&gt;$channel&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;
  &lt;span class='no'&gt;EM&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;open_keyboard&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='no'&gt;KeyboardInput&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Last example of the day: We can distribute work in our programs as well.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='nb'&gt;require&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;rubygems&amp;quot;&lt;/span&gt;
&lt;span class='nb'&gt;require&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;mq&amp;#39;&lt;/span&gt;

&lt;span class='no'&gt;MAX&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;1000&lt;/span&gt;

&lt;span class='c1'&gt;# logging&lt;/span&gt;
&lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;log&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='n'&gt;args&lt;/span&gt;
  &lt;span class='nb'&gt;p&lt;/span&gt; &lt;span class='n'&gt;args&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;

&lt;span class='c1'&gt;# spawn workers&lt;/span&gt;
&lt;span class='n'&gt;workers&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;ARGV&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='p'&gt;?&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;Integer&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='no'&gt;ARGV&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='k'&gt;rescue&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;:&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;
&lt;span class='no'&gt;AMQP&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;fork&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;workers&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;

  &lt;span class='n'&gt;log&lt;/span&gt; &lt;span class='no'&gt;MQ&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;id&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:started&lt;/span&gt;

  &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;Fixnum&lt;/span&gt;
    &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;prime?&lt;/span&gt;
      &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;1&amp;#39;&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt; &lt;span class='nb'&gt;self&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;!~&lt;/span&gt; &lt;span class='sr'&gt;/^1?$|^(11+?)\1+$/&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;

  &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;PrimeChecker&lt;/span&gt;
    &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;is_prime?&lt;/span&gt; &lt;span class='n'&gt;number&lt;/span&gt;
      &lt;span class='n'&gt;log&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;prime checker &lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='no'&gt;MQ&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;id&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:prime?&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;number&lt;/span&gt;
      &lt;span class='n'&gt;number&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;prime?&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;

  &lt;span class='no'&gt;MQ&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;rpc&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;prime checker&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='no'&gt;PrimeChecker&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;

&lt;span class='k'&gt;end&lt;/span&gt;

&lt;span class='c1'&gt;# use workers to check which numbers are prime&lt;/span&gt;
&lt;span class='no'&gt;AMQP&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;start&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:host&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
  
  &lt;span class='n'&gt;prime_checker&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;MQ&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;rpc&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;prime checker&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;

  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;10_000&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;.&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;10_000&lt;/span&gt;&lt;span class='o'&gt;+&lt;/span&gt;&lt;span class='no'&gt;MAX&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;each&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;num&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;
    &lt;span class='n'&gt;log&lt;/span&gt; &lt;span class='ss'&gt;:checking&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;num&lt;/span&gt;

    &lt;span class='n'&gt;prime_checker&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;is_prime?&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;num&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;is_prime&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;
      &lt;span class='n'&gt;log&lt;/span&gt; &lt;span class='ss'&gt;:prime?&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;num&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;is_prime&lt;/span&gt;
      &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='vi'&gt;@primes&lt;/span&gt;&lt;span class='o'&gt;||=[]&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class='n'&gt;num&lt;/span&gt; &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='n'&gt;is_prime&lt;/span&gt;
      
      &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='vi'&gt;@responses&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='vi'&gt;@responses&lt;/span&gt; &lt;span class='o'&gt;||&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='no'&gt;MAX&lt;/span&gt;
        &lt;span class='n'&gt;log&lt;/span&gt; &lt;span class='ss'&gt;:primes&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='vi'&gt;@primes&lt;/span&gt;
        &lt;span class='no'&gt;EM&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;stop_event_loop&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;

  &lt;span class='k'&gt;end&lt;/span&gt;
  
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;By using the fork method in AMQP, we are forking several consumers of the messages in the &amp;#8216;prime checker&amp;#8217; rpc queue. This shows just how easy it is to multithread a consumer for an amqp queue.&lt;/p&gt;</content>
    </entry>
  
    <entry>
      <title>Using mochiweb to create a web framework in erlang</title>
      <link href="http://willcodeforfoo.com/2009/07/29/using-mochiweb-to-create-a-webframework-in-erlang"/>
      <updated>2009-07-29T00:00:00-07:00</updated>
      <id>http://willcodeforfoo.com/2009/07/29/using-mochiweb-to-create-a-webframework-in-erlang</id>
      <content type="html">&lt;p&gt;Recently, I used &lt;a href='http://code.google.com/p/mochiweb/'&gt;Mochiweb&lt;/a&gt; for several &lt;a href='http://willcodeforfoo.com/2009/07/13/announcing-alice/'&gt;projects&lt;/a&gt; (&lt;a href='http://alicetheapp.com'&gt;Alice&lt;/a&gt;) I&amp;#8217;ve been working on. After some investigation of the current erlang web frameworks, Mochiweb suited our needs well. It&amp;#8217;s lightweight, fast, open-source and pretty source code. Throughout this post, we&amp;#8217;ll build a little mochiweb application, so note that it will be available in full for download at the end of the article, but we&amp;#8217;ll write bits and pieces at a time.&lt;/p&gt;

&lt;p&gt;So with no further ado: &lt;h3&gt;Using mochiweb in erlang&lt;/h3&gt;&lt;/p&gt;

&lt;p&gt;Starting mochiweb is pretty straightforward. Just calling the mochiweb_http:start/1 function, we&amp;#8217;ll start the mochiweb application. This is, to me the most dynamic way to start a mochiweb application. While it can be done in a different way, this allows more flexibility. Notice that we&amp;#8217;ll be passing a loop function. We&amp;#8217;ll define that shortly, but for now, just note that it&amp;#8217;s the function that will be receiving the requests.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='p'&gt;-&lt;/span&gt;&lt;span class='ni'&gt;module&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;mochiweb_server&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;
&lt;span class='p'&gt;-&lt;/span&gt;&lt;span class='ni'&gt;export&lt;/span&gt; &lt;span class='p'&gt;([&lt;/span&gt;&lt;span class='n'&gt;start_mochiweb&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;]).&lt;/span&gt;

&lt;span class='nf'&gt;start_mochiweb&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Args&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;Port&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nv'&gt;Args&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
  &lt;span class='nn'&gt;io&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;format&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;Starting mochiweb_http with &lt;/span&gt;&lt;span class='si'&gt;~p~n&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;Port&lt;/span&gt;&lt;span class='p'&gt;]),&lt;/span&gt;
  &lt;span class='nn'&gt;mochiweb_http&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;start&lt;/span&gt;&lt;span class='p'&gt;([&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;port&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Port&lt;/span&gt;&lt;span class='p'&gt;},&lt;/span&gt;
                        &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;loop&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='k'&gt;fun&lt;/span&gt; &lt;span class='n'&gt;dispatch_requests&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;}]).&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now, as promised, let&amp;#8217;s look at how to handle we&amp;#8217;ll handle the requests:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='p'&gt;-&lt;/span&gt;&lt;span class='ni'&gt;export&lt;/span&gt; &lt;span class='p'&gt;([&lt;/span&gt;&lt;span class='n'&gt;dispatch_requests&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;]).&lt;/span&gt;

&lt;span class='c'&gt;% ...&lt;/span&gt;

&lt;span class='nf'&gt;dispatch_requests&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Req&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class='nv'&gt;Path&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nv'&gt;Req&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='nb'&gt;get&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;path&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt;
  &lt;span class='nv'&gt;Action&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;clean_path&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Path&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt;
  &lt;span class='n'&gt;handle&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Action&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Req&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;

&lt;span class='c'&gt;% Get a clean path&lt;/span&gt;
&lt;span class='c'&gt;% strips off the query string&lt;/span&gt;
&lt;span class='nf'&gt;clean_path&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Path&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nn'&gt;string&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;str&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Path&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;?&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='k'&gt;of&lt;/span&gt;
    &lt;span class='mi'&gt;0&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nv'&gt;Path&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='nv'&gt;N&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nn'&gt;string&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;substr&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Path&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;N&lt;/span&gt; &lt;span class='o'&gt;-&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The Req record that is passed in is a &lt;a href='http://code.google.com/p/mochiweb/source/browse/trunk/src/mochiweb_request.erl'&gt;mochiweb_request&lt;/a&gt; record, which gives us access to all the methods defined in the mochiweb_request record. We&amp;#8217;ll use the Req:get(path) method to pull out the path. Notice that we are also pulling out the Action the path defines by stripping off any query string at the end. Sweet.&lt;/p&gt;

&lt;p&gt;Now, for some nifty request handling, we&amp;#8217;ll use the handle method to give us the ability to handle requests with Erlang&amp;#8217;s pattern matching:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='nf'&gt;handle&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;/favicon.ico&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Req&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nv'&gt;Req&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;respond&lt;/span&gt;&lt;span class='p'&gt;({&lt;/span&gt;&lt;span class='mi'&gt;200&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;[{&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;Content-Type&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;text/html&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;}],&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;});&lt;/span&gt;
&lt;span class='nf'&gt;handle&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Path&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Req&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
	&lt;span class='nv'&gt;Req&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;respond&lt;/span&gt;&lt;span class='p'&gt;({&lt;/span&gt;&lt;span class='mi'&gt;200&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;[{&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;Content-Type&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;text/html&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;}],&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;&amp;lt;h3&amp;gt;Hello world&amp;lt;/h3&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Sweet! Digging a little deeper, we can see that any request that is not /favicon.ico is going to respond with Hello World (Also, notice the use of respond on the Req record). The respond method takes a tuple that consists of:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;status&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;[{&lt;/span&gt;&lt;span class='n'&gt;proplist_of&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;headers&lt;/span&gt;&lt;span class='p'&gt;}],&lt;/span&gt; &lt;span class='nv'&gt;Body&lt;/span&gt;&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;So obviously we can respond in different ways to our different requests. Let&amp;#8217;s dig a little deeper and build out some controllers, an obvious enhancement. First, we&amp;#8217;ll modify our handle method:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='nf'&gt;handle&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Path&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Req&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class='nv'&gt;BaseController&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;lists&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;concat&lt;/span&gt;&lt;span class='p'&gt;([&lt;/span&gt;&lt;span class='n'&gt;top_level_request&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;clean_path&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Path&lt;/span&gt;&lt;span class='p'&gt;)),&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;_controller&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;]),&lt;/span&gt;
  &lt;span class='nv'&gt;CAtom&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nb'&gt;list_to_atom&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;BaseController&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt;
  &lt;span class='nv'&gt;ControllerPath&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;parse_controller_path&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;clean_path&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Path&lt;/span&gt;&lt;span class='p'&gt;)),&lt;/span&gt;
  
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nv'&gt;CAtom&lt;/span&gt; &lt;span class='k'&gt;of&lt;/span&gt;
    &lt;span class='n'&gt;home&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class='nv'&gt;IndexContents&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;?ERROR_HTML&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;Uh oh&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt;
      &lt;span class='nv'&gt;Req&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;ok&lt;/span&gt;&lt;span class='p'&gt;({&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;text/html&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;IndexContents&lt;/span&gt;&lt;span class='p'&gt;});&lt;/span&gt;
    &lt;span class='nv'&gt;ControllerAtom&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
    &lt;span class='nv'&gt;Meth&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;clean_method&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Req&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='nb'&gt;get&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;method&lt;/span&gt;&lt;span class='p'&gt;)),&lt;/span&gt;
    &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nv'&gt;Meth&lt;/span&gt; &lt;span class='k'&gt;of&lt;/span&gt;
      &lt;span class='nb'&gt;get&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
        &lt;span class='n'&gt;run_controller&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Req&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;ControllerAtom&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Meth&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;ControllerPath&lt;/span&gt;&lt;span class='p'&gt;]);&lt;/span&gt;
      &lt;span class='p'&gt;_&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
        &lt;span class='n'&gt;run_controller&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Req&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;ControllerAtom&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Meth&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;ControllerPath&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;decode_data_from_request&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Req&lt;/span&gt;&lt;span class='p'&gt;)])&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;

&lt;span class='c'&gt;% parse the controller path&lt;/span&gt;
&lt;span class='nf'&gt;parse_controller_path&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;CleanPath&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nn'&gt;string&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;tokens&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;CleanPath&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;/&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='k'&gt;of&lt;/span&gt;
    &lt;span class='p'&gt;[]&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='p'&gt;[];&lt;/span&gt;
    &lt;span class='p'&gt;[_&lt;/span&gt;&lt;span class='nv'&gt;RootPath&lt;/span&gt;&lt;span class='p'&gt;|&lt;/span&gt;&lt;span class='nv'&gt;Rest&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nv'&gt;Rest&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;
    
&lt;span class='c'&gt;% Call the controller action here&lt;/span&gt;
&lt;span class='nf'&gt;run_controller&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Req&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;ControllerAtom&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Meth&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Args&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;catch&lt;/span&gt; &lt;span class='nn'&gt;erlang&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='nb'&gt;apply&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;ControllerAtom&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Meth&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Args&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt; &lt;span class='k'&gt;of&lt;/span&gt;
    &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;&amp;#39;EXIT&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;undef&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;_}}&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nv'&gt;E&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class='nv'&gt;Req&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;ok&lt;/span&gt;&lt;span class='p'&gt;({&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;text/html&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;Unimplemented: there is nothing to see here&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;});&lt;/span&gt;
    &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;&amp;#39;EXIT&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;E&lt;/span&gt;&lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
      &lt;span class='nv'&gt;Req&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;not_found&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;
    &lt;span class='nv'&gt;Body&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
      &lt;span class='nv'&gt;Req&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;ok&lt;/span&gt;&lt;span class='p'&gt;({&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;text/html&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Body&lt;/span&gt;&lt;span class='p'&gt;})&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;

&lt;span class='c'&gt;% Other methods&lt;/span&gt;
&lt;span class='c'&gt;% Get the data off the request&lt;/span&gt;
&lt;span class='nf'&gt;decode_data_from_request&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Req&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class='nv'&gt;RecvBody&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nv'&gt;Req&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;recv_body&lt;/span&gt;&lt;span class='p'&gt;(),&lt;/span&gt;
  &lt;span class='nv'&gt;Data&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nv'&gt;RecvBody&lt;/span&gt; &lt;span class='k'&gt;of&lt;/span&gt;
    &lt;span class='o'&gt;&amp;lt;&amp;lt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nn'&gt;erlang&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='nb'&gt;list_to_binary&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;{}&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
    &lt;span class='nv'&gt;Bin&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nv'&gt;Bin&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
  &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;struct&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Struct&lt;/span&gt;&lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;mochijson2&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;decode&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Data&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt;
  &lt;span class='nv'&gt;Struct&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;

&lt;span class='c'&gt;% parse the controller path&lt;/span&gt;
&lt;span class='nf'&gt;parse_controller_path&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;CleanPath&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nn'&gt;string&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;tokens&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;CleanPath&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;/&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='k'&gt;of&lt;/span&gt;
    &lt;span class='p'&gt;[]&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='p'&gt;[];&lt;/span&gt;
    &lt;span class='p'&gt;[_&lt;/span&gt;&lt;span class='nv'&gt;RootPath&lt;/span&gt;&lt;span class='p'&gt;|&lt;/span&gt;&lt;span class='nv'&gt;Rest&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nv'&gt;Rest&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;

&lt;span class='c'&gt;% Get a clean path&lt;/span&gt;
&lt;span class='c'&gt;% strips off the query string&lt;/span&gt;
&lt;span class='nf'&gt;clean_path&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Path&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nn'&gt;string&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;str&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Path&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;?&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='k'&gt;of&lt;/span&gt;
    &lt;span class='mi'&gt;0&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nv'&gt;Path&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='nv'&gt;N&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nn'&gt;string&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;substr&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Path&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;N&lt;/span&gt; &lt;span class='o'&gt;-&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;

&lt;span class='nf'&gt;top_level_request&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Path&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nn'&gt;string&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;tokens&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Path&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;/&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='k'&gt;of&lt;/span&gt;
    &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;CleanPath&lt;/span&gt;&lt;span class='p'&gt;|_&lt;/span&gt;&lt;span class='nv'&gt;Others&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nv'&gt;CleanPath&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='p'&gt;[]&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;home&amp;quot;&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now we can use any controller with the path appended to call out to a controller of our choosing that respond to the four http methods, get, put, post and delete! To finish off, let&amp;#8217;s add a controller that responds with our hello world message:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='p'&gt;-&lt;/span&gt;&lt;span class='ni'&gt;module&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;home_controller&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;
&lt;span class='p'&gt;-&lt;/span&gt;&lt;span class='ni'&gt;export&lt;/span&gt; &lt;span class='p'&gt;([&lt;/span&gt;&lt;span class='nb'&gt;get&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;post&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;2&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nb'&gt;put&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;2&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;delete&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;2&lt;/span&gt;&lt;span class='p'&gt;]).&lt;/span&gt;

&lt;span class='nb'&gt;get&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Path&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;hello world&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;

&lt;span class='nf'&gt;post&lt;/span&gt;&lt;span class='p'&gt;(_&lt;/span&gt;&lt;span class='nv'&gt;Path&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;_&lt;/span&gt;&lt;span class='nv'&gt;Data&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;unhandled&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;
&lt;span class='nb'&gt;put&lt;/span&gt;&lt;span class='p'&gt;(_&lt;/span&gt;&lt;span class='nv'&gt;Path&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;_&lt;/span&gt;&lt;span class='nv'&gt;Data&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;unhandled&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;
&lt;span class='nf'&gt;delete&lt;/span&gt;&lt;span class='p'&gt;(_&lt;/span&gt;&lt;span class='nv'&gt;Path&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;_&lt;/span&gt;&lt;span class='nv'&gt;Data&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;unhandled&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now we have an application-scalable web framework written in erlang with mochiweb.&lt;/p&gt;

&lt;p&gt;This code can be retrieved at: &lt;a href='/code/erlang/rest_server.erl'&gt;/code/erlang/rest_server.erl&lt;/a&gt;.&lt;/p&gt;
&lt;b&gt;Thanks to damjan for pointing out the clean_path correction.&lt;/b&gt;</content>
    </entry>
  
    <entry>
      <title>Announcing Alice and Wonderland</title>
      <link href="http://willcodeforfoo.com/2009/07/13/announcing-alice"/>
      <updated>2009-07-13T00:00:00-07:00</updated>
      <id>http://willcodeforfoo.com/2009/07/13/announcing-alice</id>
      <content type="html">&lt;h2 id='alice'&gt;Alice&lt;/h2&gt;
&lt;p&gt;&lt;a href='http://alicetheapp.com'&gt;http://alicetheapp.com&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As a queue server, &lt;a href='http://www.rabbitmq.com/'&gt;RabbitMQ&lt;/a&gt; is super cool, but my company is hesitant to use it without a nice front-end or access to statistics about the server. So we set out to develop the latest RabbitMQ REST interface, &lt;a href='http://github.com/auser/alice'&gt;Alice&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Alice is a RESTful interface to the RabbitMQ server that talks directly through erlang&amp;#8217;s native interface, &lt;a href='http://www.erlang.org/doc/man/epmd.html'&gt;epmd&lt;/a&gt;. The purely &lt;a href='http://en.wikipedia.org/wiki/Representational_State_Transfer'&gt;RESTful&lt;/a&gt; server responds to the same interface as the RabbitMQ&amp;#8217;s command-line interface and presents a native HTTP interface to the data. &lt;a href='http://alicetheapp.com'&gt;Alice&lt;/a&gt; is written with &lt;a href='http://code.google.com/p/mochiweb/'&gt;Mochiweb&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id='quickstart'&gt;Quickstart&lt;/h2&gt;

&lt;p&gt;How to get started.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;git clone git://github.com/auser/alice.git
&lt;span class='nb'&gt;cd &lt;/span&gt;alice
./start.sh
&lt;/pre&gt;
&lt;/div&gt;
&lt;h4 id='currently_exposed_restful_routes'&gt;Currently exposed RESTful routes&lt;/h4&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;  /conn - Current connection information
  /exchanges - Current exchanges information
  /queues - Current queues
  /users - Current users
  /bindings - Current bindings
  /control - Access to the RabbitMQ control
  /permissions - Current permissions
  /vhosts - Current vhosts
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;These endpoints all are exposed with the four verbs (get, post, put, delete) and respond in the &lt;a href='http://www.json.org/'&gt;JSON&lt;/a&gt; format, (except the root / endpoint which responds with text/html).&lt;/p&gt;

&lt;h2 id='usage'&gt;Usage&lt;/h2&gt;

&lt;h4 id='users'&gt;Users&lt;/h4&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='c'&gt;# List users&lt;/span&gt;
curl -i http://localhost:9999/users 
HTTP/1.1 200 OK
Server: MochiWeb/1.0 &lt;span class='o'&gt;(&lt;/span&gt;Any of you quaids got a smint?&lt;span class='o'&gt;)&lt;/span&gt;
Date: Tue, 04 Aug 2009 07:08:20 GMT
Content-Type: text/json
Content-Length: 19

&lt;span class='o'&gt;{&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;users&amp;quot;&lt;/span&gt;:&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;guest&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;]}&lt;/span&gt;

&lt;span class='c'&gt;# Viewing a specific user&lt;/span&gt;
curl -i http://localhost:9999/users/guest
HTTP/1.1 200 OK
Server: MochiWeb/1.0 &lt;span class='o'&gt;(&lt;/span&gt;Any of you quaids got a smint?&lt;span class='o'&gt;)&lt;/span&gt;
Date: Tue, 04 Aug 2009 08:01:01 GMT
Content-Type: text/json
Content-Length: 17

&lt;span class='o'&gt;{&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;users&amp;quot;&lt;/span&gt;:&lt;span class='s2'&gt;&amp;quot;guest&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;}&lt;/span&gt;

&lt;span class='c'&gt;# If the user is not a user:&lt;/span&gt;
curl -i http://localhost:9999/users/bob  
HTTP/1.1 400 Bad Request
Server: MochiWeb/1.0 &lt;span class='o'&gt;(&lt;/span&gt;Any of you quaids got a smint?&lt;span class='o'&gt;)&lt;/span&gt;
Date: Tue, 04 Aug 2009 08:01:20 GMT
Content-Type: text/json
Content-Length: 20

&lt;span class='o'&gt;{&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;bob&amp;quot;&lt;/span&gt;:&lt;span class='s2'&gt;&amp;quot;not a user&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;}&lt;/span&gt;

&lt;span class='c'&gt;# Add a user&lt;/span&gt;
curl -i -XPOST &lt;span class='se'&gt;\&lt;/span&gt;
        -d&lt;span class='s1'&gt;&amp;#39;{&amp;quot;username&amp;quot;:&amp;quot;ari&amp;quot;, &amp;quot;password&amp;quot;:&amp;quot;weak password&amp;quot;}&amp;#39;&lt;/span&gt; &lt;span class='se'&gt;\&lt;/span&gt;
        http://localhost:9999/users
        
HTTP/1.1 200 OK
Server: MochiWeb/1.0 &lt;span class='o'&gt;(&lt;/span&gt;Any of you quaids got a smint?&lt;span class='o'&gt;)&lt;/span&gt;
Date: Thu, 16 Jul 2009 00:10:35 GMT
Content-Type: text/json
Content-Length: 25

&lt;span class='o'&gt;{&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;users&amp;quot;&lt;/span&gt;:&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;ari&amp;quot;&lt;/span&gt;,&lt;span class='s2'&gt;&amp;quot;guest&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;]}&lt;/span&gt;

&lt;span class='c'&gt;# Deleting a user&lt;/span&gt;
curl -i -XDELETE  http://localhost:9999/users/ari
HTTP/1.1 200 OK
Server: MochiWeb/1.0 &lt;span class='o'&gt;(&lt;/span&gt;Any of you quaids got a smint?&lt;span class='o'&gt;)&lt;/span&gt;
Date: Tue, 04 Aug 2009 07:19:24 GMT
Content-Type: text/json
Content-Length: 19

&lt;span class='o'&gt;{&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;users&amp;quot;&lt;/span&gt;:&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;guest&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;]}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Notice that when we list the user that doesn&amp;#8217;t exist, bob from the second example above, the return is a 400. This is especially useful when you want to access the data programmatically. More on extending Alice below and how to get access to the return value of the requested route.&lt;/p&gt;

&lt;p&gt;The same basic usage is applied to all the routes listed, as you can see:&lt;/p&gt;

&lt;h5 id='connections'&gt;Connections&lt;/h5&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='c'&gt;# List connections&lt;/span&gt;
curl -i http://localhost:9999/conn
HTTP/1.1 200 OK
Server: MochiWeb/1.0 &lt;span class='o'&gt;(&lt;/span&gt;Any of you quaids got a smint?&lt;span class='o'&gt;)&lt;/span&gt;
Date: Tue, 04 Aug 2009 07:30:52 GMT
Content-Type: text/json
Content-Length: 287

&lt;span class='o'&gt;{&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;conn&amp;quot;&lt;/span&gt;:&lt;span class='o'&gt;[{&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;pid&amp;quot;&lt;/span&gt;:&lt;span class='s2'&gt;&amp;quot;...&amp;quot;&lt;/span&gt;,&lt;span class='s2'&gt;&amp;quot;ip&amp;quot;&lt;/span&gt;:&lt;span class='s2'&gt;&amp;quot;127.0.0.1&amp;quot;&lt;/span&gt;,&lt;span class='s2'&gt;&amp;quot;port&amp;quot;&lt;/span&gt;:&lt;span class='s2'&gt;&amp;quot;5672&amp;quot;&lt;/span&gt;,&lt;span class='s2'&gt;&amp;quot;peer_address&amp;quot;&lt;/span&gt;:&lt;span class='s2'&gt;&amp;quot;127.0.0.1&amp;quot;&lt;/span&gt; ...&lt;span class='o'&gt;}]}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;h5 id='exchanges'&gt;Exchanges&lt;/h5&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='c'&gt;# List the current exchanges&lt;/span&gt;
curl -i http://localhost:9999/exchanges
HTTP/1.1 200 OK
Server: MochiWeb/1.0 &lt;span class='o'&gt;(&lt;/span&gt;Any of you quaids got a smint?&lt;span class='o'&gt;)&lt;/span&gt;
Date: Tue, 04 Aug 2009 07:34:14 GMT
Content-Type: text/json
Content-Length: 654

&lt;span class='o'&gt;{&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;exchanges&amp;quot;&lt;/span&gt;:&lt;span class='o'&gt;[{&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;name&amp;quot;&lt;/span&gt;:&lt;span class='s2'&gt;&amp;quot;amq.rabbitmq.log&amp;quot;&lt;/span&gt;,&lt;span class='s2'&gt;&amp;quot;type&amp;quot;&lt;/span&gt;:&lt;span class='s2'&gt;&amp;quot;topic&amp;quot;&lt;/span&gt;,&lt;span class='s2'&gt;&amp;quot;durable&amp;quot;&lt;/span&gt;:&lt;span class='s2'&gt;&amp;quot;true&amp;quot;&lt;/span&gt;,&lt;span class='s2'&gt;&amp;quot;auto_delete&amp;quot;&lt;/span&gt;:...&lt;span class='o'&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;h5 id='queues'&gt;Queues&lt;/h5&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='c'&gt;# List the current queues&lt;/span&gt;
curl -i http://localhost:9999/queues   
HTTP/1.1 200 OK
Server: MochiWeb/1.0 &lt;span class='o'&gt;(&lt;/span&gt;Any of you quaids got a smint?&lt;span class='o'&gt;)&lt;/span&gt;
Date: Tue, 04 Aug 2009 07:35:42 GMT
Content-Type: text/json
Content-Length: 60

&lt;span class='o'&gt;{&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;queues&amp;quot;&lt;/span&gt;:&lt;span class='o'&gt;[{&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;memory&amp;quot;&lt;/span&gt;:&lt;span class='s2'&gt;&amp;quot;212988&amp;quot;&lt;/span&gt;,&lt;span class='s2'&gt;&amp;quot;name&amp;quot;&lt;/span&gt;:&lt;span class='s2'&gt;&amp;quot;noises&amp;quot;&lt;/span&gt;,&lt;span class='s2'&gt;&amp;quot;vhost&amp;quot;&lt;/span&gt;:&lt;span class='s2'&gt;&amp;quot;/&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;}]}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;h5 id='bindings'&gt;Bindings&lt;/h5&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='c'&gt;# List the current bindings&lt;/span&gt;
curl -i http://localhost:9999/bindings
HTTP/1.1 200 OK
Server: MochiWeb/1.0 &lt;span class='o'&gt;(&lt;/span&gt;Any of you quaids got a smint?&lt;span class='o'&gt;)&lt;/span&gt;
Date: Tue, 04 Aug 2009 07:36:13 GMT
Content-Type: text/json
Content-Length: 69

&lt;span class='o'&gt;{&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;bindings&amp;quot;&lt;/span&gt;:&lt;span class='o'&gt;[{&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;queue&amp;quot;&lt;/span&gt;:&lt;span class='s2'&gt;&amp;quot;noises&amp;quot;&lt;/span&gt;,&lt;span class='s2'&gt;&amp;quot;exchange&amp;quot;&lt;/span&gt;:&lt;span class='s2'&gt;&amp;quot;&amp;quot;&lt;/span&gt;,&lt;span class='s2'&gt;&amp;quot;from_queue&amp;quot;&lt;/span&gt;:&lt;span class='s2'&gt;&amp;quot;noises&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;}]}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;h5 id='permissions'&gt;Permissions&lt;/h5&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='c'&gt;# List permissions&lt;/span&gt;
curl -i http://localhost:9999/permissions
HTTP/1.1 200 OK
Server: MochiWeb/1.0 &lt;span class='o'&gt;(&lt;/span&gt;Any of you quaids got a smint?&lt;span class='o'&gt;)&lt;/span&gt;
Date: Tue, 04 Aug 2009 07:37:32 GMT
Content-Type: text/json
Content-Length: 42

&lt;span class='o'&gt;{&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;permissions&amp;quot;&lt;/span&gt;:&lt;span class='o'&gt;[[&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;guest&amp;quot;&lt;/span&gt;,&lt;span class='s2'&gt;&amp;quot;.*&amp;quot;&lt;/span&gt;,&lt;span class='s2'&gt;&amp;quot;.*&amp;quot;&lt;/span&gt;,&lt;span class='s2'&gt;&amp;quot;.*&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;]]}&lt;/span&gt;

&lt;span class='c'&gt;# You can specify permissions on a vhost&lt;/span&gt;
curl -i http://localhost:9999/permissions/vhost/root
HTTP/1.1 200 OK
Server: MochiWeb/1.0 &lt;span class='o'&gt;(&lt;/span&gt;Any of you quaids got a smint?&lt;span class='o'&gt;)&lt;/span&gt;
Date: Tue, 04 Aug 2009 07:50:33 GMT
Content-Type: text/json
Content-Length: 42

&lt;span class='o'&gt;{&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;permissions&amp;quot;&lt;/span&gt;:&lt;span class='o'&gt;[[&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;guest&amp;quot;&lt;/span&gt;,&lt;span class='s2'&gt;&amp;quot;.*&amp;quot;&lt;/span&gt;,&lt;span class='s2'&gt;&amp;quot;.*&amp;quot;&lt;/span&gt;,&lt;span class='s2'&gt;&amp;quot;.*&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;]]}&lt;/span&gt;
&lt;span class='c'&gt;# Setting permissions&lt;/span&gt;
curl -i -XPOST -d &lt;span class='s1'&gt;&amp;#39;{&amp;quot;vhost&amp;quot;:&amp;quot;/&amp;quot;, &amp;quot;configure&amp;quot;:&amp;quot;.*&amp;quot;, &amp;quot;read&amp;quot;:&amp;quot;.*&amp;quot;, &amp;quot;write&amp;quot;:&amp;quot;.*&amp;quot;}&amp;#39;&lt;/span&gt; &lt;span class='se'&gt;\&lt;/span&gt;
  http://localhost:9999/permissions/guest
HTTP/1.1 200 OK
Server: MochiWeb/1.0 &lt;span class='o'&gt;(&lt;/span&gt;Any of you quaids got a smint?&lt;span class='o'&gt;)&lt;/span&gt;
Date: Tue, 04 Aug 2009 07:55:33 GMT
Content-Type: text/json
Content-Length: 38

&lt;span class='o'&gt;{&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;permissions&amp;quot;&lt;/span&gt;:&lt;span class='o'&gt;[[&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;/&amp;quot;&lt;/span&gt;,&lt;span class='s2'&gt;&amp;quot;.*&amp;quot;&lt;/span&gt;,&lt;span class='s2'&gt;&amp;quot;.*&amp;quot;&lt;/span&gt;,&lt;span class='s2'&gt;&amp;quot;.*&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;]]}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;h5 id='vhosts'&gt;Vhosts&lt;/h5&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='c'&gt;# List vhosts&lt;/span&gt;
curl -i http://localhost:9999/vhostsHTTP/1.1 200 OK
Server: MochiWeb/1.0 &lt;span class='o'&gt;(&lt;/span&gt;Any of you quaids got a smint?&lt;span class='o'&gt;)&lt;/span&gt;
Date: Tue, 04 Aug 2009 07:57:10 GMT
Content-Type: text/json
Content-Length: 16

&lt;span class='o'&gt;{&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;vhosts&amp;quot;&lt;/span&gt;:&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;/&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;]}&lt;/span&gt;

&lt;span class='c'&gt;# Viewing a specific vhost&lt;/span&gt;
curl -i http://localhost:9999/vhosts/barneys%20list
HTTP/1.1 200 OK
Server: MochiWeb/1.0 &lt;span class='o'&gt;(&lt;/span&gt;Any of you quaids got a smint?&lt;span class='o'&gt;)&lt;/span&gt;
Date: Tue, 04 Aug 2009 07:59:29 GMT
Content-Type: text/json
Content-Length: 25

&lt;span class='o'&gt;{&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;vhosts&amp;quot;&lt;/span&gt;:&lt;span class='s2'&gt;&amp;quot;barneys list&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;}&lt;/span&gt;

&lt;span class='c'&gt;# If it doesn&amp;#39;t exist:&lt;/span&gt;
curl -i http://localhost:9999/vhosts/barneys%20listings
HTTP/1.1 400 Bad Request
Server: MochiWeb/1.0 &lt;span class='o'&gt;(&lt;/span&gt;Any of you quaids got a smint?&lt;span class='o'&gt;)&lt;/span&gt;
Date: Tue, 04 Aug 2009 07:59:59 GMT
Content-Type: text/json
Content-Length: 34

&lt;span class='o'&gt;{&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;barneys listings&amp;quot;&lt;/span&gt;:&lt;span class='s2'&gt;&amp;quot;not a vhost&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;}&lt;/span&gt;

&lt;span class='c'&gt;# Add a vhost&lt;/span&gt;
curl -i http://localhost:9999/vhosts -XPOST -d&lt;span class='s1'&gt;&amp;#39;{&amp;quot;name&amp;quot;:&amp;quot;barneys list&amp;quot;}&amp;#39;&lt;/span&gt;
HTTP/1.1 200 OK
Server: MochiWeb/1.0 &lt;span class='o'&gt;(&lt;/span&gt;Any of you quaids got a smint?&lt;span class='o'&gt;)&lt;/span&gt;
Date: Tue, 04 Aug 2009 07:58:09 GMT
Content-Type: text/json
Content-Length: 31

&lt;span class='o'&gt;{&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;vhosts&amp;quot;&lt;/span&gt;:&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;/&amp;quot;&lt;/span&gt;,&lt;span class='s2'&gt;&amp;quot;barneys list&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;]}&lt;/span&gt;

&lt;span class='c'&gt;# Delete a vhost&lt;/span&gt;
curl -XDELETE -i http://localhost:9999/vhosts/barneys%20list
HTTP/1.1 200 OK
Server: MochiWeb/1.0 &lt;span class='o'&gt;(&lt;/span&gt;Any of you quaids got a smint?&lt;span class='o'&gt;)&lt;/span&gt;
Date: Tue, 04 Aug 2009 08:02:44 GMT
Content-Type: text/json
Content-Length: 16

&lt;span class='o'&gt;{&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;vhosts&amp;quot;&lt;/span&gt;:&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;/&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;]}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now, there is a module in the Alice called control. There are a lot of routes and a lot of functionality built-in here, so let&amp;#8217;s dig in.&lt;/p&gt;

&lt;h3 id='control'&gt;Control&lt;/h3&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='c'&gt;# Getting the status of the server&lt;/span&gt;
curl -i http://localhost:9999/control 
HTTP/1.1 200 OK
Server: MochiWeb/1.0 &lt;span class='o'&gt;(&lt;/span&gt;Any of you quaids got a smint?&lt;span class='o'&gt;)&lt;/span&gt;
Date: Tue, 04 Aug 2009 08:05:19 GMT
Content-Type: text/json
Content-Length: 151

&lt;span class='o'&gt;{&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;status&amp;quot;&lt;/span&gt;:&lt;span class='o'&gt;[{&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;applications&amp;quot;&lt;/span&gt;:&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;rabbit&amp;quot;&lt;/span&gt;,&lt;span class='s2'&gt;&amp;quot;mnesia&amp;quot;&lt;/span&gt;,&lt;span class='s2'&gt;&amp;quot;os_mon&amp;quot;&lt;/span&gt;,&lt;span class='s2'&gt;&amp;quot;sasl&amp;quot;&lt;/span&gt;,&lt;span class='s2'&gt;&amp;quot;stdlib&amp;quot;&lt;/span&gt;,&lt;span class='s2'&gt;&amp;quot;kernel&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;, &lt;span class='se'&gt;\&lt;/span&gt;
&lt;span class='s2'&gt;&amp;quot;nodes&amp;quot;&lt;/span&gt;:&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;rabbit@YPCMC05591&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;,&lt;span class='s2'&gt;&amp;quot;running_nodes&amp;quot;&lt;/span&gt;:&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;rabbit@YPCMC05591&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;]}]}&lt;/span&gt;

&lt;span class='c'&gt;# Stopping the rabbitmq-server&lt;/span&gt;
curl -XPOST -i http://localhost:9999/control/stop  
HTTP/1.1 200 OK
Server: MochiWeb/1.0 &lt;span class='o'&gt;(&lt;/span&gt;Any of you quaids got a smint?&lt;span class='o'&gt;)&lt;/span&gt;
Date: Tue, 04 Aug 2009 08:06:02 GMT
Content-Type: text/json
Content-Length: 20

&lt;span class='o'&gt;{&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;status&amp;quot;&lt;/span&gt;:&lt;span class='s2'&gt;&amp;quot;stopped&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;}&lt;/span&gt;

&lt;span class='c'&gt;# Starting the rabbitmq-server application&lt;/span&gt;
curl -XPOST -i http://localhost:9999/control/start_app
HTTP/1.1 200 OK
Server: MochiWeb/1.0 &lt;span class='o'&gt;(&lt;/span&gt;Any of you quaids got a smint?&lt;span class='o'&gt;)&lt;/span&gt;
Date: Tue, 04 Aug 2009 08:06:50 GMT
Content-Type: text/json
Content-Length: 20

&lt;span class='o'&gt;{&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;status&amp;quot;&lt;/span&gt;:&lt;span class='s2'&gt;&amp;quot;started&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;}&lt;/span&gt;

&lt;span class='c'&gt;# Stopping the rabbitmq-server application&lt;/span&gt;
curl -XDELETE -i http://localhost:9999/control/stop_app
HTTP/1.1 200 OK
Server: MochiWeb/1.0 &lt;span class='o'&gt;(&lt;/span&gt;Any of you quaids got a smint?&lt;span class='o'&gt;)&lt;/span&gt;
Date: Tue, 04 Aug 2009 08:15:56 GMT
Content-Type: text/json
Content-Length: 20

&lt;span class='o'&gt;{&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;status&amp;quot;&lt;/span&gt;:&lt;span class='s2'&gt;&amp;quot;stopped&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;}&lt;/span&gt;

&lt;span class='c'&gt;# Reset the rabbitmq-server application&lt;/span&gt;
curl -XPOST -i http://localhost:9999/control/reset    
HTTP/1.1 200 OK
Server: MochiWeb/1.0 &lt;span class='o'&gt;(&lt;/span&gt;Any of you quaids got a smint?&lt;span class='o'&gt;)&lt;/span&gt;
Date: Tue, 04 Aug 2009 08:07:15 GMT
Content-Type: text/json
Content-Length: 18

&lt;span class='o'&gt;{&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;status&amp;quot;&lt;/span&gt;:&lt;span class='s2'&gt;&amp;quot;reset&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;}&lt;/span&gt;

&lt;span class='c'&gt;# Or force-resetting the server&lt;/span&gt;
curl -XPOST -i http://localhost:9999/control/force_reset
HTTP/1.1 200 OK
Server: MochiWeb/1.0 &lt;span class='o'&gt;(&lt;/span&gt;Any of you quaids got a smint?&lt;span class='o'&gt;)&lt;/span&gt;
Date: Tue, 04 Aug 2009 08:07:27 GMT
Content-Type: text/json
Content-Length: 18

&lt;span class='o'&gt;{&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;status&amp;quot;&lt;/span&gt;:&lt;span class='s2'&gt;&amp;quot;reset&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;}&lt;/span&gt;

&lt;span class='c'&gt;# Clustering a set of nodes&lt;/span&gt;
curl -XPOST -i http://localhost:9999/control/cluster -d&lt;span class='s1'&gt;&amp;#39;{&amp;quot;nodes&amp;quot;:[&amp;quot;bob@otherhost&amp;quot;]}&amp;#39;&lt;/span&gt;
HTTP/1.1 200 OK
Server: MochiWeb/1.0 &lt;span class='o'&gt;(&lt;/span&gt;Any of you quaids got a smint?&lt;span class='o'&gt;)&lt;/span&gt;
Date: Tue, 04 Aug 2009 08:14:10 GMT
Content-Type: text/json
Content-Length: 20

&lt;span class='o'&gt;{&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;status&amp;quot;&lt;/span&gt;:&lt;span class='s2'&gt;&amp;quot;cluster&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;}&lt;/span&gt;

&lt;span class='c'&gt;# Rotating rabbit logs&lt;/span&gt;
curl -XPOST -i http://localhost:9999/control/rotate_logs -d&lt;span class='s1'&gt;&amp;#39;{&amp;quot;prefix&amp;quot;:&amp;quot;mn_&amp;quot;}&amp;#39;&lt;/span&gt;
HTTP/1.1 200 OK
Server: MochiWeb/1.0 &lt;span class='o'&gt;(&lt;/span&gt;Any of you quaids got a smint?&lt;span class='o'&gt;)&lt;/span&gt;
Date: Tue, 04 Aug 2009 08:15:12 GMT
Content-Type: text/json
Content-Length: 25

&lt;span class='o'&gt;{&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;status&amp;quot;&lt;/span&gt;:&lt;span class='s2'&gt;&amp;quot;rotated_logs&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;h4 id='extending'&gt;Extending&lt;/h4&gt;

&lt;p&gt;Alice is written with the intention of being highly extensible and makes it easy to do so. The controllers respond only to the four verbs with pattern-matching on the routes.&lt;/p&gt;

&lt;p&gt;For instance, a very basic controller looks like this:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='p'&gt;-&lt;/span&gt;&lt;span class='ni'&gt;module&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;say&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;
&lt;span class='p'&gt;-&lt;/span&gt;&lt;span class='ni'&gt;export&lt;/span&gt; &lt;span class='p'&gt;([&lt;/span&gt;&lt;span class='nb'&gt;get&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;post&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;2&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nb'&gt;put&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;2&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;delete&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;2&lt;/span&gt;&lt;span class='p'&gt;]).&lt;/span&gt;

&lt;span class='nb'&gt;get&lt;/span&gt;&lt;span class='p'&gt;([])&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;hello&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;world&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class='p'&gt;};&lt;/span&gt;
&lt;span class='nb'&gt;get&lt;/span&gt;&lt;span class='p'&gt;(_&lt;/span&gt;&lt;span class='nv'&gt;Path&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;error&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;unhandled&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class='p'&gt;}.&lt;/span&gt;

&lt;span class='nf'&gt;post&lt;/span&gt;&lt;span class='p'&gt;(_&lt;/span&gt;&lt;span class='nv'&gt;Path&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;_&lt;/span&gt;&lt;span class='nv'&gt;Data&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;error&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;unhandled&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class='p'&gt;}.&lt;/span&gt;
&lt;span class='nb'&gt;put&lt;/span&gt;&lt;span class='p'&gt;(_&lt;/span&gt;&lt;span class='nv'&gt;Path&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;_&lt;/span&gt;&lt;span class='nv'&gt;Data&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;error&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;unhandled&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class='p'&gt;}.&lt;/span&gt;
&lt;span class='nf'&gt;delete&lt;/span&gt;&lt;span class='p'&gt;(_&lt;/span&gt;&lt;span class='nv'&gt;Path&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;_&lt;/span&gt;&lt;span class='nv'&gt;Data&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;error&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;unhandled&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class='p'&gt;}.&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;There are the 4 RESTful verbs that the controller responds. Now, if you were to compile this in Alice (in src/rest_server/controllers), then the route http://localhost:9999/say would now be accessible. Cool!&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;curl -i http://localhost:9999/say
HTTP/1.1 200 OK
Server: MochiWeb/1.0 &lt;span class='o'&gt;(&lt;/span&gt;Any of you quaids got a smint?&lt;span class='o'&gt;)&lt;/span&gt;
Date: Tue, 04 Aug 2009 08:20:57 GMT
Content-Type: text/json
Content-Length: 17

&lt;span class='o'&gt;{&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;hello&amp;quot;&lt;/span&gt;:&lt;span class='s2'&gt;&amp;quot;world&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now let&amp;#8217;s add a route to say hello to someone:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='p'&gt;-&lt;/span&gt;&lt;span class='ni'&gt;module&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;say&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;
&lt;span class='p'&gt;-&lt;/span&gt;&lt;span class='ni'&gt;export&lt;/span&gt; &lt;span class='p'&gt;([&lt;/span&gt;&lt;span class='nb'&gt;get&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;post&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;2&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nb'&gt;put&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;2&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;delete&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;2&lt;/span&gt;&lt;span class='p'&gt;]).&lt;/span&gt;

&lt;span class='nb'&gt;get&lt;/span&gt;&lt;span class='p'&gt;([&lt;/span&gt;&lt;span class='nv'&gt;Name&lt;/span&gt;&lt;span class='p'&gt;])&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;hello&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nn'&gt;erlang&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='nb'&gt;list_to_binary&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Name&lt;/span&gt;&lt;span class='p'&gt;)};&lt;/span&gt;
&lt;span class='nb'&gt;get&lt;/span&gt;&lt;span class='p'&gt;([])&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;hello&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;world&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class='p'&gt;};&lt;/span&gt;
&lt;span class='c'&gt;% ....&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;curl -i http://localhost:9999/say/ari
HTTP/1.1 200 OK
Server: MochiWeb/1.0 &lt;span class='o'&gt;(&lt;/span&gt;Any of you quaids got a smint?&lt;span class='o'&gt;)&lt;/span&gt;
Date: Tue, 04 Aug 2009 08:21:54 GMT
Content-Type: text/json
Content-Length: 15

&lt;span class='o'&gt;{&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;hello&amp;quot;&lt;/span&gt;:&lt;span class='s2'&gt;&amp;quot;ari&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Finally, with every other verb than get, we are given data to extract. Let&amp;#8217;s see how to pull some data in a post. The data is given as a proplist with binary keys, we it&amp;#8217;s pretty easy to pull them out:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='c'&gt;% ...&lt;/span&gt;
&lt;span class='nf'&gt;post&lt;/span&gt;&lt;span class='p'&gt;([],&lt;/span&gt; &lt;span class='nv'&gt;Data&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class='nv'&gt;Name&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;erlang&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='nb'&gt;binary_to_list&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nn'&gt;proplists&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;get_value&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Data&lt;/span&gt;&lt;span class='p'&gt;)),&lt;/span&gt;
  &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;hello back&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nn'&gt;erlang&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='nb'&gt;list_to_binary&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Name&lt;/span&gt;&lt;span class='p'&gt;)};&lt;/span&gt;
&lt;span class='nf'&gt;post&lt;/span&gt;&lt;span class='p'&gt;([])&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
&lt;span class='c'&gt;% ...&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Let&amp;#8217;s check it:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;curl -i http://localhost:9999/say -XPOST -d&lt;span class='s1'&gt;&amp;#39;{&amp;quot;name&amp;quot;:&amp;quot;ari&amp;quot;}&amp;#39;&lt;/span&gt;
HTTP/1.1 200 OK
Server: MochiWeb/1.0 &lt;span class='o'&gt;(&lt;/span&gt;Any of you quaids got a smint?&lt;span class='o'&gt;)&lt;/span&gt;
Date: Tue, 04 Aug 2009 08:23:54 GMT
Content-Type: text/json
Content-Length: 20

&lt;span class='o'&gt;{&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;hello back&amp;quot;&lt;/span&gt;:&lt;span class='s2'&gt;&amp;quot;ari&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;It&amp;#8217;s as easy as pie to extend Alice.&lt;/p&gt;

&lt;h2 id='wonderland'&gt;Wonderland&lt;/h2&gt;

&lt;p&gt;Wonderland is the webUI to Alice. It is driven by the javascript framework &lt;a href='http://code.quirkey.com/sammy'&gt;Sammy&lt;/a&gt; and Alice in the backend. Because the framework is client-side and accesses the data through &lt;a href='http://en.wikipedia.org/wiki/Ajax_(programming)'&gt;ajax&lt;/a&gt;, Wonderland can be deployed nearly anywhere.&lt;/p&gt;

&lt;h2 id='quickstart'&gt;Quickstart&lt;/h2&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='nb'&gt;cd &lt;/span&gt;alice
make wonderland
&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='screenshots'&gt;Screenshots:&lt;/h2&gt;
&lt;div class='gallery'&gt;
	&lt;ul&gt;
    	&lt;li&gt;
      	&lt;a href='/images/screenshots/wonderland/home.png' title='Home'&gt;
          	&lt;img src='/images/screenshots/wonderland/home.png' height='90' alt='' width='120' /&gt;
          &lt;/a&gt;
      &lt;/li&gt;
      &lt;li&gt;
      	&lt;a href='/images/screenshots/wonderland/add_user.png' title='Add a user'&gt;
          	&lt;img src='/images/screenshots/wonderland/add_user.png' height='90' alt='' width='120' /&gt;
          &lt;/a&gt;
      &lt;/li&gt;
      &lt;li&gt;
      	&lt;a href='/images/screenshots/wonderland/conn.png' title='Current connections'&gt;
          	&lt;img src='/images/screenshots/wonderland/conn.png' height='90' alt='' width='120' /&gt;
          &lt;/a&gt;
      &lt;/li&gt;
      &lt;li&gt;
      	&lt;a href='/images/screenshots/wonderland/exchanges.png' title='Listing exchanges'&gt;
          	&lt;img src='/images/screenshots/wonderland/exchanges.png' height='90' alt='' width='120' /&gt;
          &lt;/a&gt;
      &lt;/li&gt;
      &lt;li&gt;
      	&lt;a href='/images/screenshots/wonderland/queues.png' title='Listing the queues'&gt;
          	&lt;img src='/images/screenshots/wonderland/queues.png' height='90' alt='' width='120' /&gt;
          &lt;/a&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
&lt;/div&gt;
&lt;p&gt;Check these two projects out on github at:&lt;br /&gt; &lt;a href='http://github.com/auser/alice'&gt;http://github.com/auser/alice&lt;/a&gt;&lt;br /&gt; &lt;a href='http://github.com/auser/wonderland'&gt;http://github.com/auser/wonderland&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id='community'&gt;Community&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href='http://github.com/auser/alice/issues'&gt;Issue tracker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href='http://groups.google.com/group/alice-and-wonderland?lnk=gcimv'&gt;Google group&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href='irc://irc.freenode.net#poolpartyrb'&gt;irc: irc.freenode.net / #poolpartyrb &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Or feel free to ping me on email (arilerner dot mac dot com) if you have any questions.&lt;/p&gt;

&lt;p&gt;Alice, the app &lt;a href='http://alicetheapp.com'&gt;http://alicetheapp.com&lt;/a&gt;&lt;/p&gt;</content>
    </entry>
  
    <entry>
      <title>Makefiles making erlang easy</title>
      <link href="http://willcodeforfoo.com/2009/07/10/erlang-makefile"/>
      <updated>2009-07-10T00:00:00-07:00</updated>
      <id>http://willcodeforfoo.com/2009/07/10/erlang-makefile</id>
      <content type="html">&lt;p&gt;Update (01/04/2010): Added a github repos with a project template for starting new projects here: &lt;a href='http://github.com/auser/erlproject_template'&gt;http://github.com/auser/erlproject_template&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The Rakefile in a ruby project is almost just as important as the code itself. Ask any rubyish to show you their project and you can bet your bottom dollar that nine out of every 10 projects of theirs has a Rakefile (most of the time, it&amp;#8217;s 10/10). This is one thing that can make starting an erlang project painful&amp;#8230; the Makefile (bum bum buuuummmm). Today, I&amp;#8217;ll share a Makefile (for my own future reference too!) that works really well for me and my projects.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve attached a sample project directory to get started (for the impatient, you can them &lt;a href='/code/erlang/makefile.zip'&gt; here&lt;/a&gt; if you&amp;#8217;d like to follow along). It includes a sample application file, a sample gen_server and of course all the files in this post. Let&amp;#8217;s get started:&lt;/p&gt;

&lt;p&gt;First, the Makefile:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='c'&gt;# Makefile&lt;/span&gt;
&lt;span class='nv'&gt;LIBDIR&lt;/span&gt;		&lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='sb'&gt;`&lt;/span&gt;erl -eval &lt;span class='se'&gt;\&lt;/span&gt;
  &lt;span class='s1'&gt;&amp;#39;io:format(&amp;quot;~s~n&amp;quot;, [code:lib_dir()])&amp;#39;&lt;/span&gt; -s init stop -noshell&lt;span class='sb'&gt;`&lt;/span&gt;
&lt;span class='nv'&gt;VERSION&lt;/span&gt;		&lt;span class='o'&gt;=&lt;/span&gt; 0.0.1
&lt;span class='nv'&gt;CC&lt;/span&gt;  			&lt;span class='o'&gt;=&lt;/span&gt; erlc
&lt;span class='nv'&gt;ERL&lt;/span&gt;     	&lt;span class='o'&gt;=&lt;/span&gt; erl
&lt;span class='nv'&gt;EBIN&lt;/span&gt;			&lt;span class='o'&gt;=&lt;/span&gt; ebin
&lt;span class='nv'&gt;CFLAGS&lt;/span&gt;  	&lt;span class='o'&gt;=&lt;/span&gt; -I include -pa &lt;span class='k'&gt;$(&lt;/span&gt;EBIN&lt;span class='k'&gt;)&lt;/span&gt;
&lt;span class='nv'&gt;COMPILE&lt;/span&gt;		&lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;$(&lt;/span&gt;CC&lt;span class='k'&gt;)&lt;/span&gt; &lt;span class='k'&gt;$(&lt;/span&gt;CFLAGS&lt;span class='k'&gt;)&lt;/span&gt; -o &lt;span class='k'&gt;$(&lt;/span&gt;EBIN&lt;span class='k'&gt;)&lt;/span&gt;
&lt;span class='nv'&gt;EBIN_DIRS&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;$(&lt;/span&gt;wildcard deps/*/ebin&lt;span class='k'&gt;)&lt;/span&gt;

all: mochi ebin compile
all_boot: all make_boot
start: all start_all

mochi:
  @&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;cd &lt;/span&gt;deps/mochiweb;&lt;span class='k'&gt;$(&lt;/span&gt;MAKE&lt;span class='k'&gt;)&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;

compile:
  @&lt;span class='k'&gt;$(&lt;/span&gt;ERL&lt;span class='k'&gt;)&lt;/span&gt; -pa &lt;span class='k'&gt;$(&lt;/span&gt;EBIN_DIRS&lt;span class='k'&gt;)&lt;/span&gt; -noinput +B &lt;span class='se'&gt;\&lt;/span&gt;
  -eval &lt;span class='s1'&gt;&amp;#39;case make:all() of up_to_date -&amp;gt; halt(0); \&lt;/span&gt;
&lt;span class='s1'&gt;        error -&amp;gt; halt(1) end.&amp;#39;&lt;/span&gt;

edoc:
  @echo Generating &lt;span class='k'&gt;$(&lt;/span&gt;APP&lt;span class='k'&gt;)&lt;/span&gt; documentation from srcs
  @erl -noinput -eval &lt;span class='s1'&gt;&amp;#39;edoc:application($(APP), &amp;quot;./&amp;quot;, \&lt;/span&gt;
&lt;span class='s1'&gt;        [{doc, &amp;quot;doc/&amp;quot;}, {files, &amp;quot;src/&amp;quot;}])&amp;#39;&lt;/span&gt; -s erlang halt
  
make_boot:
  &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;cd &lt;/span&gt;ebin; erl -pa ebin -noshell &lt;span class='se'&gt;\&lt;/span&gt;
    -run make_boot write_scripts rest_app&lt;span class='o'&gt;)&lt;/span&gt;

start_all:
  &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;cd &lt;/span&gt;ebin; erl -pa ebin -noshell -sname _name_ -boot _name_&lt;span class='o'&gt;)&lt;/span&gt;

ebin:
  @mkdir ebin

clean:
  rm -rf ebin/*.beam ebin/erl_crash.dump erl_crash.dump
  rm -rf ebin/*.boot ebin/*.rel ebin/*.script
  rm -rf doc/*.html doc/*.css doc/erlang.png doc/edoc-info
  
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This particular project (not yet announced) uses mochiweb (and it&amp;#8217;s a good example to show dependencies, so I left it), so we have a task called mochi so that we compile all of the mochiweb sources. Before showing the EMakefile, which is what drives the compile task, it&amp;#8217;s important to note that there is also a make_boot task that creates a boot file for the project. This is pretty interesting, so we&amp;#8217;ll dive into that real quick:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='c'&gt;% make_boot.erl&lt;/span&gt;
&lt;span class='p'&gt;-&lt;/span&gt;&lt;span class='ni'&gt;module&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;make_boot&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;
&lt;span class='p'&gt;-&lt;/span&gt;&lt;span class='ni'&gt;export&lt;/span&gt;&lt;span class='p'&gt;([&lt;/span&gt;&lt;span class='n'&gt;write_scripts&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;]).&lt;/span&gt;

&lt;span class='nf'&gt;write_scripts&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Args&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
  &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;Name&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nv'&gt;Args&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
  &lt;span class='nn'&gt;io&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;format&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;write_scripts for &lt;/span&gt;&lt;span class='si'&gt;~p~n&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;Name&lt;/span&gt;&lt;span class='p'&gt;]),&lt;/span&gt;
  &lt;span class='nv'&gt;Erts&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;erlang&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='nb'&gt;system_info&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;version&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt;
  &lt;span class='nn'&gt;application&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;load&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;sasl&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt;
  &lt;span class='nv'&gt;Version&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;0.1&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
  &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;value&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;kernel&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;_,&lt;/span&gt; &lt;span class='nv'&gt;Kernel&lt;/span&gt;&lt;span class='p'&gt;}}&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;lists&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;keysearch&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;kernel&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
    &lt;span class='nn'&gt;application&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;loaded_applications&lt;/span&gt;&lt;span class='p'&gt;()),&lt;/span&gt;
  &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;value&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;stdlib&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;_,&lt;/span&gt; &lt;span class='nv'&gt;Stdlib&lt;/span&gt;&lt;span class='p'&gt;}}&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;lists&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;keysearch&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;stdlib&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
    &lt;span class='nn'&gt;application&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;loaded_applications&lt;/span&gt;&lt;span class='p'&gt;()),&lt;/span&gt;
  &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;value&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;sasl&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;_,&lt;/span&gt; &lt;span class='nv'&gt;Sasl&lt;/span&gt;&lt;span class='p'&gt;}}&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;lists&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;keysearch&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;sasl&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
    &lt;span class='nn'&gt;application&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;loaded_applications&lt;/span&gt;&lt;span class='p'&gt;()),&lt;/span&gt;

  &lt;span class='nv'&gt;Rel&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;{release, {\&amp;quot;&lt;/span&gt;&lt;span class='err'&gt;~&lt;/span&gt;&lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='err'&gt;\&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;, \&amp;quot;&lt;/span&gt;&lt;span class='err'&gt;~&lt;/span&gt;&lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='err'&gt;\&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;}, {erts, \&amp;quot;&lt;/span&gt;&lt;span class='err'&gt;~&lt;/span&gt;&lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='err'&gt;\&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;}, [&amp;quot;&lt;/span&gt;
          &lt;span class='s'&gt;&amp;quot;{kernel, \&amp;quot;&lt;/span&gt;&lt;span class='err'&gt;~&lt;/span&gt;&lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='err'&gt;\&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;}, {stdlib, \&amp;quot;&lt;/span&gt;&lt;span class='err'&gt;~&lt;/span&gt;&lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='err'&gt;\&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;}, &lt;/span&gt;
&lt;span class='s'&gt;          {sasl, \&amp;quot;&lt;/span&gt;&lt;span class='err'&gt;~&lt;/span&gt;&lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='err'&gt;\&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;}, {&lt;/span&gt;&lt;span class='si'&gt;~s&lt;/span&gt;&lt;span class='s'&gt;, \&amp;quot;&lt;/span&gt;&lt;span class='err'&gt;~&lt;/span&gt;&lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='err'&gt;\&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;}]}.&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
  
  &lt;span class='nv'&gt;Lowername&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;string&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;to_lower&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Name&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt;

  &lt;span class='nv'&gt;Filename&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;lists&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;flatten&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Lowername&lt;/span&gt; &lt;span class='o'&gt;++&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;.rel&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt;
  &lt;span class='nn'&gt;io&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;format&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;Writing to &lt;/span&gt;&lt;span class='si'&gt;~p&lt;/span&gt;&lt;span class='s'&gt; (as &lt;/span&gt;&lt;span class='si'&gt;~s&lt;/span&gt;&lt;span class='s'&gt;)&lt;/span&gt;&lt;span class='si'&gt;~n&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;Filename&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Lowername&lt;/span&gt;&lt;span class='p'&gt;]),&lt;/span&gt;
  &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;ok&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Fs&lt;/span&gt;&lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;file&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;open&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Filename&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;write&lt;/span&gt;&lt;span class='p'&gt;]),&lt;/span&gt;

  &lt;span class='nn'&gt;io&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;format&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Fs&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;Rel&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;Name&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; 
                      &lt;span class='nv'&gt;Version&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; 
                      &lt;span class='nv'&gt;Erts&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; 
                      &lt;span class='nv'&gt;Kernel&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; 
                      &lt;span class='nv'&gt;Stdlib&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; 
                      &lt;span class='nv'&gt;Sasl&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; 
                      &lt;span class='nv'&gt;Lowername&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; 
                      &lt;span class='nv'&gt;Version&lt;/span&gt;&lt;span class='p'&gt;]),&lt;/span&gt;
  &lt;span class='nn'&gt;file&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;close&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Fs&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt;

  &lt;span class='nn'&gt;systools&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='n'&gt;make_script&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;Lowername&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;local&lt;/span&gt;&lt;span class='p'&gt;]),&lt;/span&gt;
  &lt;span class='n'&gt;halt&lt;/span&gt;&lt;span class='p'&gt;().&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;To actually write a bootfile, we need to supply the name of the bootfile to the method call, so we call this like so:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;% shell &lt;span class='nb'&gt;command&lt;/span&gt;
erl -pa ebin -noshell -run make_boot write_scripts rest_app
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Finally, let&amp;#8217;s make sure we have a .app file in the ebin/ directory, sample one below:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='c'&gt;% _name_.app&lt;/span&gt;
&lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;application&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;_&lt;/span&gt;&lt;span class='n'&gt;name_&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;
  &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;description&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;_Name_&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;},&lt;/span&gt;
  &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;vsn&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;0.1&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;},&lt;/span&gt;
  &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;modules&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;[_&lt;/span&gt;&lt;span class='n'&gt;modules_&lt;/span&gt;&lt;span class='p'&gt;]},&lt;/span&gt;
  &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;env&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;
    &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;port&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;9999&lt;/span&gt;&lt;span class='p'&gt;}&lt;/span&gt;
  &lt;span class='p'&gt;]},&lt;/span&gt;
  &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;registered&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;[_&lt;/span&gt;&lt;span class='n'&gt;name_&lt;/span&gt;&lt;span class='p'&gt;]},&lt;/span&gt;
  &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;applications&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;kernel&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;stdlib&lt;/span&gt;&lt;span class='p'&gt;]},&lt;/span&gt;
  &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;mod&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;{_&lt;/span&gt;&lt;span class='n'&gt;name_&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;[]}}&lt;/span&gt;
&lt;span class='p'&gt;]}.&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Lastly, break out the EMakefile so that we can actually compile the project:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='c'&gt;% EMakefile&lt;/span&gt;
&lt;span class='c'&gt;% -*- mode: erlang -*-&lt;/span&gt;
&lt;span class='p'&gt;{[&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;src/*&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;src/*/*&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;src/*/*/*&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;],&lt;/span&gt;
 &lt;span class='p'&gt;[{&lt;/span&gt;&lt;span class='n'&gt;i&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;include&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;},&lt;/span&gt;
  &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;outdir&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;ebin&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;},&lt;/span&gt;
  &lt;span class='n'&gt;debug_info&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
&lt;span class='p'&gt;}.&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Hurray, we are almost set. Now let&amp;#8217;s make a start.sh file so we can just call that to start the application:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;span class='c'&gt;#!/bin/sh&lt;/span&gt;
&lt;span class='c'&gt;# start.sh&lt;/span&gt;
&lt;span class='nb'&gt;cd&lt;/span&gt; &lt;span class='sb'&gt;`&lt;/span&gt;dirname &lt;span class='nv'&gt;$0&lt;/span&gt;&lt;span class='sb'&gt;`&lt;/span&gt;
erl -pa &lt;span class='nv'&gt;$PWD&lt;/span&gt;/ebin -pa &lt;span class='nv'&gt;$PWD&lt;/span&gt;/deps/*/ebin &lt;span class='se'&gt;\&lt;/span&gt;
    -sname alice -s reloader -boot rest_app &lt;span class='nv'&gt;$1&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Easy as pie.&lt;/p&gt;

&lt;p&gt;To show you why this is a great setup, simply navigate to the project directory and type&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;make &lt;span class='o'&gt;&amp;amp;&amp;amp;&lt;/span&gt; start.sh
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;And your server should start right up.&lt;/p&gt;

&lt;p&gt;A quick-tip I&amp;#8217;ve picked up&amp;#8230; get rstakeout so that anytime you change a file in the src/ directory, your application will recompile:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;rstakeout &lt;span class='s2'&gt;&amp;quot;make&amp;quot;&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;src/**/*&amp;quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Lemme know if this helps, I love to hear feedback!&lt;/p&gt;

&lt;p&gt;Download project files &lt;a href='/code/erlang/makefile.zip'&gt; here&lt;/a&gt;&lt;/p&gt;

&lt;h2 id='update'&gt;Update&lt;/h2&gt;

&lt;p&gt;I&amp;#8217;ve added a generic makefile generator in my erlang snippet project: &lt;a href='http://github.com/auser/skelerl/tree/master'&gt;Skelerl&lt;/a&gt;. Get it on &lt;a href='http://github.com/auser/skelerl/tree/master'&gt;github&lt;/a&gt; and type:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;makefile app_name
&lt;/pre&gt;
&lt;/div&gt;</content>
    </entry>
  
    <entry>
      <title>New blog engine, same ole' blog</title>
      <link href="http://willcodeforfoo.com/2009/06/23/willcode-returns"/>
      <updated>2009-06-23T00:00:00-07:00</updated>
      <id>http://willcodeforfoo.com/2009/06/23/willcode-returns</id>
      <content type="html">&lt;p&gt;Welcome to the new &lt;a href='http://WillCodeForFoo.com'&gt;WillCodeForFoo.com&lt;/a&gt; blog. It&amp;#8217;s gone through plenty of changes and is now going through yet one more! Powered by &lt;a href='http://wiki.github.com/mojombo/jekyll'&gt;Jekyll&lt;/a&gt;!&lt;/p&gt;</content>
    </entry>
  
</feed>