rails_url_shortener 0.2.2 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +10 -0
- data/Rakefile +23 -5
- data/app/controllers/rails_url_shortener/urls_controller.rb +2 -0
- data/app/helpers/rails_url_shortener/urls_helper.rb +4 -2
- data/app/jobs/rails_url_shortener/application_job.rb +2 -0
- data/app/jobs/rails_url_shortener/ip_crawler_job.rb +14 -8
- data/app/models/rails_url_shortener/application_record.rb +2 -0
- data/app/models/rails_url_shortener/ipgeo.rb +3 -1
- data/app/models/rails_url_shortener/url.rb +12 -10
- data/app/models/rails_url_shortener/visit.rb +13 -7
- data/db/migrate/20220418184647_create_rails_url_shortener_ipgeos.rb +1 -0
- data/lib/generators/rails_url_shortener/rails_url_shortener_generator.rb +4 -4
- data/lib/generators/rails_url_shortener/templates/initializer.rb +6 -4
- data/lib/rails_url_shortener/engine.rb +2 -0
- data/lib/rails_url_shortener/version.rb +3 -1
- data/lib/rails_url_shortener.rb +6 -6
- data/lib/tasks/rails_url_shortener_tasks.rake +1 -0
- metadata +7 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6aeebf6acccb2b42410986eb0328a509bebf98a1615a60836804f8c62e525ecf
|
4
|
+
data.tar.gz: 7a08775acadc07b9d0a12286056a02f496db98eebe6e87bc913c91d230f60d82
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b38105a3f020cbf8304bf8a19f9db19c4ff6e1aa4b7f6364060a54d10d0d5d97094d17d39e2b96b0002325fe03816b899eb8a021f3bfa015186e93c871f1a08e
|
7
|
+
data.tar.gz: 500fc4916e53ce218043ba388c9302f9010f614adf4ac90bb790b835792bb381192181eeb8beff8c8dd93825d736785cac84edf208843d1c2e67c6c712769020
|
data/README.md
CHANGED
@@ -15,6 +15,7 @@ A few of the things you can do with RailsUrlShortener:
|
|
15
15
|
* The short links can be associated with a model in your app.
|
16
16
|
* Save interesting things like browser, system and ip data of the 'un-shortened' request.
|
17
17
|
* Temporal short links using the expires_at option.
|
18
|
+
* Get IP data from third part service.
|
18
19
|
|
19
20
|
## Usage
|
20
21
|
|
@@ -80,6 +81,15 @@ Or using the model class:
|
|
80
81
|
RailsUrlShortener::Visit.all # all in database
|
81
82
|
```
|
82
83
|
|
84
|
+
And a Visit is related to a Ipgeo model that contain information about the ip, so you can view this using the active record relation:
|
85
|
+
```ruby
|
86
|
+
RailsUrlShortener::Visit.first.ipgeo # Ipgeo object that contain information of the ip
|
87
|
+
```
|
88
|
+
|
89
|
+
### Ip data
|
90
|
+
|
91
|
+
When a Visit record is created, a job is enqueue for get Ip data from [this](https://ip-api.com/) service and create the Ipgeo record. It is integrated to the free endpoint, so if you think that you have more than 45 different IPS querying in a minute to your app, we need to think in a new solution.
|
92
|
+
|
83
93
|
## Installation
|
84
94
|
|
85
95
|
Add this line to your application's Gemfile:
|
data/Rakefile
CHANGED
@@ -1,8 +1,26 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
load "rails/tasks/engine.rake"
|
3
|
+
require 'bundler/setup'
|
5
4
|
|
6
|
-
|
5
|
+
APP_RAKEFILE = File.expand_path('test/dummy/Rakefile', __dir__)
|
6
|
+
load 'rails/tasks/engine.rake'
|
7
7
|
|
8
|
-
|
8
|
+
load 'rails/tasks/statistics.rake'
|
9
|
+
|
10
|
+
require 'bundler/gem_tasks'
|
11
|
+
require 'rake/testtask'
|
12
|
+
|
13
|
+
Rake::TestTask.new(:test) do |t|
|
14
|
+
t.warning = false
|
15
|
+
t.libs << 'test'
|
16
|
+
t.libs << 'lib'
|
17
|
+
t.test_files = FileList['test/**/*test.rb']
|
18
|
+
end
|
19
|
+
|
20
|
+
require 'rubocop/rake_task'
|
21
|
+
|
22
|
+
RuboCop::RakeTask.new do |task|
|
23
|
+
task.requires << 'rubocop-minitest'
|
24
|
+
end
|
25
|
+
|
26
|
+
task default: %i[test rubocop]
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RailsUrlShortener
|
2
4
|
module UrlsHelper
|
3
5
|
##
|
@@ -19,8 +21,8 @@ module RailsUrlShortener
|
|
19
21
|
if url_object.errors.empty?
|
20
22
|
# options for url_for
|
21
23
|
options = {
|
22
|
-
controller:
|
23
|
-
action:
|
24
|
+
controller: 'rails_url_shortener/urls',
|
25
|
+
action: 'show',
|
24
26
|
key: url_object.key,
|
25
27
|
host: RailsUrlShortener.host
|
26
28
|
}.merge(url_options)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RailsUrlShortener
|
2
4
|
class IpCrawlerJob < ApplicationJob
|
3
5
|
queue_as :default
|
@@ -11,12 +13,16 @@ module RailsUrlShortener
|
|
11
13
|
# create or update an existing record information for an ip
|
12
14
|
|
13
15
|
def perform(visit)
|
14
|
-
if Ipgeo.exists?(ip: visit.ip)
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
16
|
+
if Ipgeo.exists?(ip: visit.ip)
|
17
|
+
ipgeo = Ipgeo.find_by(ip: visit.ip)
|
18
|
+
if Ipgeo.find_by(ip: visit.ip).updated_at <= 3.months.ago
|
19
|
+
# Then update
|
20
|
+
ip = HTTP.get("http://ip-api.com/json/#{visit.ip}?fields=status,message,country,countryCode,region,regionName,city,zip,lat,lon,timezone,isp,org,as,mobile,proxy,hosting,query")
|
21
|
+
if ip.code == 200
|
22
|
+
ipgeo.update(JSON.parse(ip.body).transform_keys { |key| key.to_s.underscore }.slice(*Ipgeo.column_names))
|
23
|
+
visit.update(ipgeo: ipgeo)
|
24
|
+
end
|
25
|
+
else
|
20
26
|
visit.update(ipgeo: ipgeo)
|
21
27
|
end
|
22
28
|
elsif !Ipgeo.exists?(ip: visit.ip)
|
@@ -29,8 +35,8 @@ module RailsUrlShortener
|
|
29
35
|
visit.update(ipgeo: ipgeo)
|
30
36
|
end
|
31
37
|
end
|
32
|
-
rescue
|
33
|
-
|
38
|
+
rescue StandarError => e
|
39
|
+
Rails.logger.debug { "Error#{e}" }
|
34
40
|
end
|
35
41
|
end
|
36
42
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RailsUrlShortener
|
2
4
|
class Url < ApplicationRecord
|
3
5
|
# variables
|
@@ -5,7 +7,7 @@ module RailsUrlShortener
|
|
5
7
|
|
6
8
|
# relations
|
7
9
|
belongs_to :owner, polymorphic: true, optional: true
|
8
|
-
has_many :visits
|
10
|
+
has_many :visits, dependent: :nullify
|
9
11
|
|
10
12
|
# validations
|
11
13
|
validates :key, presence: true, length: { minimum: RailsUrlShortener.minimum_key_length }, uniqueness: true
|
@@ -14,9 +16,9 @@ module RailsUrlShortener
|
|
14
16
|
# exclude records in which expiration time is set and expiration time is greater than current time
|
15
17
|
scope :unexpired, -> { where(arel_table[:expires_at].eq(nil).or(arel_table[:expires_at].gt(::Time.current))) }
|
16
18
|
|
19
|
+
after_initialize :set_attr
|
17
20
|
# callbacks
|
18
21
|
before_validation :generate_key
|
19
|
-
after_initialize :set_attr
|
20
22
|
|
21
23
|
##
|
22
24
|
# set default instance variables values
|
@@ -74,14 +76,14 @@ module RailsUrlShortener
|
|
74
76
|
end
|
75
77
|
|
76
78
|
def generate_key
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
79
|
+
return unless key.nil?
|
80
|
+
|
81
|
+
loop do
|
82
|
+
# plus to the key length if after 10 attempts was not found a candidate
|
83
|
+
self.key_length += 1 if generating_retries >= 10
|
84
|
+
self.key = key_candidate
|
85
|
+
self.generating_retries += 1
|
86
|
+
break unless self.class.exists?(key: key)
|
85
87
|
end
|
86
88
|
end
|
87
89
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RailsUrlShortener
|
2
4
|
require 'json'
|
3
5
|
class Visit < ApplicationRecord
|
@@ -11,19 +13,19 @@ module RailsUrlShortener
|
|
11
13
|
|
12
14
|
def self.parse_and_save(url, request)
|
13
15
|
# browser detection
|
14
|
-
browser
|
15
|
-
if !RailsUrlShortener.save_bots_visits && browser.bot?
|
16
|
+
browser(request)
|
17
|
+
if !RailsUrlShortener.save_bots_visits && @browser.bot?
|
16
18
|
false
|
17
19
|
else
|
18
20
|
# save
|
19
21
|
visit = Visit.create(
|
20
22
|
url: url,
|
21
23
|
ip: request.ip,
|
22
|
-
browser: browser.name,
|
23
|
-
browser_version: browser.full_version,
|
24
|
-
platform: browser.platform.name,
|
25
|
-
platform_version: browser.platform.version,
|
26
|
-
bot: browser.bot?,
|
24
|
+
browser: @browser.name,
|
25
|
+
browser_version: @browser.full_version,
|
26
|
+
platform: @browser.platform.name,
|
27
|
+
platform_version: @browser.platform.version,
|
28
|
+
bot: @browser.bot?,
|
27
29
|
user_agent: request.headers['User-Agent']
|
28
30
|
)
|
29
31
|
# We enqueue a job for get more data later
|
@@ -31,5 +33,9 @@ module RailsUrlShortener
|
|
31
33
|
visit
|
32
34
|
end
|
33
35
|
end
|
36
|
+
|
37
|
+
def self.browser(request)
|
38
|
+
@browser = Browser.new(request.headers['User-Agent'])
|
39
|
+
end
|
34
40
|
end
|
35
41
|
end
|
@@ -21,6 +21,7 @@ class CreateRailsUrlShortenerIpgeos < ActiveRecord::Migration[7.0]
|
|
21
21
|
add_column :rails_url_shortener_visits, :ipgeo_id, :integer
|
22
22
|
add_index :rails_url_shortener_visits, :ipgeo_id
|
23
23
|
end
|
24
|
+
|
24
25
|
def down
|
25
26
|
remove_column :rails_url_shortener_visits, :ipgeo_id
|
26
27
|
drop_table :rails_url_shortener_ipgeos
|
@@ -1,11 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'rails/generators'
|
2
4
|
|
3
5
|
class RailsUrlShortenerGenerator < Rails::Generators::Base
|
4
|
-
|
5
|
-
source_root File.expand_path("templates", __dir__)
|
6
|
+
source_root File.expand_path('templates', __dir__)
|
6
7
|
|
7
8
|
def copy
|
8
|
-
copy_file
|
9
|
+
copy_file 'initializer.rb', 'config/initializers/rails_url_shortener.rb'
|
9
10
|
end
|
10
|
-
|
11
11
|
end
|
@@ -1,11 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
CHARSETS = {
|
2
4
|
alphanum: ('a'..'z').to_a + (0..9).to_a,
|
3
5
|
alphacase: ('a'..'z').to_a + ('A'..'Z').to_a,
|
4
|
-
alphanumcase: ('A'..'Z').to_a + ('a'..'z').to_a
|
5
|
-
}
|
6
|
+
alphanumcase: ('A'..'Z').to_a + ('a'..'z').to_a + (0..9).to_a
|
7
|
+
}.freeze
|
6
8
|
|
7
|
-
RailsUrlShortener.host =
|
8
|
-
RailsUrlShortener.default_redirect =
|
9
|
+
RailsUrlShortener.host = 'localhost:3000' # the host used for the helper
|
10
|
+
RailsUrlShortener.default_redirect = '/' # where the users are redirect if the link is not found.
|
9
11
|
RailsUrlShortener.charset = CHARSETS[:alphanumcase] # used for generate the keys, better long.
|
10
12
|
RailsUrlShortener.key_length = 6 # Key length for random generator
|
11
13
|
RailsUrlShortener.minimum_key_length = 3 # minimun permited for a key
|
data/lib/rails_url_shortener.rb
CHANGED
@@ -1,15 +1,16 @@
|
|
1
|
-
|
2
|
-
require "rails_url_shortener/engine"
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
|
-
|
3
|
+
require 'rails_url_shortener/version'
|
4
|
+
require 'rails_url_shortener/engine'
|
5
5
|
|
6
|
+
module RailsUrlShortener
|
6
7
|
##
|
7
8
|
# constants
|
8
9
|
CHARSETS = {
|
9
10
|
alphanum: ('a'..'z').to_a + (0..9).to_a,
|
10
11
|
alphacase: ('a'..'z').to_a + ('A'..'Z').to_a,
|
11
|
-
alphanumcase: ('A'..'Z').to_a + ('a'..'z').to_a
|
12
|
-
}
|
12
|
+
alphanumcase: ('A'..'Z').to_a + ('a'..'z').to_a + (0..9).to_a
|
13
|
+
}.freeze
|
13
14
|
|
14
15
|
##
|
15
16
|
# host for build final url on helper
|
@@ -37,5 +38,4 @@ module RailsUrlShortener
|
|
37
38
|
# so if you put this configuration like false could lose some visits to your link
|
38
39
|
# by default saving all requests
|
39
40
|
mattr_accessor :save_bots_visits, default: true
|
40
|
-
|
41
41
|
end
|
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails_url_shortener
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- a-chacon
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-05-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: rails
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: 7.0.2.3
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ">="
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: 7.0.2.3
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: browser
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,9 +52,9 @@ dependencies:
|
|
66
52
|
- - ">="
|
67
53
|
- !ruby/object:Gem::Version
|
68
54
|
version: 5.0.4
|
69
|
-
description:
|
70
|
-
|
71
|
-
|
55
|
+
description: |-
|
56
|
+
RailsUrlShortener is a simple engine that provide to your rail's app the functionalities for
|
57
|
+
short URLs. Like bitly.com, but working on your project only.
|
72
58
|
email:
|
73
59
|
- andres.ch@protonmail.com
|
74
60
|
executables: []
|
@@ -101,9 +87,9 @@ licenses:
|
|
101
87
|
- GPL-3.0
|
102
88
|
metadata:
|
103
89
|
bug_tracker_uri: https://www.github.com/a-chacon/rails-url-shortener/issues
|
104
|
-
changelog_uri: https://www.github.com/a-chacon/rails-url-shortener/releases/tag/v0.2.
|
90
|
+
changelog_uri: https://www.github.com/a-chacon/rails-url-shortener/releases/tag/v0.2.5
|
105
91
|
documentation_uri: https://github.com/a-chacon/rails-url-shortener/blob/main/README.md
|
106
|
-
source_code_uri: https://github.com/a-chacon/rails-url-shortener/tree/v0.2.
|
92
|
+
source_code_uri: https://github.com/a-chacon/rails-url-shortener/tree/v0.2.5
|
107
93
|
rubygems_mfa_required: 'true'
|
108
94
|
post_install_message:
|
109
95
|
rdoc_options: []
|