|
ProjectNotes
How I built LinkShrink.
IntroductionI 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)
endThe 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
endAfter 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
endAll 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.
|
please note you forgot to add the @ sign to the link variables in index and redirect methods.