diff --git a/source/Gemfile b/source/Gemfile
index 9627b8b..6a4c4a5 100644
--- a/source/Gemfile
+++ b/source/Gemfile
@@ -16,8 +16,6 @@ gem 'coffee-rails', '~> 4.0.0'
# Use jquery as the JavaScript library
gem 'jquery-rails'
-# Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
-gem 'turbolinks'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.0'
# bundle exec rake doc:rails generates the API under doc/api.
@@ -38,4 +36,3 @@ gem 'spring', group: :development
# Use debugger
# gem 'debugger', group: [:development, :test]
gem 'rspec-rails', group: [:development, :test]
-
diff --git a/source/Gemfile.lock b/source/Gemfile.lock
index fcf8b98..0eae19a 100644
--- a/source/Gemfile.lock
+++ b/source/Gemfile.lock
@@ -113,8 +113,6 @@ GEM
thor (0.19.1)
thread_safe (0.3.4)
tilt (1.4.1)
- turbolinks (2.4.0)
- coffee-rails
tzinfo (1.2.2)
thread_safe (~> 0.1)
uglifier (2.5.3)
@@ -134,5 +132,4 @@ DEPENDENCIES
sdoc (~> 0.4.0)
spring
sqlite3
- turbolinks
uglifier (>= 1.3.0)
diff --git a/source/app/assets/javascripts/application.js b/source/app/assets/javascripts/application.js
index d6925fa..1ca0e3b 100644
--- a/source/app/assets/javascripts/application.js
+++ b/source/app/assets/javascripts/application.js
@@ -12,5 +12,4 @@
//
//= require jquery
//= require jquery_ujs
-//= require turbolinks
//= require_tree .
diff --git a/source/app/controllers/urls_controller.rb b/source/app/controllers/urls_controller.rb
index ef26710..0d6ca07 100644
--- a/source/app/controllers/urls_controller.rb
+++ b/source/app/controllers/urls_controller.rb
@@ -1,2 +1,37 @@
class UrlsController < ApplicationController
+
+ # GET /urls
+ def index
+ @urls = Url.all
+ @url = Url.new
+ end
+
+ # POST /urls
+ def create
+ @url = Url.new(url_params)
+
+ respond_to do |format|
+ if @url.save
+ format.html { redirect_to root_path, notice: 'Url was successfully created.' }
+ else
+ format.html { redirect_to root_path, notice: @url.errors.full_messages }
+ end
+ end
+ end
+
+ # GET /:shortened_url
+ def redirect
+ @url = Url.where(shortened_url: params[:shortened_url]).take
+ if @url != nil
+ @url.update_attribute(:click_count, @url.click_count + 1)
+ redirect_to @url.original_url
+ else
+ redirect_to root_path, notice: 'We couldn\'t find a link for the bitly URL you clicked.'
+ end
+ end
+
+ private
+ def url_params
+ params.require(:url).permit(:original_url, :shortened_url, :click_count)
+ end
end
diff --git a/source/app/models/url.rb b/source/app/models/url.rb
new file mode 100644
index 0000000..a81ec9e
--- /dev/null
+++ b/source/app/models/url.rb
@@ -0,0 +1,41 @@
+require 'uri'
+require 'net/http'
+
+class Url < ActiveRecord::Base
+ ALPHANUMERIC_CHARACTERS = (('a'..'z').to_a + ('A'..'Z').to_a + ('0'..'9').to_a)
+
+ validates_presence_of :original_url
+ validates_format_of :original_url, :with => URI::regexp, :message => "must be a valid Ruby URI"
+ validate :original_url_starts_with_http_or_https
+ validate :original_url_must_return_a_response
+
+ before_save :shorten_url
+
+ def original_url_starts_with_http_or_https
+ if not original_url =~ /^https?:\/\//
+ errors.add(:original_url, "must start with http:// or https://")
+ end
+ end
+
+ def original_url_must_return_a_response
+ return unless original_url.present? && original_url =~ URI::regexp(['http', 'https'])
+ uri = URI.parse(original_url)
+ response = Net::HTTP.get_response(uri)
+ rescue URI::InvalidURIError
+ errors.add(:original_url, "must respond to a HTTP request")
+ rescue Errno::ECONNREFUSED
+ errors.add(:original_url, "must respond to a HTTP request")
+ rescue SocketError
+ errors.add(:original_url, "must respond to a HTTP request")
+ end
+
+ def shorten_url
+ self.shortened_url = generate_key unless self.shortened_url
+ end
+
+ def generate_key
+ key = ""
+ 7.times { key << ALPHANUMERIC_CHARACTERS.sample }
+ key
+ end
+end
diff --git a/source/app/views/layouts/application.html.erb b/source/app/views/layouts/application.html.erb
index f946432..d5124e5 100644
--- a/source/app/views/layouts/application.html.erb
+++ b/source/app/views/layouts/application.html.erb
@@ -2,8 +2,8 @@
Source
- <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
- <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
+ <%= stylesheet_link_tag 'application', media: 'all' %>
+ <%= javascript_include_tag 'application' %>
<%= csrf_meta_tags %>
diff --git a/source/app/views/urls/_form.html.erb b/source/app/views/urls/_form.html.erb
new file mode 100644
index 0000000..2324492
--- /dev/null
+++ b/source/app/views/urls/_form.html.erb
@@ -0,0 +1,19 @@
+<%= form_for(@url) do |f| %>
+ <% if @url.errors.any? %>
+
+
<%= pluralize(@url.errors.count, "error") %> prohibited this url from being saved:
+
+
+ <% @url.errors.full_messages.each do |message| %>
+ - <%= message %>
+ <% end %>
+
+
+ <% end %>
+
+
+ <%= f.text_field :original_url %>
+ <%= f.hidden_field :click_count, value: 0 %>
+ <%= f.submit 'Shorten' %>
+
+<% end %>
diff --git a/source/app/views/urls/index.html.erb b/source/app/views/urls/index.html.erb
new file mode 100644
index 0000000..8494a87
--- /dev/null
+++ b/source/app/views/urls/index.html.erb
@@ -0,0 +1,27 @@
+Shorten a link
+
+<%= render 'form' %>
+
+
+
+<%= notice %>
+
+Your shortened links
+
+
+
+ <% @urls.each do |url| %>
+
+ | <%= url.original_url %> |
+
+
+ | <%= link_to "http://localhost:3000/#{url.shortened_url}", "http://localhost:3000/#{url.shortened_url}" %> |
+ |
+ Clicks: <%= url.click_count %> |
+
+
+ | |
+
+ <% end %>
+
+
diff --git a/source/config/routes.rb b/source/config/routes.rb
index 3f66539..fe0566b 100644
--- a/source/config/routes.rb
+++ b/source/config/routes.rb
@@ -1,56 +1,5 @@
Rails.application.routes.draw do
- # The priority is based upon order of creation: first created -> highest priority.
- # See how all your routes lay out with "rake routes".
-
- # You can have the root of your site routed with "root"
- # root 'welcome#index'
-
- # Example of regular route:
- # get 'products/:id' => 'catalog#view'
-
- # Example of named route that can be invoked with purchase_url(id: product.id)
- # get 'products/:id/purchase' => 'catalog#purchase', as: :purchase
-
- # Example resource route (maps HTTP verbs to controller actions automatically):
- # resources :products
-
- # Example resource route with options:
- # resources :products do
- # member do
- # get 'short'
- # post 'toggle'
- # end
- #
- # collection do
- # get 'sold'
- # end
- # end
-
- # Example resource route with sub-resources:
- # resources :products do
- # resources :comments, :sales
- # resource :seller
- # end
-
- # Example resource route with more complex sub-resources:
- # resources :products do
- # resources :comments
- # resources :sales do
- # get 'recent', on: :collection
- # end
- # end
-
- # Example resource route with concerns:
- # concern :toggleable do
- # post 'toggle'
- # end
- # resources :posts, concerns: :toggleable
- # resources :photos, concerns: :toggleable
-
- # Example resource route within a namespace:
- # namespace :admin do
- # # Directs /admin/products/* to Admin::ProductsController
- # # (app/controllers/admin/products_controller.rb)
- # resources :products
- # end
+ resources :urls, only: [:index, :create]
+ get '/:shortened_url', to: 'urls#redirect'
+ root 'urls#index'
end
diff --git a/source/db/migrate/20180125164843_create_urls.rb b/source/db/migrate/20180125164843_create_urls.rb
new file mode 100644
index 0000000..a7067ea
--- /dev/null
+++ b/source/db/migrate/20180125164843_create_urls.rb
@@ -0,0 +1,10 @@
+class CreateUrls < ActiveRecord::Migration
+ def change
+ create_table :urls do |t|
+ t.string :original_url
+ t.string :shortened_url
+
+ t.timestamps
+ end
+ end
+end
diff --git a/source/db/migrate/20180125194335_add_click_count_to_urls.rb b/source/db/migrate/20180125194335_add_click_count_to_urls.rb
new file mode 100644
index 0000000..8e0eda3
--- /dev/null
+++ b/source/db/migrate/20180125194335_add_click_count_to_urls.rb
@@ -0,0 +1,5 @@
+class AddClickCountToUrls < ActiveRecord::Migration
+ def change
+ add_column :urls, :click_count, :integer
+ end
+end
diff --git a/source/db/schema.rb b/source/db/schema.rb
new file mode 100644
index 0000000..d95b2ed
--- /dev/null
+++ b/source/db/schema.rb
@@ -0,0 +1,24 @@
+# encoding: UTF-8
+# This file is auto-generated from the current state of the database. Instead
+# of editing this file, please use the migrations feature of Active Record to
+# incrementally modify your database, and then regenerate this schema definition.
+#
+# Note that this schema.rb definition is the authoritative source for your
+# database schema. If you need to create the application database on another
+# system, you should be using db:schema:load, not running all the migrations
+# from scratch. The latter is a flawed and unsustainable approach (the more migrations
+# you'll amass, the slower it'll run and the greater likelihood for issues).
+#
+# It's strongly recommended that you check this file into your version control system.
+
+ActiveRecord::Schema.define(version: 20180125194335) do
+
+ create_table "urls", force: true do |t|
+ t.string "original_url"
+ t.string "shortened_url"
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ t.integer "click_count"
+ end
+
+end