PHP to Sinatra

When it comes to prototyping, there is no reason that it can’t be done with PHP. My own core web development is with PHP, but have found increasingly, that I want something better. Better, that is, at getting a web application running with a minimum of fuss.

In this article, I’ll assume that your starting point is where mine was: competent with PHP and the web generally (HTML and CSS), but looking for a slick prototyping tool. We’ll get Ruby and Sinatra installed, and then we’ll build a simple blog that doesn’t need a database, but does support Markdown.

Options for Getting Setup

There isn’t too much that you need to get started, the main component being the Ruby programming language. Ruby is available everywhere, but it can be a little troublesome to get set up. For example, if you use a Mac you already have Ruby installed, but not a version you want to use. For some reason, Apple have left version 1.8.7 as the installed version, even on Mountain Lion.

Mac and Windows

Ruby 1.9.3 is the current version, so how do we install that? If you are on Windows or Mac, you re lucky. A relatively new option is available called the Rails Installer is available. It provides you with an installable program that automatically adds all the components you need without any fuss. You might be wondering why I am suggesting you install Rails when want we want is Sinatra. The answer is simple. Rails installer provides everything you need to work with Sinatra as well (almost).

Rails Installer is like WAMP, or MAMP if you use either of those, you’ll get the idea.

For example, it will install amongst other things, Ruby, Git, Sqlite, the compilers you need, and the Ruby Version Manager (RVM). RVM is an amazing way to manage Rubies on your system. The nice thing about it is, it installs in a “sandbox” and doesn’t cause conflicts with anything else on your system.

What About Linux?

If you are using Linux, Ruby will be available in the repositories for your distro of choice. You might find that the version of Ruby will be old though, so I recommend installing RVM. The best instructions for doing that can be found on the RVM web site.

Ruby Gems

Ruby uses a system of libraries known as gems. You can think of them as something similar to the idea of PEAR libraries. Whether you installed via Rails Installer, or RVM directly, you will need to install the Sinatra gem.

It couldn’t be easier. Get on the command line and do:

gem install sinatra 

Now, I don’t know about you, but that feels like a lot less messing around than “discovering” PEAR channels doesn’t it?

By the way, it is also worth installing a nice slick web server called Thin. Sinatra will pick it up automatically if it is installed:

gem install thin 

Building an App – Making a Start

If you are like me, you probably do most of your PHP development via a framework nowadays. That usually means dropping the framework files into a folder, and starting on your layouts, or data layer, or whatever needs doing first. It might be setting configuration options, and adding connection parameters. Well, with Sinatra, there is none of that.

Sinatra is NOT a framework, it’s a Domain Specific Language, meaning it is designed to solve a particular problem.

Oh, and while I’m at it, it is not practical to try and compare PHP with Sinatra. The only judgement I am making is how quickly we can get something up and running.

Alright, time for code. Create a new folder called sinatra_projects, and then inside that create one called blog. Using your favourite text editor, create a file called main.rb and save it to the blog folder. Next, create a sub folder called public, and another called views.

The public folder will store assets such as stylesheets and images, and the views folder will contain the interface our users will see. Although it is possible to break Sinatra apps up over multiple files, most of the time it is not necessary. For a classic Sinatra app, just create a file called main.rb inside the blog folder.

Then, we will need to add some some gems to get things working. So at the top of the main.rb file you just add:

require 'sinatra' 

Sinatra works by responding to the http verbs such as GET, POST, PUT etc., so it is easy to get something working. In main.rb, add a method like this:

Here, we are asking Sinatra to “get” the contents of our method and display it in the browser. The reason it works is because Sinatra is a layer that allows developers to work with Ruby middleware known as Rack. Sinatra abstracts Rack so that we can focus on HTTP requests without having to worry about any of the other technical stuff going on.

Now we can test the file and see how it looks. On the command line, navigate to the your blog directory and then type:

ruby main.rb 

The output will tell you that Sinatra has taken the stage, and that the server is running on port 4567. So now, you can visit http://localhost:4567 in your browser and you should see our brilliant web page greeting us with the “hello world” message. Next, we’ll start to make something a little more useful.

Building a Blog, Part 1

Let’s say that we wanted to create a Sinatra application that allowed us to write blog posts using Markdown. For our first iteration, we need a way to to create files that have a bit more content in them. Ruby has the ability to be embedded inside HTML in a way that will feel similar to PHP. It is known as Embedded RuBy (erb), and works great with Sinatra. That means we can create .erb files, add what HTML markup we want, and embed Ruby code too.

Create a new file in your blog/views folder and name it index.erb. In this file, create a simple HTML page. We’ll then use the Ruby methods to display the current date and time:

We change the root method in main.rb to make this work:

Here, we have created an instance variable called time, created a new instance of the built-in Time method and assigned it to our variable. That will be available in our .erb file as we have already seen.

You will probably need to to re-start the server (CTRL & C, then do ruby main.rb as before) and you should see a page displaying the date and time. That is still not very exciting, but at least we have seen how we can display a HTML page with Ruby code embedded.

Creating a Layout

Sinatra is clever. Among its fortes is detecting certain files automatically. Create a new file in your views folder called layout.erb. Knock yourself out with a design for your blog. You can add a stylesheet in the public folder, and then call it as though it was in the site root. Sinatra will find it automatically after that. The only bit of Ruby code we need for this file (for now) is:

<%= yield %> 

Wherever you want the content of your page to appear. Sinatra will automatically detect and use the file to display your pages. That means you don’t have to add all the normal HTML tags to your .erb files, just the stuff that should go in the content area of your design. You can try it out with the index.erb file if you wish. Clear out all the page structure HTML stuff and re-load the page. With your layout.erb file in place nothing should change except that the page will now display with your design added.

Building a Blog, Part 2

Now that we have a layout sorted, let’s concentrate on the core code for our app. Create a sub folder in your blog/views folder named posts. Here is where we will store the blog posts written in Markdown. What we need to be able to do is create a clickable list of links for the articles directory. That means each time a new article is added, our list will be updated automatically.

In main.rb create a new method called get_files, and add a parameter called path:

def get_files(path) 

This method will be used to list the files in our posts directory. Here is the method, I’ll explain what’s going on in a moment:

  1. First, we create an array to hold the list of file names that have been found in the directory passed in via the path parameter.
  2. Then we use the Ruby Find gem to iterate over the files it finds in our posts directory, adding the file name to the dir_list_array array for each file found.
  3. Make sure that you add: require 'find' to the list of included gems.
  4. The File.basename part makes sure we get just the filename and not the full path and extension.
  5. The if !File.directory?(f) part, makes sure that we only list the contents of the directory passed in, and not any sub folders.

This method will do most of the work for us. Next, change your index method to call our get_files method and populate an instance variable with the contents:

Now, in index.erb, we can create a simple loop to iterate through the files and make a clickable list:

Here you can see that we loop through the array passed in from the instance variable, printing out the filename and making a hyperlink at the same time.

Re-start your server, and go to http://localhost:4567 in your browser. You might not see anything yet, of course, if you haven’t added any posts. Just create a couple of dummy posts and save them as markdown files in your posts folder. Obviously, clicking a link won’t work at the moment, we’ll sort that out next.

Building a Blog, Part 3

We can see from the index.erb file that we now need a method in main.rb to handle calls to view. The method also needs to accept a parameter called link We’ll be passing the filename of the blog post for rendering as HTML.

Here is the method:

First, be sure and add the rdiscount gem (require 'rdiscount') to our list of required gems at the top of the file. The gem will render the Markdown as HTML for us.

Notice that :link is added to the route call. That is the way we denote a querystring parameter passed in from index.erb.

Now you should be able to click the links and be taken to a page that renders the Markdown as HTML for each post saved in your posts folder.

The halt action in Sinatra is very useful The first line of our method checks that the passed in filename exists. If it doesn’t, we are sent to a 404 page (we’ll create a custom one in a minute). The second line uses the rdiscount gem to render the Markdown found in the passed-in Markdown file as HTML. We specify that the erb layout engine is being used.

Create a Custom 404

The idea is, that if the user requests a file that doesn’t exist in our posts folder, they will get a 404. We can create a special Sinatra method for handling that situation called not_found:

Here, you can see that we need to create missing.erb in our views folder. Add whatever content you would like to the file, but obviously it should politely inform your users that the file doesn’t exist.

What About Adding Other Pages?

To add more pages to the site, all you need to do is create a method in main.rb, and a corresponding file in views. You could even write extra pages using Markdown using a similar approach to what we have already done. Let’s create an ‘about’ page:

Create either about.md, or about.erb and then test the page in your browser by going to: http://localhost:4567/about.

Tidying Up the Links

If you have used a file naming scheme that is typical for blog posts, you probably have a list with entries like ‘my-blog-post’. We can tidy that up a bit by using a helper method to remove the hyphens and capitalize the first word of the title. This will only affect the displayed filename. In main.rb add this after the gem calls:

Then, you can change the loop that iterates over the posts directory in index.erb to look like this:

Now you have a list where the displayed filename looks like a blog title. The hyperlink will still work as expected. Here is the completed main.rb file:

Finally…

Coming from PHP and working with Sinatra certainly feels different. But in very little time, you have set up Ruby and have created a Sinatra app that has plenty of potential. It is worth pointing out that this can be achieved without knowing Ruby in great detail. Working with Sinatra helps with the process of learning Ruby, and is good preparation for taking on Ruby on Rails too.

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • Feras

    If you want something similar to sinatra but still PHP you can have a looks at:
    http://silex.sensiolabs.org/

    Its based on Symfony2 components so its very flexible and is a very good starting point to build a simple API or something like that.

  • http://www.thedigitalforge.com Jim Holland

    Hi Andy,

    Very nice tutorial, thanks. There are a couple of wee bugs though:

    1. Need require ‘rubygems’ in main.rb for it to run at all
    2. In Building a Blog, Part 3 you switch ‘posts’ for articles the code should read

    halt 404 unless File.exist?("views/posts/#{params[:link]}.md")
    markdown :"posts/#{params[:link]}", :layout_engine => :erb

    Keep up the good work!
    Cheers
    Jim

  • David

    Great article!

    I think there is an error in the call to view method with the name of the folder: should be ‘posts’ not ‘articles’. https://gist.github.com/3749130

  • http://www.andyhawthorne.co.uk Andy

    Good catch – it should indeed be “posts” and not “articles”, I’ve updated the gist. I’m not sure about needing to require gems to be honest. I don’t need to. I’m on Ruby version 1.9.3…