Sha256: 86b7c2bb9017dd48b98b4cc2438893d4192dcb9229427df4a745b022f28086ec
Contents?: true
Size: 1.94 KB
Versions: 1
Compression:
Stored size: 1.94 KB
Contents
# frozen_string_literal: true require "active_record" require "addressable" require "digest/sha2" require "rack" require "securerandom" module Tanshuku class Url < ActiveRecord::Base MAX_URL_LENGTH = 10_000 URL_PATTERN = %r{\A(?:https?:/)?/\w+} KEY_LENGTH = 20 validates :url, :hashed_url, :key, presence: true validates :url, length: { maximum: MAX_URL_LENGTH } validates :url, format: { with: URL_PATTERN } # Don't validate uniqueness of unique attributes. Raise ActiveRecord::RecordNotUnique instead if the attributes get # duplicated. Then rescue the exception and try to retry. # validates :url, :hashed_url, :key, uniqueness: true def self.shorten(original_url, retries: 0) url = normalize_url(original_url) record = create_or_find_by!(hashed_url: hash_url(url)) do |r| r.attributes = { url:, key: generate_key } end record.shortened_url rescue ActiveRecord::RecordNotUnique => e if retries < 10 shorten(url, retries: retries + 1) else report_exception(exception: e, original_url:) original_url end rescue StandardError => e report_exception(exception: e, original_url:) original_url end # Normalize a trailing slash, `?` for an empty query, and so on, and sort query keys. def self.normalize_url(url) parsed_url = Addressable::URI.parse(url) parsed_url.query_values = Rack::Utils.parse_query(parsed_url.query) parsed_url.normalize.to_s end def self.hash_url(url) Digest::SHA512.hexdigest(url) end def self.generate_key SecureRandom.alphanumeric(KEY_LENGTH) end def self.report_exception(exception:, original_url:) logger.warn("Tanshuku - Failed to shorten a URL: #{exception.inspect} for #{original_url.inspect}") end def shortened_url Tanshuku::Engine.routes.url_for(controller: "tanshuku/urls", action: :show, key:) end end end
Version data entries
1 entries across 1 versions & 1 rubygems
Version | Path |
---|---|
tanshuku-0.0.5 | app/models/tanshuku/url.rb |