h1. mojito - Next level Ruby webframework

  1. Mojito is a lean and simple webframework.

  2. As the name implies mojito derives from cuba (github.com/soveran/cuba). Many thanks to Michel and his cuba project for giving me some major insights on web-application-simplicity! See also github.com/mtrense/mojito-examples for more examples.

h2. Installing

bc. $ gem install mojito

h2. Your first application

  1. The easiest way to start with mojito is to use a plain @config.ru@ script to develop and configure your application.

bc.. $ cat config.ru require ‘mojito’

class FirstApp

include Mojito
controller :runtime
rendering :all

on GET(), PATH('/hello/:name') do |name|
        write "Hello #{name}! How are you?"
        content_type :plain
        ok!
end

end

run FirstApp

  1. This installs a handler for GET requests to a path of /hello/ followed by a name (actually this notation catches everything but a slash ‘/’). You can start this application by running @rackup@ from the same directory:

bc. $ rackup

  1. This starts a http-server on port 9292. Now try to call your handler with curl:

bc. $ curl localhost:9292/hello/Fred Hello Fred! How are you?

h2. Controllers

Controllers are the common building blocks of Mojito Applications. For each successful request at least one controller is instantiated. The call to @controller :runtime@ actually defines the calling class as runtime controller and includes the corresponding module - Mojito::Controllers::Runtime in this case. For a specific class one can choose from many controller types, each of which is specialized to a specific use-case.

Controller classes are actually Rack-Applications, so they must provide a (class-)method @call(env)@. The common sequence of processing a request includes:

This ensures that the controller instance which handles a specific request is used solely for that request, so that any instance variables created during request-processing stay request-local. At the same time this keeps application stacking and nesting as simple as @call@-ing the next application.

h2. Structure of a real-world application

  1. *This is not up-to-date*

  2. The above call to @Mojito.application@ actually created a class and included most of Mojitos foundation methods, so that you could start writing your application code without wondering what features you want to include in your application. As a tribute to simplicity (one of the most important I think), another helper method @Mojito.base_application@ can be used to create a blank application class, which only includes modules that are strictly necessary. Instead of using those methods you can also write out all of the generated classes code (here @Mojito@ is included, which in turn includes @Mojito::Base@, the basic module which is used by @Mojito.base_application@):

bc.. class FirstApp

include Mojito
routes do
        on GET(), PATH('/hello/:name') do |name|
                ...
        end
end

end

  1. which is not only perfectly legal but also favoured, when you need any special behaviour on your application class.

  2. Although you can actually use any structure you want (including a single-file application), some of them are more useful than others. My preferred way of developing Mojito applications is to reuse most of the concepts found in product development with rubygems and git.

h2. Behind the scenes

  1. Understanding how Mojito dispatches requests and selects handlers, which in turn use common functionality to create the response is vital to an efficient use of Mojito as web application framework. First of all Mojito applications (classes which include @Mojito::Base@ or @Mojito@) are simply Ruby classes, which are instantiated with the Rack-environment hash for each request. This is automatically triggered by a rack-enabled webserver through the call of @run ApplicationClass@, which tells rack to call @call(env)@ on that class. The Mojito implementation will then instantiate the Application (the instance is called a controller from now on) and call @dispatch@ on that controller. The dispatch method then executes any block given to the @routes@-method in the class definition. As in Cuba the routes-definition is executed once for each request.

h3. Matching

  1. A matcher is simply a Proc, instantiated with matcher-specific configuration, which returns whether or not a given request matches its criteria. The request-method matcher for example is implemented as follows:

bc.. def METHOD(method)

proc { request.request_method == method.to_s.upcase }

end

  1. This method configures a Proc to return true when the requests method matches the given parameter. The returned Proc is evaluated in the context of the current controller. This is also where the @request@ method comes from. Like @request@, a matcher can access any method from the controller, within which it is executed. The naming convention is to name all matchers uppercase.

h3. Rendering

h3. Helpers

h2. Deployment/Hosting

  1. tbd

h2. Writing extensions

  1. tbd

h2. Contributing to mojito

h2. Copyright

  1. Copyright © 2012 Max Trense. See LICENSE.txt for further details.