Create a custom domain URL shortener with Rails

Rails, Tutorial Posted on

A few weeks ago I made a post about creating custom domain short URL services with bit.ly. I'm going to walk you through a simple Rails application that allows you to create a custom domain URL shortener for free!

Creating the Rails App

I'm going to assume that you know a little bit of Rails. First let's begin by creating our base Rails app and a few models. I will be calling my application leav.in (just because it's what I used in the previous post.

rails new leav.in

Let's create a very simple Link model:

rails c scaffold Link in_url:string out_url:text http_status:integer

Here's the breakdown of each field:

  • in_url - the URL that we will search by
  • out_url - the outgoing URL that we will redirect to
  • http_status - the status we will attach to the redirect

Before we migrate, let's get down and dirty and add a few things to our migration:

def up
  create_table :links do |t|
    t.string :in_url
    t.text :out_url
    t.integer :http_status, :default => 301 # default to :permanent
    t.timestamps
  end

  add_index :links, :in_url
end

We've added two (2) things. First, we default the HTTP Status code to 301 (permanent redirect - for more information on HTTP status codes, see W3C's documentation on HTTP status codes

Now lets run our migration:

rake db:migrate

We should probably add some validations to our simple model:

class Link < ActiveRecord::Base
  validates :in_url, :out_url, :http_status, :presence => true
  validates :in_url, :uniqueness => true
end

Here we are making sure that in_url, out_url, and the http_status fields are all present and we make sure that in_url is unique (because we can't have the same short URL point to two different links!)

Now it's time to play around a little bit. Start up the rails development server:

rails s

Play around and add some shortenings.

Cool, now onto the fun part. Let's open up the config/routes.rb file and add a default route at the very end for catching all our links:

LeavIn::Application.routes.draw do
  resources :links
  match ':in_url' => 'links#go'
end

If you refresh the page now and try a url like http://localhost:3000/t, you'll probably get a message like "No action go defined for links_controller". So let's fix that. Open up the links_controller.rb file and add the following method:

def go
  @link = Link.find_by_in_url!(params[:in_url])
  redirect_to @link.out_url, :status => @link.http_status
end

Now check it out! Links are working as expected!

There's definitely a lot more that needs to go into this project, like adding authentication, authorization, UI, etc. but I think you understand the basic idea now.

About Seth

Seth Vargo is an engineer at Google. Previously he worked at HashiCorp, Chef Software, CustomInk, and some Pittsburgh-based startups. He is the author of Learning Chef and is passionate about reducing inequality in technology. When he is not writing, working on open source, teaching, or speaking at conferences, Seth advises non-profits.