From 17411e40f0442c9144a38d1bd4ad9ecbdfcfe130 Mon Sep 17 00:00:00 2001 From: Rupert Saxton Date: Tue, 23 Jan 2018 14:37:14 -0500 Subject: [PATCH 1/9] Implement a simple shortener (Release 0) --- source/Gemfile | 2 +- source/Gemfile.lock | 6 ++--- source/app/controllers/urls_controller.rb | 21 ++++++++++++++++++ source/app/helpers/urls_helper.rb | 3 +++ source/app/models/url.rb | 7 ++++++ source/app/views/layouts/application.html.erb | 2 -- source/app/views/urls/index.html.erb | 10 +++++++++ source/app/views/urls/show.html.erb | 0 source/config/routes.rb | 5 +++++ .../db/migrate/20180123175724_create_urls.rb | 9 ++++++++ source/db/schema.rb | 22 +++++++++++++++++++ source/spec/models/url_spec.rb | 5 +++++ 12 files changed, 86 insertions(+), 6 deletions(-) create mode 100644 source/app/models/url.rb create mode 100644 source/app/views/urls/index.html.erb create mode 100644 source/app/views/urls/show.html.erb create mode 100644 source/db/migrate/20180123175724_create_urls.rb create mode 100644 source/db/schema.rb create mode 100644 source/spec/models/url_spec.rb diff --git a/source/Gemfile b/source/Gemfile index 9627b8b..69c6692 100644 --- a/source/Gemfile +++ b/source/Gemfile @@ -17,7 +17,7 @@ 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' +# 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. diff --git a/source/Gemfile.lock b/source/Gemfile.lock index fcf8b98..be7dbc0 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,7 @@ DEPENDENCIES sdoc (~> 0.4.0) spring sqlite3 - turbolinks uglifier (>= 1.3.0) + +BUNDLED WITH + 1.16.1 diff --git a/source/app/controllers/urls_controller.rb b/source/app/controllers/urls_controller.rb index ef26710..297861c 100644 --- a/source/app/controllers/urls_controller.rb +++ b/source/app/controllers/urls_controller.rb @@ -1,2 +1,23 @@ class UrlsController < ApplicationController + require 'uri' + include UrlsHelper + + def index + @urls = Url.all + @url = Url.new(address: "https://") + end + + def create + @url = Url.new(url_params) + if @url.save + redirect_to root_path + else + render 'index' + end + end + + def show + @url = Url.find(params[:id]) + redirect_to @url.address + end end diff --git a/source/app/helpers/urls_helper.rb b/source/app/helpers/urls_helper.rb index 83216b1..2224082 100644 --- a/source/app/helpers/urls_helper.rb +++ b/source/app/helpers/urls_helper.rb @@ -1,2 +1,5 @@ module UrlsHelper + def url_params + params.require(:url).permit(:address) + end end diff --git a/source/app/models/url.rb b/source/app/models/url.rb new file mode 100644 index 0000000..b2f1e8d --- /dev/null +++ b/source/app/models/url.rb @@ -0,0 +1,7 @@ +class Url < ActiveRecord::Base + before_save :generate_shortened_url + + def generate_shortened_url + + end +end diff --git a/source/app/views/layouts/application.html.erb b/source/app/views/layouts/application.html.erb index f946432..b3995a2 100644 --- a/source/app/views/layouts/application.html.erb +++ b/source/app/views/layouts/application.html.erb @@ -2,8 +2,6 @@ Source - <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %> - <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %> <%= csrf_meta_tags %> diff --git a/source/app/views/urls/index.html.erb b/source/app/views/urls/index.html.erb new file mode 100644 index 0000000..07b8d42 --- /dev/null +++ b/source/app/views/urls/index.html.erb @@ -0,0 +1,10 @@ +

Index Page

+ +<% @urls.each do |url| %> +

<%= url.address %> - <%= "#{request.url}#{url.id}" %>

+<% end %> + +<%= form_for @url do |f| %> + <%= f.text_field :address %> + <%= f.submit "Shorten URL" %> +<% end %> \ 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..e69de29 diff --git a/source/config/routes.rb b/source/config/routes.rb index 3f66539..73fab2a 100644 --- a/source/config/routes.rb +++ b/source/config/routes.rb @@ -53,4 +53,9 @@ # # (app/controllers/admin/products_controller.rb) # resources :products # end + root "urls#index" + + resources :urls, only: [:index, :create, :show] + + get '/:id', to: 'urls#show', as: :shortened_url end diff --git a/source/db/migrate/20180123175724_create_urls.rb b/source/db/migrate/20180123175724_create_urls.rb new file mode 100644 index 0000000..fb4a6f4 --- /dev/null +++ b/source/db/migrate/20180123175724_create_urls.rb @@ -0,0 +1,9 @@ +class CreateUrls < ActiveRecord::Migration + def change + create_table :urls do |t| + t.string :address + + t.timestamps + end + end +end diff --git a/source/db/schema.rb b/source/db/schema.rb new file mode 100644 index 0000000..304bf44 --- /dev/null +++ b/source/db/schema.rb @@ -0,0 +1,22 @@ +# 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: 20180123175724) do + + create_table "urls", force: true do |t| + t.string "address" + t.datetime "created_at" + t.datetime "updated_at" + end + +end diff --git a/source/spec/models/url_spec.rb b/source/spec/models/url_spec.rb new file mode 100644 index 0000000..209ca4c --- /dev/null +++ b/source/spec/models/url_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe Url, :type => :model do + pending "add some examples to (or delete) #{__FILE__}" +end From 68ee32e31ff1efe4260415371174ce45db1a3999 Mon Sep 17 00:00:00 2001 From: Rupert Saxton Date: Tue, 23 Jan 2018 14:47:06 -0500 Subject: [PATCH 2/9] Add a click_count (Release 1) --- source/app/controllers/urls_controller.rb | 3 +++ source/app/views/urls/index.html.erb | 2 +- source/app/views/urls/show.html.erb | 0 source/db/migrate/20180123194146_add_click_count_to_urls.rb | 5 +++++ source/db/schema.rb | 3 ++- 5 files changed, 11 insertions(+), 2 deletions(-) delete mode 100644 source/app/views/urls/show.html.erb create mode 100644 source/db/migrate/20180123194146_add_click_count_to_urls.rb diff --git a/source/app/controllers/urls_controller.rb b/source/app/controllers/urls_controller.rb index 297861c..d87cf15 100644 --- a/source/app/controllers/urls_controller.rb +++ b/source/app/controllers/urls_controller.rb @@ -9,6 +9,7 @@ def index def create @url = Url.new(url_params) + @url.click_count = 0 if @url.save redirect_to root_path else @@ -18,6 +19,8 @@ def create def show @url = Url.find(params[:id]) + @url.click_count += 1 + @url.save redirect_to @url.address end end diff --git a/source/app/views/urls/index.html.erb b/source/app/views/urls/index.html.erb index 07b8d42..f8a97e5 100644 --- a/source/app/views/urls/index.html.erb +++ b/source/app/views/urls/index.html.erb @@ -1,7 +1,7 @@

Index Page

<% @urls.each do |url| %> -

<%= url.address %> - <%= "#{request.url}#{url.id}" %>

+

<%= url.address %> - <%= "#{request.url}#{url.id}" %> - Clicks: <%= url.click_count %>

<% end %> <%= form_for @url do |f| %> diff --git a/source/app/views/urls/show.html.erb b/source/app/views/urls/show.html.erb deleted file mode 100644 index e69de29..0000000 diff --git a/source/db/migrate/20180123194146_add_click_count_to_urls.rb b/source/db/migrate/20180123194146_add_click_count_to_urls.rb new file mode 100644 index 0000000..f70faec --- /dev/null +++ b/source/db/migrate/20180123194146_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 index 304bf44..e6cac5d 100644 --- a/source/db/schema.rb +++ b/source/db/schema.rb @@ -11,12 +11,13 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20180123175724) do +ActiveRecord::Schema.define(version: 20180123194146) do create_table "urls", force: true do |t| t.string "address" t.datetime "created_at" t.datetime "updated_at" + t.integer "click_count" end end From 87250444a16cc3d14a63ae5151adfe11c5e7e374 Mon Sep 17 00:00:00 2001 From: Rupert Saxton Date: Tue, 23 Jan 2018 16:26:42 -0500 Subject: [PATCH 3/9] Add basic validations and display errors --- source/.byebug_history | 6 +++ source/Gemfile | 4 +- source/Gemfile.lock | 2 + source/app/controllers/urls_controller.rb | 2 +- source/app/models/url.rb | 6 ++- source/app/views/urls/index.html.erb | 8 ++++ source/config/routes.rb | 54 ----------------------- 7 files changed, 24 insertions(+), 58 deletions(-) create mode 100644 source/.byebug_history diff --git a/source/.byebug_history b/source/.byebug_history new file mode 100644 index 0000000..aee08b2 --- /dev/null +++ b/source/.byebug_history @@ -0,0 +1,6 @@ +continue +@url.errors.first.essage +@url.errors.full_messages +@url.errors.each { |error| puts error.full_messages } +@url.errors.each do |error| +@url.errors diff --git a/source/Gemfile b/source/Gemfile index 69c6692..61b9127 100644 --- a/source/Gemfile +++ b/source/Gemfile @@ -36,6 +36,6 @@ gem 'spring', group: :development # gem 'capistrano-rails', group: :development # Use debugger -# gem 'debugger', group: [:development, :test] - gem 'rspec-rails', group: [:development, :test] +gem 'byebug' +gem 'rspec-rails', group: [:development, :test] diff --git a/source/Gemfile.lock b/source/Gemfile.lock index be7dbc0..8145aea 100644 --- a/source/Gemfile.lock +++ b/source/Gemfile.lock @@ -29,6 +29,7 @@ GEM tzinfo (~> 1.1) arel (5.0.1.20140414130214) builder (3.2.2) + byebug (9.1.0) coffee-rails (4.0.1) coffee-script (>= 2.2.0) railties (>= 4.0.0, < 5.0) @@ -123,6 +124,7 @@ PLATFORMS ruby DEPENDENCIES + byebug coffee-rails (~> 4.0.0) jbuilder (~> 2.0) jquery-rails diff --git a/source/app/controllers/urls_controller.rb b/source/app/controllers/urls_controller.rb index d87cf15..f7d1fc3 100644 --- a/source/app/controllers/urls_controller.rb +++ b/source/app/controllers/urls_controller.rb @@ -1,5 +1,4 @@ class UrlsController < ApplicationController - require 'uri' include UrlsHelper def index @@ -13,6 +12,7 @@ def create if @url.save redirect_to root_path else + @urls = Url.all render 'index' end end diff --git a/source/app/models/url.rb b/source/app/models/url.rb index b2f1e8d..0887f57 100644 --- a/source/app/models/url.rb +++ b/source/app/models/url.rb @@ -1,7 +1,11 @@ class Url < ActiveRecord::Base + require 'uri' + before_save :generate_shortened_url - def generate_shortened_url + validates :address, presence: true + validates :address, format: { with: /\Ahttps?:\/\/.*/, message: "must begin with 'http://' or 'https://'" } + def generate_shortened_url end end diff --git a/source/app/views/urls/index.html.erb b/source/app/views/urls/index.html.erb index f8a97e5..1b8ff17 100644 --- a/source/app/views/urls/index.html.erb +++ b/source/app/views/urls/index.html.erb @@ -1,5 +1,13 @@

Index Page

+<% if @url.errors %> + +<% end %> + <% @urls.each do |url| %>

<%= url.address %> - <%= "#{request.url}#{url.id}" %> - Clicks: <%= url.click_count %>

<% end %> diff --git a/source/config/routes.rb b/source/config/routes.rb index 73fab2a..3406f1c 100644 --- a/source/config/routes.rb +++ b/source/config/routes.rb @@ -1,58 +1,4 @@ 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 root "urls#index" resources :urls, only: [:index, :create, :show] From 5afed00baacb94c97b015d52609faba3d656eaff Mon Sep 17 00:00:00 2001 From: Rupert Saxton Date: Wed, 24 Jan 2018 10:45:27 -0500 Subject: [PATCH 4/9] Complete validations (Release 2) --- source/app/models/url.rb | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/source/app/models/url.rb b/source/app/models/url.rb index 0887f57..6ec9953 100644 --- a/source/app/models/url.rb +++ b/source/app/models/url.rb @@ -1,10 +1,29 @@ class Url < ActiveRecord::Base - require 'uri' + require 'net/http' before_save :generate_shortened_url - validates :address, presence: true - validates :address, format: { with: /\Ahttps?:\/\/.*/, message: "must begin with 'http://' or 'https://'" } + validates :address, presence: true, format: { with: /\Ahttps?:\/\/.*/, message: "must begin with 'http://' or 'https://'" } + validate :url_is_correct_format, :url_responds_to_http_request + + def url_is_correct_format + unless address =~ /\A#{URI.regexp}\z/ + errors.add(:address, "is not a valid url format") + end + end + + def url_responds_to_http_request + url = URI.parse(address) + begin + response = Net::HTTP.get_response(url) + + if response.code == "404" + errors.add(:address, "is not accessible via HTTP(S)") + end + rescue + errors.add(:address, "is not accessible via HTTP(S)") + end + end def generate_shortened_url end From a6fe70d031e25aae3425a2c0072b5619e7416890 Mon Sep 17 00:00:00 2001 From: Rupert Saxton Date: Wed, 24 Jan 2018 13:27:50 -0500 Subject: [PATCH 5/9] Apply a more complex method of shortening urls --- source/.byebug_history | 5 ++++ source/app/controllers/urls_controller.rb | 2 +- source/app/models/url.rb | 25 ++++++++++++++++++- source/app/views/urls/index.html.erb | 2 +- source/config/routes.rb | 2 +- ...857_add_shortened_address_suffix_to_url.rb | 5 ++++ ...change_shortened_address_suffix_to_slug.rb | 5 ++++ source/db/schema.rb | 3 ++- 8 files changed, 44 insertions(+), 5 deletions(-) create mode 100644 source/db/migrate/20180124154857_add_shortened_address_suffix_to_url.rb create mode 100644 source/db/migrate/20180124180333_change_shortened_address_suffix_to_slug.rb diff --git a/source/.byebug_history b/source/.byebug_history index aee08b2..bd778e4 100644 --- a/source/.byebug_history +++ b/source/.byebug_history @@ -1,4 +1,9 @@ continue +next +@url +next +@url +continue @url.errors.first.essage @url.errors.full_messages @url.errors.each { |error| puts error.full_messages } diff --git a/source/app/controllers/urls_controller.rb b/source/app/controllers/urls_controller.rb index f7d1fc3..1e49945 100644 --- a/source/app/controllers/urls_controller.rb +++ b/source/app/controllers/urls_controller.rb @@ -18,7 +18,7 @@ def create end def show - @url = Url.find(params[:id]) + @url = Url.find_by(slug: params[:slug]) @url.click_count += 1 @url.save redirect_to @url.address diff --git a/source/app/models/url.rb b/source/app/models/url.rb index 6ec9953..29642c4 100644 --- a/source/app/models/url.rb +++ b/source/app/models/url.rb @@ -3,7 +3,9 @@ class Url < ActiveRecord::Base before_save :generate_shortened_url - validates :address, presence: true, format: { with: /\Ahttps?:\/\/.*/, message: "must begin with 'http://' or 'https://'" } + validates :address, presence: true + validates :address, format: { with: /\Ahttps?:\/\/.*/, message: "must begin with 'http://' or 'https://'" } + validates :address, uniqueness: true validate :url_is_correct_format, :url_responds_to_http_request def url_is_correct_format @@ -26,5 +28,26 @@ def url_responds_to_http_request end def generate_shortened_url + url = URI.parse(address) + if url.host.present? + #Remove 'www.' from start of string if present + stripped_host = url.host.gsub(/\Awww\./, "") || url.host + #Remove top level domain from URL + stripped_host = stripped_host.gsub(/\..*/, "") || stripped_host + #Shorten URL either by removing vowels or halving length if no vowels + shortened_host = stripped_host.gsub(/[aeiou]/, "") || stripped_host[0..(stripped_host.length/2)] + + count = 0 + #This ensures that if a slug exists then a new one is not created + temp_shortened_host = self.slug || shortened_host + #Creates a slug if one doesn't exist + while !self.slug && Url.find_by(slug: temp_shortened_host) + count += 1 + temp_shortened_host = "#{shortened_host}#{count}" + end + self.slug = temp_shortened_host + else + errors.add(:address, "no url host present") + end end end diff --git a/source/app/views/urls/index.html.erb b/source/app/views/urls/index.html.erb index 1b8ff17..89df642 100644 --- a/source/app/views/urls/index.html.erb +++ b/source/app/views/urls/index.html.erb @@ -9,7 +9,7 @@ <% end %> <% @urls.each do |url| %> -

<%= url.address %> - <%= "#{request.url}#{url.id}" %> - Clicks: <%= url.click_count %>

+

<%= url.address %> - <%= "#{request.base_url}/#{url.slug}" %> - Clicks: <%= url.click_count %>

<% end %> <%= form_for @url do |f| %> diff --git a/source/config/routes.rb b/source/config/routes.rb index 3406f1c..c9ee5d6 100644 --- a/source/config/routes.rb +++ b/source/config/routes.rb @@ -3,5 +3,5 @@ resources :urls, only: [:index, :create, :show] - get '/:id', to: 'urls#show', as: :shortened_url + get '/:slug', to: 'urls#show' end diff --git a/source/db/migrate/20180124154857_add_shortened_address_suffix_to_url.rb b/source/db/migrate/20180124154857_add_shortened_address_suffix_to_url.rb new file mode 100644 index 0000000..19a6902 --- /dev/null +++ b/source/db/migrate/20180124154857_add_shortened_address_suffix_to_url.rb @@ -0,0 +1,5 @@ +class AddShortenedAddressSuffixToUrl < ActiveRecord::Migration + def change + add_column :urls, :shortened_address_suffix, :string + end +end diff --git a/source/db/migrate/20180124180333_change_shortened_address_suffix_to_slug.rb b/source/db/migrate/20180124180333_change_shortened_address_suffix_to_slug.rb new file mode 100644 index 0000000..1f00ed0 --- /dev/null +++ b/source/db/migrate/20180124180333_change_shortened_address_suffix_to_slug.rb @@ -0,0 +1,5 @@ +class ChangeShortenedAddressSuffixToSlug < ActiveRecord::Migration + def change + rename_column :urls, :shortened_address_suffix, :slug + end +end diff --git a/source/db/schema.rb b/source/db/schema.rb index e6cac5d..ff14f0a 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: 20180123194146) do +ActiveRecord::Schema.define(version: 20180124180333) do create_table "urls", force: true do |t| t.string "address" t.datetime "created_at" t.datetime "updated_at" t.integer "click_count" + t.string "slug" end end From cd56b61d717a5000cd3a9aac268364199db7c361 Mon Sep 17 00:00:00 2001 From: Rupert Saxton Date: Thu, 25 Jan 2018 12:45:48 -0500 Subject: [PATCH 6/9] Improve shortening algorithm with random strings --- source/.gitignore | 3 ++ source/app/models/url.rb | 31 ++++++------------- source/config/routes.rb | 2 +- .../20180125162712_add_index_to_slug.rb | 5 +++ source/db/schema.rb | 4 ++- 5 files changed, 21 insertions(+), 24 deletions(-) create mode 100644 source/db/migrate/20180125162712_add_index_to_slug.rb diff --git a/source/.gitignore b/source/.gitignore index 6a502e9..e6f33a3 100644 --- a/source/.gitignore +++ b/source/.gitignore @@ -7,6 +7,9 @@ # Ignore bundler config. /.bundle +# Ignore byebug history +/.byebug_history + # Ignore the default SQLite database. /db/*.sqlite3 /db/*.sqlite3-journal diff --git a/source/app/models/url.rb b/source/app/models/url.rb index 29642c4..7781d72 100644 --- a/source/app/models/url.rb +++ b/source/app/models/url.rb @@ -1,5 +1,6 @@ class Url < ActiveRecord::Base require 'net/http' + require 'securerandom' before_save :generate_shortened_url @@ -9,7 +10,7 @@ class Url < ActiveRecord::Base validate :url_is_correct_format, :url_responds_to_http_request def url_is_correct_format - unless address =~ /\A#{URI.regexp}\z/ + unless address =~ /\A#{URI.regexp}\z/ errors.add(:address, "is not a valid url format") end end @@ -28,26 +29,12 @@ def url_responds_to_http_request end def generate_shortened_url - url = URI.parse(address) - if url.host.present? - #Remove 'www.' from start of string if present - stripped_host = url.host.gsub(/\Awww\./, "") || url.host - #Remove top level domain from URL - stripped_host = stripped_host.gsub(/\..*/, "") || stripped_host - #Shorten URL either by removing vowels or halving length if no vowels - shortened_host = stripped_host.gsub(/[aeiou]/, "") || stripped_host[0..(stripped_host.length/2)] - - count = 0 - #This ensures that if a slug exists then a new one is not created - temp_shortened_host = self.slug || shortened_host - #Creates a slug if one doesn't exist - while !self.slug && Url.find_by(slug: temp_shortened_host) - count += 1 - temp_shortened_host = "#{shortened_host}#{count}" - end - self.slug = temp_shortened_host - else - errors.add(:address, "no url host present") - end + #This ensures that if a slug exists then a new one is not created + temp_shortened_host = self.slug || SecureRandom.base64(4) + #Creates a slug if one doesn't exist + while !self.slug && Url.find_by(slug: temp_shortened_host) + temp_shortened_host = SecureRandom.base64(4) + end + self.slug = temp_shortened_host end end diff --git a/source/config/routes.rb b/source/config/routes.rb index c9ee5d6..4ce6c58 100644 --- a/source/config/routes.rb +++ b/source/config/routes.rb @@ -1,7 +1,7 @@ Rails.application.routes.draw do root "urls#index" - resources :urls, only: [:index, :create, :show] + resources :urls, only: [:index, :create] get '/:slug', to: 'urls#show' end diff --git a/source/db/migrate/20180125162712_add_index_to_slug.rb b/source/db/migrate/20180125162712_add_index_to_slug.rb new file mode 100644 index 0000000..b0f62ae --- /dev/null +++ b/source/db/migrate/20180125162712_add_index_to_slug.rb @@ -0,0 +1,5 @@ +class AddIndexToSlug < ActiveRecord::Migration + def change + add_index :urls, :slug + end +end diff --git a/source/db/schema.rb b/source/db/schema.rb index ff14f0a..cf1d9ce 100644 --- a/source/db/schema.rb +++ b/source/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20180124180333) do +ActiveRecord::Schema.define(version: 20180125162712) do create_table "urls", force: true do |t| t.string "address" @@ -21,4 +21,6 @@ t.string "slug" end + add_index "urls", ["slug"], name: "index_urls_on_slug" + end From 5d0649b1eb0ee78285f24c05b07e051a902d8fa3 Mon Sep 17 00:00:00 2001 From: Rupert Saxton Date: Thu, 25 Jan 2018 12:55:48 -0500 Subject: [PATCH 7/9] Update variable names for clarity --- source/app/models/url.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/app/models/url.rb b/source/app/models/url.rb index 7781d72..d7e80dc 100644 --- a/source/app/models/url.rb +++ b/source/app/models/url.rb @@ -30,11 +30,11 @@ def url_responds_to_http_request def generate_shortened_url #This ensures that if a slug exists then a new one is not created - temp_shortened_host = self.slug || SecureRandom.base64(4) + temp_slug = self.slug || SecureRandom.base64(4) #Creates a slug if one doesn't exist - while !self.slug && Url.find_by(slug: temp_shortened_host) - temp_shortened_host = SecureRandom.base64(4) + while !self.slug && Url.find_by(slug: temp_slug) + temp_slug = SecureRandom.base64(4) end - self.slug = temp_shortened_host + self.slug = temp_slug end end From 770b884aadaf54e8e8c7b13ebf7fb7b49d8d14d9 Mon Sep 17 00:00:00 2001 From: Rupert Saxton Date: Tue, 30 Jan 2018 16:39:25 -0500 Subject: [PATCH 8/9] Make changes recommended by MikeGee --- source/app/controllers/urls_controller.rb | 10 ++++++---- .../20180130212955_add_default_value_to_click_count.rb | 5 +++++ source/db/schema.rb | 4 ++-- 3 files changed, 13 insertions(+), 6 deletions(-) create mode 100644 source/db/migrate/20180130212955_add_default_value_to_click_count.rb diff --git a/source/app/controllers/urls_controller.rb b/source/app/controllers/urls_controller.rb index 1e49945..6418c3d 100644 --- a/source/app/controllers/urls_controller.rb +++ b/source/app/controllers/urls_controller.rb @@ -8,7 +8,6 @@ def index def create @url = Url.new(url_params) - @url.click_count = 0 if @url.save redirect_to root_path else @@ -19,8 +18,11 @@ def create def show @url = Url.find_by(slug: params[:slug]) - @url.click_count += 1 - @url.save - redirect_to @url.address + if @url + @url.increment!(:click_count) + redirect_to @url.address + else + redirect_to root_path + end end end diff --git a/source/db/migrate/20180130212955_add_default_value_to_click_count.rb b/source/db/migrate/20180130212955_add_default_value_to_click_count.rb new file mode 100644 index 0000000..042820d --- /dev/null +++ b/source/db/migrate/20180130212955_add_default_value_to_click_count.rb @@ -0,0 +1,5 @@ +class AddDefaultValueToClickCount < ActiveRecord::Migration + def change + change_column :urls, :click_count, :integer, default: 0 + end +end diff --git a/source/db/schema.rb b/source/db/schema.rb index cf1d9ce..90e75a0 100644 --- a/source/db/schema.rb +++ b/source/db/schema.rb @@ -11,13 +11,13 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20180125162712) do +ActiveRecord::Schema.define(version: 20180130212955) do create_table "urls", force: true do |t| t.string "address" t.datetime "created_at" t.datetime "updated_at" - t.integer "click_count" + t.integer "click_count", default: 0 t.string "slug" end From 91eaf7c7aacfee8caca26942a3bf4f6962e5684a Mon Sep 17 00:00:00 2001 From: Rupert Saxton Date: Wed, 31 Jan 2018 10:25:50 -0500 Subject: [PATCH 9/9] Use atomic increment of click_count --- source/app/controllers/urls_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/app/controllers/urls_controller.rb b/source/app/controllers/urls_controller.rb index 6418c3d..664e90d 100644 --- a/source/app/controllers/urls_controller.rb +++ b/source/app/controllers/urls_controller.rb @@ -19,7 +19,7 @@ def create def show @url = Url.find_by(slug: params[:slug]) if @url - @url.increment!(:click_count) + Url.increment_counter(:click_count, @url.id) redirect_to @url.address else redirect_to root_path