My favorites | Sign in
Project Home Downloads Wiki Issues Source
Search
for
ProjectNotes  
How I built LinkShrink.
Updated Apr 12, 2008 by nleghari

Introduction

I believe that the best way to learn something is to develop an application with it. So when it comes to Rails, I decided to develop a clone of TinyUrl.

Flow:

Because the website is simple therefore it only consists of a single page. Remember less is more :). The user lands on the main page, where he/she enters the url and click the shrink button to shorten the url.

The first thing is to create a new Rails application.

Rails linkshrink

create
create  app/controllers
create  app/helpers
create  app/models
create  app/views/layouts
create  config/environments
......

Then I am going to open this into my favourite Ruby/Rails IDE.

<netbeans>

From NetBeans, I created a new project with existing sources and point the sources to the folder created above. (It is possible to create a new rails project using NetBeans but I personally prefer to use command line)

Then it's time to build the model. At this moment, I'll keep the database simple with just a single table and uses MySql as the database engine.

mysqladmin create linkshrink_development

Then create a new model for links.

ruby script/generate model link actual_url:string shrinked_url:string

exists  app/models/
exists  test/unit/
exists  test/fixtures/
create  app/models/link.rb
create  test/unit/link_test.rb
create  test/fixtures/links.yml
create  db/migrate
create  db/migrate/001_create_links.rb

Once we have the model and the database script, we can apply the migrations using rake.

rake db:migrate

(in E:/BitNamiRubyStack/apps/linkshrink)
== 1 CreateLinks: migrating ===================================================
-- create_table(:links)
   -> 0.1410s
== 1 CreateLinks: migrated (0.1410s) ======================

It looks like the database is updated so now it's time to create the controller. We know that our user starts on the default page which maps to the default action (index) and then we need another action to 'create' the link. Using ruby to generate the controller with these two actions.

ruby script/generate controller public index create

Now that we have the controller and the basic view, lets build a simple form to submit the url.

Here is the code for the simple form that we have on the default page.

<% form_for :link, 
    :url => {:action => :index}  do |t| %>
    <p>
      <label for='actual_url'>Enter the link to shrink:e:</label>
      <%= t.text_field 'actual_url' %>
    </p>
    <p>
      <%= submit_tag "Shrink Url" %>
    </p>
<% end %>

The form is submitted to the index action for the same controller so we need to handle the post there.

def index
        return unless request.post?
        # if the record exist in database then get the shrinked url from the db
        link = Link.find_by_actual_url(params[:link][:actual_url])
        
        # else create a new shrinked url
        unless link
            link = Link.create(params[:link])
            link.shrinked_url = get_shrinked_url
            link.save!
        end
        
        @shrinked_url = build_url(link.shrinked_url)
        
 end

The code to generate a random word is in the get_shrinked_url. At the moment, it is very simple and possibly not optimized.

def get_shrinked_url
        valid_chars = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o',
'p','q','r','s','t','u','v','w','x','y','z','1','2','3','4','5','6','7','8','9']
        code = ''
        (1..8).each do |i|
            char = valid_chars[rand(valid_chars.length)]
            code << char
        end
        code
    end

After getting the shrinked_url, we are building the complete url including the code which is then used on the view, so we'll add the following code to the view

<% if @link %>
    Original Url: <%= link_to @link.actual_url, @link.actual_url %> 
    Shrinked Url: <%= link_to @link.shrinked_url, @link.shrinked_url %>
<% end %>

So, we can test our application now by navigating to the index page

And as soon as I click the Shrink Url button, I get the shrinked url.

We have our tiny url so we just need a redirect action which is invoked when the above url is used. So we added a new action to the public controller.

def redirect
        link = Link.find_by_shrinked_url(params[:id])
        if link
            unless link.actual_url.include? 'http://'
                puts 'adding protocol'
                link.actual_url = "http://#{link.actual_url}" 
            end
            puts "Redirecting to #{link.actual_url}"
            redirect_to(link.actual_url)
        end
    end

All it is doing is to get the parameter from the url and search for the link object in the database. Once we have a valid link object, we redirect to the actual url. Before we test this, we also have to add a new route in config\routes.rb file to handle this url scheme.

    map.connect '/:id', :controller => 'public', :action => 'redirect'

Now when we put our tiny url, this will invoke the redirect action.

Making it look better:

I'm not a designer so here is what I came up with after tinkering with CSS.

Comment by hattorih...@gmail.com, Nov 16, 2008

please note you forgot to add the @ sign to the link variables in index and redirect methods.


Sign in to add a comment
Powered by Google Project Hosting