From 358202ccb22ba3b70e57533ad27cb686811f63d1 Mon Sep 17 00:00:00 2001 From: David Hatten Date: Wed, 24 Jan 2018 10:36:09 -0500 Subject: [PATCH 1/3] Release 0: Urls are shortened, uses before_save --- .../app/controllers/application_controller.rb | 3 ++ source/app/controllers/urls_controller.rb | 47 +++++++++++++++++++ source/app/models/url.rb | 9 ++++ source/app/views/application/index.html.erb | 4 ++ source/app/views/urls/edit.html.erb | 3 ++ source/app/views/urls/index.html.erb | 21 +++++++++ source/app/views/urls/new.html.erb | 14 ++++++ source/app/views/urls/show.html.erb | 12 +++++ source/config/routes.rb | 6 +++ .../db/migrate/20180123203210_create_urls.rb | 8 ++++ .../20180123215003_add_long_url_to_url.rb | 5 ++ .../20180124143738_add_short_url_to_url.rb | 5 ++ source/db/schema.rb | 23 +++++++++ 13 files changed, 160 insertions(+) create mode 100644 source/app/models/url.rb create mode 100644 source/app/views/application/index.html.erb create mode 100644 source/app/views/urls/edit.html.erb create mode 100644 source/app/views/urls/index.html.erb create mode 100644 source/app/views/urls/new.html.erb create mode 100644 source/app/views/urls/show.html.erb create mode 100644 source/db/migrate/20180123203210_create_urls.rb create mode 100644 source/db/migrate/20180123215003_add_long_url_to_url.rb create mode 100644 source/db/migrate/20180124143738_add_short_url_to_url.rb create mode 100644 source/db/schema.rb diff --git a/source/app/controllers/application_controller.rb b/source/app/controllers/application_controller.rb index d83690e..99ee3ea 100644 --- a/source/app/controllers/application_controller.rb +++ b/source/app/controllers/application_controller.rb @@ -2,4 +2,7 @@ class ApplicationController < ActionController::Base # Prevent CSRF attacks by raising an exception. # For APIs, you may want to use :null_session instead. protect_from_forgery with: :exception + + def index + end end diff --git a/source/app/controllers/urls_controller.rb b/source/app/controllers/urls_controller.rb index ef26710..969c48e 100644 --- a/source/app/controllers/urls_controller.rb +++ b/source/app/controllers/urls_controller.rb @@ -1,2 +1,49 @@ class UrlsController < ApplicationController + def index + @urls = Url.all + end + + def new + + end + + def create + @url = Url.new(url_params) + + if @url.save + redirect_to @url + else + render 'edit' + end + end + + def show + @url = Url.find(params[:id]) + end + + def edit + @url = Url.find(params[:id]) + end + + def destroy + @url = Url.find(params[:id]) + @url.destroy + + redirect_to urls_path + end + + def jump + url = Url.find_by_short_url(params[:key]) + + if url.nil? + redirect_to root_path + else + redirect_to url.long_url + end + end + + private + def url_params + params.require(:url).permit(:long_url) + end end diff --git a/source/app/models/url.rb b/source/app/models/url.rb new file mode 100644 index 0000000..e7be119 --- /dev/null +++ b/source/app/models/url.rb @@ -0,0 +1,9 @@ +class Url < ActiveRecord::Base + before_save :shorten_url + + private + def shorten_url + range = [*'0'..'9',*'A'..'Z',*'a'..'z'] + self.short_url = Array.new(6){ range.sample }.join + end +end diff --git a/source/app/views/application/index.html.erb b/source/app/views/application/index.html.erb new file mode 100644 index 0000000..1e4e6c0 --- /dev/null +++ b/source/app/views/application/index.html.erb @@ -0,0 +1,4 @@ +

URL Shortener Home

+ +<%= link_to 'New Url', new_url_path %>
+<%= link_to 'All Urls', urls_path %> \ No newline at end of file diff --git a/source/app/views/urls/edit.html.erb b/source/app/views/urls/edit.html.erb new file mode 100644 index 0000000..57352a1 --- /dev/null +++ b/source/app/views/urls/edit.html.erb @@ -0,0 +1,3 @@ +

Editing a Url

+ +<%= link_to 'Back', urls_path %> \ No newline at end of file diff --git a/source/app/views/urls/index.html.erb b/source/app/views/urls/index.html.erb new file mode 100644 index 0000000..5eed9f9 --- /dev/null +++ b/source/app/views/urls/index.html.erb @@ -0,0 +1,21 @@ +

Listing Urls:

+ + + + + + + + <% @urls.each do |url| %> + + + + + + + + <% end %> +
Short UrlOriginal Url
<%= url.short_url %><%= url.long_url %><%= link_to 'Show', url_path(url) %><%= link_to 'Edit', edit_url_path(url) %><%= link_to 'Delete', url_path(url), method: :delete, data: {confirm: 'Are you sure?'} %>
+ +<%= link_to 'New Url', new_url_path %>
+<%= link_to 'Home', root_path %> \ No newline at end of file diff --git a/source/app/views/urls/new.html.erb b/source/app/views/urls/new.html.erb new file mode 100644 index 0000000..abf4360 --- /dev/null +++ b/source/app/views/urls/new.html.erb @@ -0,0 +1,14 @@ +

Make a new url here

+ +<%= form_for :url, url: urls_path, local: true do |form| %> +

+ <%= form.label :long_url %> + <%= form.text_field :long_url %> +

+ +

+ <%= form.submit %> +

+<% end %> + +<%= link_to 'Home', root_path %> \ No newline at end of file diff --git a/source/app/views/urls/show.html.erb b/source/app/views/urls/show.html.erb new file mode 100644 index 0000000..76cd0e7 --- /dev/null +++ b/source/app/views/urls/show.html.erb @@ -0,0 +1,12 @@ +

Showing a URL here

+

+ Long Url: + <%= @url.long_url %> +

+ +

+ Short Url: + <%= @url.short_url %> +

+ +<%= link_to 'Home', root_path %> \ No newline at end of file diff --git a/source/config/routes.rb b/source/config/routes.rb index 3f66539..d02b98d 100644 --- a/source/config/routes.rb +++ b/source/config/routes.rb @@ -53,4 +53,10 @@ # # (app/controllers/admin/products_controller.rb) # resources :products # end + # + + get 'application/index' + resources :urls + get '/:key' => 'urls#jump' + root 'application#index' end diff --git a/source/db/migrate/20180123203210_create_urls.rb b/source/db/migrate/20180123203210_create_urls.rb new file mode 100644 index 0000000..7c172a8 --- /dev/null +++ b/source/db/migrate/20180123203210_create_urls.rb @@ -0,0 +1,8 @@ +class CreateUrls < ActiveRecord::Migration + def change + create_table :urls do |t| + + t.timestamps + end + end +end diff --git a/source/db/migrate/20180123215003_add_long_url_to_url.rb b/source/db/migrate/20180123215003_add_long_url_to_url.rb new file mode 100644 index 0000000..9d890a9 --- /dev/null +++ b/source/db/migrate/20180123215003_add_long_url_to_url.rb @@ -0,0 +1,5 @@ +class AddLongUrlToUrl < ActiveRecord::Migration + def change + add_column :urls, :long_url, :text + end +end diff --git a/source/db/migrate/20180124143738_add_short_url_to_url.rb b/source/db/migrate/20180124143738_add_short_url_to_url.rb new file mode 100644 index 0000000..5885fcd --- /dev/null +++ b/source/db/migrate/20180124143738_add_short_url_to_url.rb @@ -0,0 +1,5 @@ +class AddShortUrlToUrl < ActiveRecord::Migration + def change + add_column :urls, :short_url, :text + end +end diff --git a/source/db/schema.rb b/source/db/schema.rb new file mode 100644 index 0000000..e294bce --- /dev/null +++ b/source/db/schema.rb @@ -0,0 +1,23 @@ +# 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: 20180124143738) do + + create_table "urls", force: true do |t| + t.datetime "created_at" + t.datetime "updated_at" + t.text "long_url" + t.text "short_url" + end + +end From 91976cdb5f42c936f6763c51b0038144feabbf44 Mon Sep 17 00:00:00 2001 From: David Hatten Date: Wed, 24 Jan 2018 11:22:57 -0500 Subject: [PATCH 2/3] Release 1, urls have a counter associated with them --- source/app/controllers/urls_controller.rb | 1 + source/app/models/url.rb | 2 +- source/app/views/urls/index.html.erb | 2 ++ source/app/views/urls/show.html.erb | 10 ++++++++-- source/db/migrate/20180124160940_add_count_to_url.rb | 5 +++++ source/db/schema.rb | 3 ++- 6 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 source/db/migrate/20180124160940_add_count_to_url.rb diff --git a/source/app/controllers/urls_controller.rb b/source/app/controllers/urls_controller.rb index 969c48e..d093bdf 100644 --- a/source/app/controllers/urls_controller.rb +++ b/source/app/controllers/urls_controller.rb @@ -38,6 +38,7 @@ def jump if url.nil? redirect_to root_path else + url.update({'click_count': url.click_count + 1}) redirect_to url.long_url end end diff --git a/source/app/models/url.rb b/source/app/models/url.rb index e7be119..6c021ea 100644 --- a/source/app/models/url.rb +++ b/source/app/models/url.rb @@ -4,6 +4,6 @@ class Url < ActiveRecord::Base private def shorten_url range = [*'0'..'9',*'A'..'Z',*'a'..'z'] - self.short_url = Array.new(6){ range.sample }.join + self.short_url = Array.new(6){ range.sample }.join if self.short_url.nil? end end diff --git a/source/app/views/urls/index.html.erb b/source/app/views/urls/index.html.erb index 5eed9f9..d150a87 100644 --- a/source/app/views/urls/index.html.erb +++ b/source/app/views/urls/index.html.erb @@ -3,12 +3,14 @@ + <% @urls.each do |url| %> + diff --git a/source/app/views/urls/show.html.erb b/source/app/views/urls/show.html.erb index 76cd0e7..ac0037f 100644 --- a/source/app/views/urls/show.html.erb +++ b/source/app/views/urls/show.html.erb @@ -1,12 +1,18 @@

Showing a URL here

- Long Url: + Original Url: <%= @url.long_url %>

+

+ Visit Count: + <%= @url.click_count %> +

+

Short Url: <%= @url.short_url %>

-<%= link_to 'Home', root_path %> \ No newline at end of file +<%= link_to 'Back', urls_path %>
+<%= link_to 'Home', root_path %> diff --git a/source/db/migrate/20180124160940_add_count_to_url.rb b/source/db/migrate/20180124160940_add_count_to_url.rb new file mode 100644 index 0000000..8582ba8 --- /dev/null +++ b/source/db/migrate/20180124160940_add_count_to_url.rb @@ -0,0 +1,5 @@ +class AddCountToUrl < ActiveRecord::Migration + def change + add_column :urls, :click_count, :integer, default: 0 + end +end diff --git a/source/db/schema.rb b/source/db/schema.rb index e294bce..a4ed327 100644 --- a/source/db/schema.rb +++ b/source/db/schema.rb @@ -11,13 +11,14 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20180124143738) do +ActiveRecord::Schema.define(version: 20180124160940) do create_table "urls", force: true do |t| t.datetime "created_at" t.datetime "updated_at" t.text "long_url" t.text "short_url" + t.integer "click_count", default: 0 end end From 4cec52aea79afe6471ce7666f804c9c3bb155459 Mon Sep 17 00:00:00 2001 From: David Hatten Date: Wed, 24 Jan 2018 14:08:56 -0500 Subject: [PATCH 3/3] added validation to url input --- source/app/controllers/urls_controller.rb | 6 ++--- source/app/models/url.rb | 27 +++++++++++++++++++++++ source/app/views/urls/new.html.erb | 13 +++++++++++ 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/source/app/controllers/urls_controller.rb b/source/app/controllers/urls_controller.rb index d093bdf..0151246 100644 --- a/source/app/controllers/urls_controller.rb +++ b/source/app/controllers/urls_controller.rb @@ -4,7 +4,7 @@ def index end def new - + @url = Url.new end def create @@ -13,7 +13,7 @@ def create if @url.save redirect_to @url else - render 'edit' + render 'new' end end @@ -38,7 +38,7 @@ def jump if url.nil? redirect_to root_path else - url.update({'click_count': url.click_count + 1}) + url.increment!(:click_count) redirect_to url.long_url end end diff --git a/source/app/models/url.rb b/source/app/models/url.rb index 6c021ea..1a4cce4 100644 --- a/source/app/models/url.rb +++ b/source/app/models/url.rb @@ -1,4 +1,9 @@ +require 'uri' +require 'net/http' + class Url < ActiveRecord::Base + validate :long_url_must_be_valid_uri, :long_url_must_be_reachable + validates :long_url, presence: true before_save :shorten_url private @@ -6,4 +11,26 @@ def shorten_url range = [*'0'..'9',*'A'..'Z',*'a'..'z'] self.short_url = Array.new(6){ range.sample }.join if self.short_url.nil? end + + def long_url_must_be_valid_uri + return if long_url.empty? + + unless long_url =~ /\A#{URI.regexp(['http', 'https'])}\z/ + errors.add(:long_url, "must be a valid url prefaced with http(s)://") + end + end + + def long_url_must_be_reachable + return if long_url.empty? + + url = URI.parse(long_url) + http = Net::HTTP.new(url.host, url.port) + http.read_timeout = 1 + http.start { |http| + http.get(url) + } + + rescue + errors.add(:long_url, "must be a reachable url") + end end diff --git a/source/app/views/urls/new.html.erb b/source/app/views/urls/new.html.erb index abf4360..16104bd 100644 --- a/source/app/views/urls/new.html.erb +++ b/source/app/views/urls/new.html.erb @@ -1,6 +1,19 @@

Make a new url here

<%= form_for :url, url: urls_path, local: true do |form| %> + <% if @url.errors.any? %> +
+

+ <%= pluralize(@url.errors.count, "error") %> prohibited this url from being saved: +

+
    + <%= @url.errors.full_messages.each do |msg| %> +
  • <%= msg %>
  • + <% end %> +
+
+ <% end %> +

<%= form.label :long_url %> <%= form.text_field :long_url %>

Short UrlTimes Visited Original Url
<%= url.short_url %><%= url.click_count %> <%= url.long_url %> <%= link_to 'Show', url_path(url) %> <%= link_to 'Edit', edit_url_path(url) %>