Class: Tanshuku::Url
- Inherits:
-
ActiveRecord::Base
- Object
- ActiveRecord::Base
- Tanshuku::Url
- Defined in:
- app/models/tanshuku/url.rb
Overview
rubocop:disable Rails/ApplicationRecord
An ActiveRecord::Base
inherited class for a shortened URL. This class also have some logics for shortening URLs.
Constant Summary collapse
- DEFAULT_NAMESPACE =
""
Instance Attribute Summary collapse
-
#created_at ⇒ ActiveSupport::TimeWithZone
A timestamp when the record is created.
-
#hashed_url ⇒ String
private
A hashed string of the record’s original URL.
-
#key ⇒ String
A unique key for the record.
-
#url ⇒ String
Original, i.e., non-shortened, URL of the record.
Class Method Summary collapse
-
.find_by_url(url, namespace: DEFAULT_NAMESPACE) ⇒ Tanshuku::Url?
Finds a Url record by a non-shortened URL.
-
.generate_key ⇒ String
Generates a unique key for a shortened URL.
-
.hash_url(url, namespace: DEFAULT_NAMESPACE) ⇒ String
Hashes a URL.
-
.normalize_url(url) ⇒ String
Normalizes a URL.
-
.report_exception(exception:, original_url:) ⇒ void
Reports an exception when failed to shorten a URL.
-
.shorten(original_url, namespace: DEFAULT_NAMESPACE, url_options: {}) ⇒ String
Shortens a URL.
Instance Method Summary collapse
-
#shortened_url(url_options = {}) ⇒ String
The record’s shortened URL.
Instance Attribute Details
#created_at ⇒ ActiveSupport::TimeWithZone
Returns A timestamp when the record is created.
26 |
# File 'app/models/tanshuku/url.rb', line 26 DEFAULT_NAMESPACE = "" |
#hashed_url ⇒ String
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This attribute is used for uniqueness of the original URL.
Returns A hashed string of the record’s original URL.
26 |
# File 'app/models/tanshuku/url.rb', line 26 DEFAULT_NAMESPACE = "" |
#key ⇒ String
Returns A unique key for the record.
26 |
# File 'app/models/tanshuku/url.rb', line 26 DEFAULT_NAMESPACE = "" |
#url ⇒ String
Returns Original, i.e., non-shortened, URL of the record.
26 |
# File 'app/models/tanshuku/url.rb', line 26 DEFAULT_NAMESPACE = "" |
Class Method Details
.find_by_url(url, namespace: DEFAULT_NAMESPACE) ⇒ Tanshuku::Url?
Finds a Tanshuku::Url record by a non-shortened URL.
113 114 115 116 117 118 |
# File 'app/models/tanshuku/url.rb', line 113 def self.find_by_url(url, namespace: DEFAULT_NAMESPACE) normalized_url = normalize_url(url) hashed_url = hash_url(normalized_url, namespace:) find_by(hashed_url:) end |
.generate_key ⇒ String
This method calls Configuration#key_generator’s call
and returns its return value.
Generates a unique key for a shortened URL.
149 150 151 |
# File 'app/models/tanshuku/url.rb', line 149 def self.generate_key Tanshuku.config.key_generator.call end |
.hash_url(url, namespace: DEFAULT_NAMESPACE) ⇒ String
This method calls Configuration#url_hasher’s call
and returns its return value.
Hashes a URL.
140 141 142 |
# File 'app/models/tanshuku/url.rb', line 140 def self.hash_url(url, namespace: DEFAULT_NAMESPACE) Tanshuku.config.url_hasher.call(url, namespace:) end |
.normalize_url(url) ⇒ String
Normalizes a URL. Adds or removes a trailing slash, removes ? for an empty query, and so on. And sorts query keys.
126 127 128 129 130 |
# File 'app/models/tanshuku/url.rb', line 126 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 |
.report_exception(exception:, original_url:) ⇒ void
This method calls Configuration#exception_reporter’s call
and returns its return value.
This method returns an undefined value.
Reports an exception when failed to shorten a URL.
161 162 163 |
# File 'app/models/tanshuku/url.rb', line 161 def self.report_exception(exception:, original_url:) Tanshuku.config.exception_reporter.call(exception:, original_url:) end |
.shorten(original_url, namespace: DEFAULT_NAMESPACE, url_options: {}) ⇒ String
If a Tanshuku::Url record already exists, no additional record will be created and the existing record will be used.
The given URL will be normalized before shortening. So for example, shorten(“google.com/”) and shorten(“google.com”) have the same result.
Shortens a URL. Builds and saves a Tanshuku::Url record with generating a unique key for the given URL and namespace. Then returns the record’s shortened URL with the given URL options.
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'app/models/tanshuku/url.rb', line 76 def self.shorten(original_url, namespace: DEFAULT_NAMESPACE, url_options: {}) raise ArgumentError, "original_url should be present" unless original_url url = normalize_url(original_url) retries = 0 begin transaction do record = create_or_find_by!(hashed_url: hash_url(url, namespace:)) do |r| r.attributes = { url:, key: generate_key } end record.shortened_url() end # ActiveRecord::RecordNotFound is raised when the key is duplicated. rescue ActiveRecord::RecordNotFound => e if retries < 10 retries += 1 retry else report_exception(exception: e, original_url:) original_url end end rescue StandardError => e report_exception(exception: e, original_url:) original_url end |