# Terminal bin/rails g mannequin short_url slug target_url clicks_count:integer bin/rails g controller short_urls index new create
# config/routes.rb
Rails.software.routes.draw do
sources :short_urls, solely: %i[index new create]
root to: "short_urls#index"
get "u/:slug" => "redirects#present", as: :quick
# Outline your software routes per the DSL in https://guides.rubyonrails.org/routing.html
# Reveal well being standing on /up that returns 200 if the app boots with no exceptions, in any other case 500.
# Can be utilized by load balancers and uptime displays to confirm that the app is stay.
get "up" => "rails/well being#present", as: :rails_health_check
# Render dynamic PWA recordsdata from app/views/pwa/* (bear in mind to hyperlink manifest in software.html.erb)
# get "manifest" => "rails/pwa#manifest", as: :pwa_manifest
# get "service-worker" => "rails/pwa#service_worker", as: :pwa_service_worker
# Defines the foundation path route ("https://www.driftingruby.com/")
# root "posts#index"
finish
# app/controllers/short_urls_controller.rb
class ShortUrlsController < ApplicationController
def index
@short_urls = ShortUrl.order(created_at: :desc)
finish
def new
@short_url = ShortUrl.new
finish
def create
@short_url = ShortUrl.new(short_url_params)
if @short_url.save
redirect_to short_urls_path, discover: "Quick hyperlink created."
else
render :new, standing: :unprocessable_content
finish
finish
non-public
def short_url_params
params.count on(short_url: [ :target_url ])
finish
finish
# app/fashions/short_url.rb
class ShortUrl < ApplicationRecord
attribute :slug, :string, default: -> { SecureRandom.alphanumeric(5) }
validates :slug, presence: true, uniqueness: true
validates :target_url, presence: true
validate :target_url_must_be_http
def to_param = slug
non-public
def target_url_must_be_http
return if target_url.clean?
uri = URI.parse(target_url)
errors.add(:target_url, "have to be an http or https URL") except uri.is_a?(URI::HTTP) && uri.host.current?
rescue URI::InvalidURIError
errors.add(:target_url, "is just not a sound URL")
finish
finish
# app/controllers/redirects_controller.rb
class RedirectsController < ApplicationController
def present
short_url = ShortUrl.find_by!(slug: params[:slug])
short_url.increment!(:clicks_count)
redirect_to short_url.target_url, allow_other_host: true # , standing: :moved_permanently
finish
finish
# config/software.rb config.action_controller.allowed_redirect_hosts = [ "docs.example.com", /A.*.example.comz/ ] config.action_controller.action_on_open_redirect = :log # or :notify or :error (default)
# app/views/short_urls/index.html.erb
<% content_for :title, "Quick Hyperlinks" %>
<div class="flex items-center justify-between mb-6">
<h1 class="font-bold text-4xl">Quick Hyperlinks</h1>
<%= link_to "New Quick Hyperlink", new_short_url_path, class: "bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded" %>
</div>
<desk class="w-full text-left">
<thead>
<tr class="border-b-2 border-slate-300">
<th class="py-2">Quick Hyperlink</th>
<th class="py-2">Vacation spot</th>
<th class="py-2 text-right">Clicks</th>
</tr>
</thead>
<tbody>
<% @short_urls.every do |hyperlink| %>
<tr class="border-b border-slate-200">
<td class="py-2 font-mono"><%= link_to short_url(hyperlink.slug), short_path(hyperlink.slug), goal: "_blank", class: "text-blue-600 hover:underline" %></td>
<td class="py-2 truncate max-w-md"><%= hyperlink.target_url %></td>
<td class="py-2 text-right"><%= hyperlink.clicks_count %></td>
</tr>
<% finish %>
</tbody>
</desk>
# app/views/short_urls/new.html.erb
<% content_for :title, "New Quick Hyperlink" %>
<h1 class="font-bold text-4xl mb-6">New Quick Hyperlink</h1>
<%= form_with mannequin: @short_url, class: "max-w-xl space-y-4" do |type| %>
<% if @short_url.errors.any? %>
<div class="bg-red-500 text-white p-4 rounded">
<% @short_url.errors.full_messages.every do |message| %>
<p><%= message %></p>
<% finish %>
</div>
<% finish %>
<div>
<%= type.label :target_url, "Vacation spot URL", class: "block font-semibold mb-1" %>
<%= type.url_field :target_url, required: true, placeholder: "https://www.driftingruby.com", class: "w-full border border-slate-400 rounded px-3 py-2" %>
</div>
<div class="flex items-center gap-4">
<%= type.submit "Shorten", class: "bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded cursor-pointer" %>
<%= link_to "Cancel", short_urls_path, class: "text-gray-700 hover:text-gray-900" %>
</div>
<% finish %>

