From f616795d6e548fb58eb840c8d4e5ebf7b08f4f63 Mon Sep 17 00:00:00 2001 From: Jesse Doyle Date: Thu, 14 Nov 2024 22:07:14 -0700 Subject: [PATCH] feat: Custom Tracking Strategies Previously customizing the tracking strategy required monkey patching core methods such as `Shortener::ShortenedUrl#increment_usage_count`. Some implementations may want to easily configure the URL tracking strategy, or disable it entirely. This commit adds a new configuration option to specify the behaviour, with a default value that does not break existing functionality. The strategy can be configured as follows: ```ruby Shortener.increment_usage_count = ->(url) do MyBackgroundJob.perform_later(url) end ``` --- README.rdoc | 27 +++++++++++++++++---------- app/models/shortener/shortened_url.rb | 2 +- lib/shortener.rb | 7 +++++++ spec/models/shortened_url_spec.rb | 16 ++++++++++++++++ 4 files changed, 41 insertions(+), 11 deletions(-) diff --git a/README.rdoc b/README.rdoc index be2a838..4628c4c 100644 --- a/README.rdoc +++ b/README.rdoc @@ -106,6 +106,18 @@ You can control this option if it interferes for any of your logic. One common c Shortener.auto_clean_url = true +By default, Shortener will track utilization of shortened URLs. This value is stored as an integer in the +use_count+ column. +You can override this behaviour as necessary for your application: + + Shortener.increment_usage_count = ->(url) do + # move the operation to a background job (your application defines the job class) + UrlTrackingJob.perform_later(url) + end + +Alternatively tracking can be disabled entirely with the following configuration: + + Shortener.increment_usage_count = ->(_url) {} # turn into a no-op + == Usage To generate a Shortened URL object for the URL "http://example.com" within your controller / models do the following: @@ -268,20 +280,15 @@ You can store a `shortened_urls` table in another database and connecting to it === Configuring Reader and Writer Multi-DB Roles -Shortener has one write operation that happens on a GET request. To allow this you can override this method in an initializer. +By default shortener will perform one write operation per GET request. You can configure a custom database role as follows: - module ShortenerWriterMonkeyPatch - def increment_usage_count - ActiveRecord::Base.connected_to(role: :writing) do - self.class.increment_counter(:use_count, id) - end + # config/initializers/shortener.rb + Shortener.increment_usage_count = ->(url) do + ActiveRecord::Base.connected_to(role: :writing) do + url.class.increment_counter(:use_count, url.id) end end - ActiveSupport.on_load(:shortener_shortened_url) do - Shortener::ShortenedUrl.prepend(ShortenerWriterMonkeyPatch) - end - == Contributing We welcome new contributors. Because we're all busy people, and because Shortener diff --git a/app/models/shortener/shortened_url.rb b/app/models/shortener/shortened_url.rb index b557ec8..9820f16 100644 --- a/app/models/shortener/shortened_url.rb +++ b/app/models/shortener/shortened_url.rb @@ -117,7 +117,7 @@ def self.merge_params_to_url(url: nil, params: {}) end def increment_usage_count - self.class.increment_counter(:use_count, id) + Shortener.increment_usage_count.call(self) end def to_param diff --git a/lib/shortener.rb b/lib/shortener.rb index 84ade2c..870a0b0 100644 --- a/lib/shortener.rb +++ b/lib/shortener.rb @@ -45,6 +45,13 @@ module Shortener mattr_accessor :auto_clean_url self.auto_clean_url = true + # increment_usage_count - strategy used to increment usage count, defined as + # a lambda that accepts the Shortener::ShortenedUrl record as an argument + mattr_accessor :increment_usage_count + self.increment_usage_count = ->(url) do + url.class.increment_counter(:use_count, url.id) + end + def self.key_chars charset.is_a?(Symbol) ? CHARSETS[charset] : charset end diff --git a/spec/models/shortened_url_spec.rb b/spec/models/shortened_url_spec.rb index 5b520fc..dd1df7c 100644 --- a/spec/models/shortened_url_spec.rb +++ b/spec/models/shortened_url_spec.rb @@ -229,11 +229,27 @@ describe '#increment_usage_count' do let(:url) { 'https://example.com'} let(:short_url) { Shortener::ShortenedUrl.generate!(url) } + it 'increments the use_count on the shortenedLink' do original_count = short_url.use_count short_url.increment_usage_count expect(short_url.reload.use_count).to eq (original_count + 1) end + + context 'with usage count disabled' do + around(:each) do |example| + original = Shortener.increment_usage_count + Shortener.increment_usage_count = ->(_record) {} # no-op + example.run + Shortener.increment_usage_count = original + end + + it 'returns the original usage count' do + original_count = short_url.use_count + short_url.increment_usage_count + expect(short_url.reload.use_count).to eq(original_count) + end + end end describe '#merge_params_to_url' do