Create a custom domain URL shortener with Rails
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 a Distinguished Software 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.