Getting Started With Cappuccino and Ruby on Rails

Cappuccino is completely server agnostic, meaning Cappuccino applications can be served using any HTTP server (for example Apache, lighttpd, Microsoft IIS, etc) and can communicate with any server side technology over HTTP (Ruby on Rails, Django, PHP, ASP, Java, CouchDB, etc). This lets you choose your server-side components based on whatever criteria is important to you (experience, existing infrastructure, etc).

That said, many people have asked for examples of using Cappuccino with various server side technologies, especially Ruby on Rails. Since Cappuccino is server agnostic, it turns out to be very simple to get started.

Setting Up a Project

The first step is to create your Rails project using the standard “rails appname” command:

rails appname
cd appname

Then create a new Cappuccino project in a temporary directory, either using the “steam create” command, or by downloading the “Starter Package”. Move the contents of the Cappuccino project to the Rails application’s “public” directory. Here’s an example using “steam create” (which will overwrite the default index.html):

steam create temp
mv temp/* public/.
rmdir temp

That’s it! Start the Rails webserver using “script/server”. Point your browser to http://localhost:3000/ and you should see the “hello world” Cappuccino application.

Exposing the Data

This alone isn’t particularly interesting. For Rails to be useful in conjunction with Cappuccino you’ll want to be able to transfer data between them. Rails makes this very easy.

Rails offers built in support for two common data exchange formats: JSON and XML. Of the two, JSON is typically prefered in Cappuccino. To output a Ruby data structure as JSON, simply call “render :json => object” in the controller action:


class TestController < ApplicationController
  def movies
    @movies = Movie.find(:all)
    render :json => @movies
  end
end

This is getting all the “Movie” model objects, and simply serializing the array into JSON.

You can also filter or process the array before serializing it. When an ActiveRecord instance is converted to JSON it is wrapped in an extra object that’s usually uneccessary (i.e. { “movie” : { “title” : “something”, “description” : “a description” }}). Creating a plain Ruby object from each ActiveRecord object prevents this. Additionally, it allows you to perform other processing, such as excluding certain properties. Here we use “map” to convert each ActiveRecord object to a plain Ruby object:


def movies
  @movies = Movie.find(:all).map {|m| { :title => m.title, :description => m.description } }
  render :json => @movies
end

Finally, if for some reason you need to use JSONP (be sure you understand why you need it, and the security implications!), Rails makes it very easy to wrap the JSON in callback:


def hello
	render :json => { :hello => "world" }, :callback => params[:jsoncallback]
end

This example also demonstrates accessing parameters that were passed in, namely the “jsoncallback” parameter.

Getting and Submitting Data From Cappuccino

The typical way to retrieve or submit data from a Cappuccino application is to use CPURLConnection. This is discussed extensively in a previous blog post, and all of it applies to using Cappuccino with Rails.

Scaffolding

In addition to HTML views Rails “scaffolding” also provides simple XML web services. You can also easily add JSON versions similar to the following:


def index
  @movies = Movie.find(:all)

  respond_to do |format|
    format.html # index.html.erb
    format.xml  { render <img src='http://cappuccino.org/discuss/wp-includes/images/smilies/icon_mad.gif' alt=':x' class='wp-smiley' /> ml => @movies }
    format.json  { render :json => @movies }
  end
end

Conclusion

This covers the bare essentials of integrating a Cappuccino application with Rails. There is lots of potential for better Cappuccino integration with ActiveRecord and other server-side data technologies. Please feel free to make suggestions, or implement something and contribute it back!

  • Thanks for this guide. I'm working on my first Cappuccino UI and this is pretty neat stuff.

    I had never heard of JSONP but am excited to start working with it in my first Cappuccino app.
  • Great start, guys. Glad to see this tutorial. I think the "harder" stuff of integrating Cappuccino w/ Rails will be dealing with multi-model and nested-model scenarios. These are more common with full-fledged applications, multiple windows, etc., all things that are possible with Cappuccino. Looking forward to the next level of examples and tips.

    One other thought: It would be great to see your recommendations on organizing code for a "typical" rails app. Just as Rails creates conventions of model, views, controllers in separate folders (as well as URL resources), Cappuccino has no such hard and fast convention. Would like to see your recommendations on that.
  • Nice article.

    One nitpick: Your solution for serializing only certain attributes in JSON isn't very Rails-like. Instead, first load the model as you usually would, then render like this:

    render :json => @movies.to_json(:only => [:title, :description])

    This serializes the objects to JSON with only the title and description attributes. This method is also very flexible, e.g. you can include associations and methods that way too. See the RDoc at http://api.rubyonrails.com/classes/ActiveRecord/Serialization.html#M001417 for details.
  • I agree, that's the way to do it. And regarding the wrapping in a "movie" object: that can be turned off by setting config.active_record.include_root_in_json = false in environment.
blog comments powered by Disqus

Download

Cappuccino and Objective-J are licensed under the LGPL. For more information, see our licensing page.

Copyright © 2009 - 280 North, Inc. Cappuccino and Objective-J are registered Trademarks of 280 North. Logo by Sofa. Hosting by Slicehost.