Archive for June 2009

There's been a lot of buzz recently around the lightweight Ruby framework known as Sinatra. It seems ideally suited for simple web applications that require a little sprinkle of Ruby and using the entire Ruby on Rails stack might be overkill. You've probably also heard of Rack (unless you've been without Internet access for the past six months.) If you're new to Rack and would like to learn more, you can check out this excellent presentation from RailsConf. I recently had the need to build a website that featured a blog along with some minimal dynamic content so I thought I would try hooking up Sinatra together with the Word Press blog engine.

WordPress(WP) is an excellent blogging platform. Its the consensus tool of choice for professional bloggers (those who blog for a living as opposed to people like me who occasionally blog about technology.) Since I was really happy with WP and I believe in using the best technology for the job, I wanted to see if I could get it working alongside Sinatra which I planned to use for the rest of the site. Why not just do the whole thing in PHP? Well the answer is that I hate programming in PHP. I didn't mind using an excellent tool like WP but I didn't want to get carried away with the PHP when it came to my own coding.

First, you need to get WP up and running with Apache HTTP Server. You can use any server really but I would recommend Apache since its widely used and well documented when it comes to PHP applications. There is no shortage of WP setup documentation so I'm not going to cover it here. Just be sure to setup WP in its own directory (/blog) instead of the top level root directory. Once you can reach your WP blog via http://example.com/blog then you're ready to proceed.

You're also going to need to install Phusion Passenger. I'm not going to cover installation of Passenger either since most Rails developers are already familiar with it. If you're not, I suggest you read some of the excellent documentation on the subject. What you may not know, however, is that Passenger also supports arbitrary Ruby web applications that follow the Rack interface (like say ... Sinatra.) So lets get started with a simple Rack app and then move onto Sinatra.

Install the Rack Gem

Lets make sure the rack gem is installed on our server.


gem install rack

Create the Directories Required by Rack

Suppose we are creating an application called "example" which is located in the /webapps directory


mkdir /webapps/example/public
mkdir /webapps/example/tmp

Create a Basic Rackup File

We also need to create a /webapps/example/config.ru for starting the Rack application


app = proc do |env|
    return [200, { "Content-Type" => "text/html" }, "hello world"]
end
run app

Change the Document Root

In the Apache config you will want to configure the DocumentRoot to point to the public directory in your Rack app (/webapps/example/public). Leave your WP blog directory where it is for now. Restart Apache.

If you navigate to your application in a web browser you should see the familiar "hello world" greeting. This means Phusion and Rack are now working together without a problem. Lets add Sinatra to the mix.

Setup Sinatra

Install the Sinatra gem if you haven't done so already.


gem install sinatra

Replace your config.ru with one that will setup Sinatra


require 'rubygems'
require 'sinatra'

Sinatra::Application.default_options.merge!(
  :run => false,
  :env => :production,
  :views => '/webapps/example'
)

require 'app.rb'
run Sinatra.application

Now create an app.rb which will be the basis for your Sinatra app


get '/' do
  'Hello Sinatra!'
end

Restart Apache and navigate to your local application using your web browser you should now see the Sinatra greeting that we just added.

Add the WP Blog

Move your entire blog dir into your Sinatra public directory. So you will now have /webapps/example/public/blog along with the original .htacess file used by WP. Your blog won't work yet, there's an important tweak to be made to your httpd.conf


<Location /blog>
  PassengerEnabled off
</Location>

This tells Passenger not to bother with files in the blog directory. This is key to getting the PHP-based WP blog to run inside of a directory where everything else is Sinatra. If you test your application inside of a web browser the blog should be working!

Build Out Your Sinatra Application

Go ahead and build out the rest of your Sinatra application now. Most likely you're going to want to share a common layout, header and footer between your Sinatra application and your WP blog. You can add "partial" support in Sinatra using a helper (Sinatra does not explicitly support partials.)

Modify your app.rb as follows:


get '/' do
  @section = 'overview'
  erb :overview, :layout => :default
end

helpers do
  # Usage: partial :foo
  def partial(page, options={})
    erb page, options.merge!(:layout => false)
  end
end

Then you can create a default.erb to serve as the default layout.


<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="en-US">
<head profile="http://gmpg.org/xfn/11">
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  <link rel="Shortcut Icon" type="image/ico" href="/blog/wp-content/themes/spree/favicon.ico" />
  <title>Spree</title>
  <link rel="stylesheet" href="/blog/wp-content/themes/spree/style.css" type="text/css" media="screen" />
</head>
<body>
  <div id="page">
    <!-- BEGIN: Header -->
    <%= partial :header %>
    <!-- END: Header -->
    <div id="main">
      <div class="content">  
        <p>
          <%= yield %>
        </p>
      </div>
    </div>
    <!-- BEGIN: Footer -->
    <%= partial :footer %>
    <!-- END: Footer -->
  </div>                 
</body>
</html>

Notice how I am using the favicon and stylesheets right from the WP blog theme. From this point on we're just writing a nice Sinatra application and sharing styles and images with our WP blog.

Final Thoughts

This is an excellent way to build a simple Ruby based website that requires a blog. I started off by having my artist just work up a design for the WP blog since she could do that on her own without any Ruby. I then copied the header and footer into my Sinatra app and created some stub ERB files for her to edit. Sinatra worked out well for my very simple needs. I basically needed a simple way to share layouts and to highlight the current navigation tab in my header.

My artist was able to edit these ERB files in place because they were basically straight HTML. All of the dynamic stuff was contained in the layout itself. The end result is a seamless integration of Ruby + PHP where each technology is being used for what it does best. There's been a lot of buzz recently around the lightweight Ruby framework known as Sinatra. It seems ideally suited for simple web applications that require a little sprinkle of Ruby and using the entire Ruby on Rails stack might be overkill. You've probably also heard of Rack (unless you've been without Internet access for the past six months.) If you're new to Rack and would like to learn more, you can check out this excellent presentation from RailsConf. I recently had the need to build a website that featured a blog along with some minimal dynamic content so I thought I would try hooking up Sinatra together with the Word Press blog engine.