Halcyon

Notice: The website is currently being udpated. Sorry for any inconvenience.

Writing Controllers

Controllers are the functional heart of your application. Requests to your
application get routed to controllers where the actions defined within them are
dispatched.

Those of you familiar with Rails or MVC
in general will recognize the role that the controller and its actions play.
While the models will contain the primary portion of logic, controllers will
coordinate it all.

Really, there’s nothing special about Halcyon controllers. Let’s look at what
they look like.

Controller Structure

1 class Messages < Application
2   
3   def show
4     ok Message[params[:id]]
5   end
6   
7 end

The Application class we inherit from simply from Halcyon::Controller and
provides a place for utility methods et al. Application is created by default
when generating an application.

Actions

Actions make up the functional portion of classes. Actions are considered any
public method (private methods are not callable through routes).

Actions have several useful methods, two of which will be used in most actions:
params and ok. The params method provides access to the parameters
available, such as GET params, POST params, and route params. ok is used to
format responses and is akin to calling render :json => val in Rails.

Resources

The REST approach to application design treats
our models as resources with a standard set of methods to work them them.
Again, if you’re familiar with Rails development, none of this is new. Here is
an example controller defining these standard REST methods.

 1 class Messages < Application
 2   
 3   def show
 4     ok Message[params[:id]]
 5   end
 6   
 7   def create
 8     ok Message << params
 9   end
10   
11   def update
12     Message.filter(:id => params[:id]).update(params)
13     ok
14   end
15   
16   def delete
17     Message.filter(:id => params[:id]).delete
18     ok
19   end
20   
21 end

Resources are mapped to these methods through routing method resource. This
is one of the benefits of using the Merb router.

Read more about writing routes for great coverage of this
topic.

Error Handling and Exceptions

There will inevitably be errors that need to be handled and exceptions are a
big part of gracefully working with errors in a meaningful way. Halcyon
provides all of the standard HTTP responses as exceptions to help with quickly
communicating the appropriate status of a request, and Halcyon handles
exceptions to gracefully communicate with the client the appropriate status in
the standard format.

Here is an example of handling success or failure:

 1 class Messages < Application
 2   
 3   def show
 4     if (msg = Message[params[:id]])
 5       ok msg
 6     else
 7       raise NotFound.new
 8     end
 9   end
10   
11   def create
12     msg = Message.new
13     msg.values.merge! params
14     if (id = msg.save)
15       ok id
16     else
17       raise UnprocessableEntity.new
18     end
19   end
20   
21 end

The UnprocessableEntity exception class maps directly to the standard HTTP
response code 422 Unprocessable Entity which signifies that there were errors
creating the record as the models validations failed. You can certainly supply
the exception with a body other than the literal text "Unprocessable Entity"
which could be the exact error (which is recommended). This is up to you, of
course.

Check out the list of exceptions to see what’s
available and how to use them.