Using ActiveRecord with Sinatra

Show Notes

In this screencast we'll create a URL shortener in Ruby with Sinatra. We're going to show you how to integrate ActiveRecord with a Sinatra application.

You'll need this regular expression to follow along:

What you'll learn

  • How to integrate ActiveRecord in to Sinatra with sinatra-activerecord
  • How to build a URL shortener and how to use Base 62 in order to keep your urls short


Welcome to the Using ActiveRecord with Sinatra screencast. In this episode we'll show you how to build a URL shortener in Sinatra. If you're new to Sinatra, we recommend you watch our Introduction to Sinatra screencast before watching this video. We'll also be using Haml in our views, so we also recommend getting up to speed with our Introudction to Haml screencast.

ActiveRecord in Sinatra

To get Sinatra working with ActiveRecord, we could do it the long way, by configuring it all up ourselves and writing the migrations ourselves, but that would take quite a while. Thankfully, Blake Mizerany, the creator of Sinatra, has provided a gem that will get you up and running in a couple of minutes. The gem is called sinatra-activerecord.

sinatra-activerecord extends Sinatra to use ActiveRecord, and provides helpful rake tasks. Currently there are two rake tasks provided. There is db:create_migration for creating migrations, and the familiar db:migrate for running migrations. We'll go into the setup and usage of both later in this video.

Installing sinatra-activerecord

First let's get sinatra-activerecord installed. We need to install the gems: activerecord, sinatra-activerecord, and sqlite3 (for our database).

Now that they're installed, we need to set up our Rakefile. To do this, let's first create our app.rb, then we'll require 'sinatra' and 'sinatra/activerecord'

Then, we'll make a Rakefile, and require our 'app' and 'sinatra/activerecord/rake', which includes db:create_migration and db:migrate in our list of available rake tasks.

So when we run rake -T in our console, we see both tasks are now available.

Creating Our Model

Now that we've got this set up, let's create our first model ShortenedUrl. So lets type in rake db:create_migration and hit return. As you can see, we need to pass in a NAME option with the name of our migration. In our case, let's pass in NAME=create_shortened_urls.

As you can see, it's created a db/migrate folder with our migration in it. Now, let's write our up and down migration code.

In self.up we want to create the table :shortened_urls with the string :url. Let's also be sure to add an index on :url.

Now to self.down. While sinatra-activerecord doesn't have a db:rollback task at the moment, it's always good to get in the habit of doing so. So we want to drop the table :shortened_urls on rollback.

So when we run rake db:migrate, you'll see the migration run fine, and it creates a development.db database with the table shortend_urls.

You can manually rollback by going into irb, requiring 'app', and then the migration path. Then, call 'down' on the migration class. In our case, CreateshortenedUrls.down. And as you can see, the table is dropped. Let's go up again and move on.

OK, in our app.rb let's create our ShortenedUrl model. This is done in our app.rb file by typing class ShortenedUrl, and then inheriting from ActiveRecord::Base. We can include validates_uniqueness_of and validates_presence_of too, just like you'd expect in Rails.

We should also add a regular expression to validate the format of the :url.

We found a regular expression on John Gruber's Daring Fireball blog, but we've had to tweak it a little to fit our example a bit better. We'll include it in the show notes.

So that's all we need for our model. Now, to our routes.


We'll create a get route for our root path, for when people visit the site.

We'll also create a post route, to create our shortened URL.

We'll also create a get route to forward people from the shortened URL to their destination. Let's create a named parameter called :shortened.

Let's assume for the time being that the id of our saved ShortenedUrl is the shortened version of our URL. So let's find our ShortenedUrl with our :shortened parameter, which is its id.

Now let's redirect to the short_url's url.


Now that we have our redirection code, let's add some view files.

Let's create a views folder and include a layout. We'll create a very simple, crude layout...

OK, now let's create an index view. In here, let's create a %form that posts to the root with a %label(for="url") [label for url] and a text%inputfor the URL. Finally, we'll add asubmit` button.

Let's not forget to add haml :index inside of our get route block for the root path.

Now, in our post route block, let's write the code for finding or creating our ShortenedUrl. So @short_url = ShortenedUrl.find_or_create_by_url(params[:url]) will either find or create a new @short_url. If @short_url.valid? is valid then we show the :success view. If not, let's show the :index again.

OK, so let's create a success.haml file, and in it, let's include our shortened url.

Let's go back to our index and add an error message. If @short_url.present? is present and !@short_url.valid? not valid then let's inform the user that they've entered an "Invalid URL".

OK, so let's try it out.

As you can see, if we type in something invalid, we see the error message appear. And if we type in a valid URL, like, we the "shortened" URL.

Let's copy and paste this address into our address bar, hit return...and as you can see, it forwards us to


Alright, so our code is working. But this isn't that much of a URL shortener since when we get to the id of 10 our URL will increase by one character. What we can do to prevent the premature lengthening of the URL is to convert our id into a Base 62 string. Base 62 uses letters and numbers, to write numbers with with less characters, since we have all 26 letters, upper and lower case, with the 10 digits, 0-9, all at our disposal. Twenty six uppercase letters, plus twenty six lowercase letters, plus ten numbers, equals 62. That means our URL won't increase by one character until we reach the 62nd URL. After that, our URL won't increase by one until the 3,844th URL is added, as that is 62 squared.

So using Base 62 scales well! Another benifit form using Base 62 is that since the characters are all alphanumerical, we won't have any problems with the shortened URLs.

To encode integers into Base 62 strings, we can use a gem called alphadecimal. This gem allows you to call .alphadecimal on integers to convert them to Base 62 strings. The reverse is also true. If you call .alphadecimal on a string, you get an integer returned.

So let's install alphadecimal, using the command: sudo gem install alphadecimal.

Now let's require it in our app.rb.

Let's add a shorten method to our ShortenedUrl where we convert the id to a Base 62 string.

Then in our :success view, let's change id to shorten

Now, we need to create a class method on ShortenedUrl to find it by the Base 62 string. We'll call this method find_by_shortened. We'll pass in a string, shortened and then convert it back to the integer, id by calling .alphadecimal. Then we just need to find that id.

Finally we just need to update our redirect route block, so instead of a simple find we replace it with find_by_shortened.

And that's it. If we go back to our browser and enter a few more URLs, we see the Base 62 URLs being shown. And if we copy-and-paste them, we find that they redirect correctly too.

Thanks for watching! Subscribe to our RSS feed, follow us on Twitter, and please leave any questions, comments or suggestions for new screencasts in the comments below. If you like our videos, and think your friends, followers or colleagues would benefit from seeing them, please feel free share via any of the links below the video. We really appreciate your support.

See you next time!