shortener 0.5.1 → 0.5.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.rdoc +23 -7
- data/app/controllers/shortener/shortened_urls_controller.rb +1 -1
- data/app/models/shortener/shortened_url.rb +10 -6
- data/lib/generators/shortener/templates/migration.rb +3 -0
- data/lib/shortener.rb +4 -0
- data/lib/shortener/version.rb +1 -1
- data/shortener.gemspec +1 -1
- data/spec/controllers/shortened_urls_controller_spec.rb +10 -3
- data/spec/dummy/config/environments/development.rb +1 -1
- data/spec/dummy/db/migrate/20120213084304_create_shortened_urls_table.rb +4 -1
- data/spec/dummy/db/migrate/20150919033038_change_url_field_to_text_on_shortened_url.rb +9 -0
- data/spec/dummy/db/migrate/20150919033108_add_expires_at_to_shortened_url.rb +5 -0
- data/spec/dummy/db/schema.rb +16 -14
- data/spec/models/shortened_url_spec.rb +40 -0
- data/spec/models/user_spec.rb +16 -0
- metadata +5 -3
- data/config/routes.rb +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4c844faf59a32a6bc3c3bbaba68f8281296e010e
|
4
|
+
data.tar.gz: d4f9edc81356aba4c03fda63cfb4dac7884f5b30
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 11178f236215ab473d80bd630337056779e20519d8cde40e48e37f0958ce1b2a9cfb8dea1fc05bd829a23bd6b2e8046481523e7652cd8b8bbdb2ae9220c30188
|
7
|
+
data.tar.gz: ce0e61e18cf452f062243d106fab7c5a0c6fac373e018998b57e6d6f08b4ec6902cc66771f7c3b74f93466b800bbc60a10b3db01a4a43fc68c22819a053a5d93
|
data/README.rdoc
CHANGED
@@ -4,8 +4,6 @@
|
|
4
4
|
|
5
5
|
Shortener is a Rails Engine Gem that makes it easy to create and interpret shortened URLs on your own domain from within your Rails application. Once installed Shortener will generate, store URLS and "unshorten" shortened URLs for your applications visitors, all whilst collecting basic usage metrics.
|
6
6
|
|
7
|
-
---
|
8
|
-
|
9
7
|
== Overview
|
10
8
|
|
11
9
|
The majority of the Shortener consists of three parts:
|
@@ -66,13 +64,13 @@ Then add to your routes:
|
|
66
64
|
The gem can be configured in a config/initializers/shortener.rb file.
|
67
65
|
|
68
66
|
By default, the shortener will generate keys that are 5 characters long. You can change that by specifying the length of the key like so;
|
69
|
-
|
67
|
+
|
70
68
|
Shortener.unique_key_length = 6
|
71
|
-
|
69
|
+
|
72
70
|
By default, when a unique key isn't matched the site is redirected to "/". You can change that by specifying a different url like so;
|
73
|
-
|
71
|
+
|
74
72
|
Shortener.default_redirect = "http://www.someurl.com"
|
75
|
-
|
73
|
+
|
76
74
|
== Usage
|
77
75
|
|
78
76
|
To generate a Shortened URL object for the URL "http://example.com" within your controller / models do the following:
|
@@ -111,10 +109,28 @@ And to access those URLs:
|
|
111
109
|
|
112
110
|
You can pass in your own key when generating a shortened URL. This should be unique.
|
113
111
|
|
114
|
-
Shortener::ShortenedUrl.
|
112
|
+
Shortener::ShortenedUrl.generate("example.com", owner: user, custom_key: "my-key")
|
115
113
|
|
116
114
|
short_url("http://example.com", custom_key: 'yourkey')
|
117
115
|
|
116
|
+
=== Expirable Shortened URLs
|
117
|
+
|
118
|
+
You can create expirable URLs.
|
119
|
+
Probably, most of the time it would be used with owner:
|
120
|
+
|
121
|
+
Shortener::ShortenedUrl.generate("example.com/page", user, expires_at: 24.hours.since)
|
122
|
+
|
123
|
+
You can omit owner passing nil instead:
|
124
|
+
|
125
|
+
Shortener::ShortenedUrl.generate("example.com/page", nil, expires_at: 24.hours.since)
|
126
|
+
|
127
|
+
=== Forbidden keys
|
128
|
+
|
129
|
+
You can ensure that records with forbidden keys will not be generated.
|
130
|
+
In rails you can put next line into config/initializers/shortener.rb
|
131
|
+
|
132
|
+
Shortener.forbidden_keys.concat %w(terms promo)
|
133
|
+
|
118
134
|
=== Shorten URLs in generated emails
|
119
135
|
|
120
136
|
You can register the included mail interceptor to shorten all links in the emails generated by your Rails app. For example, add to your mailer:
|
@@ -6,7 +6,7 @@ class Shortener::ShortenedUrlsController < ActionController::Base
|
|
6
6
|
token = /^([#{Shortener.key_chars.join}]*).*/.match(params[:id])[1]
|
7
7
|
|
8
8
|
# pull the link out of the db
|
9
|
-
sl = ::Shortener::ShortenedUrl.
|
9
|
+
sl = ::Shortener::ShortenedUrl.unexpired.where(unique_key: token).first
|
10
10
|
|
11
11
|
if sl
|
12
12
|
# don't want to wait for the increment to happen, make it snappy!
|
@@ -7,6 +7,9 @@ class Shortener::ShortenedUrl < ActiveRecord::Base
|
|
7
7
|
# allows the shortened link to be associated with a user
|
8
8
|
belongs_to :owner, polymorphic: true
|
9
9
|
|
10
|
+
# exclude records in which expiration time is set and expiration time is greater than current time
|
11
|
+
scope :unexpired, -> { where(arel_table[:expires_at].eq(nil).or(arel_table[:expires_at].gt(::Time.current.to_s(:db)))) }
|
12
|
+
|
10
13
|
# ensure the url starts with it protocol and is normalized
|
11
14
|
def self.clean_url(url)
|
12
15
|
|
@@ -20,28 +23,29 @@ class Shortener::ShortenedUrl < ActiveRecord::Base
|
|
20
23
|
# generate a shortened link from a url
|
21
24
|
# link to a user if one specified
|
22
25
|
# throw an exception if anything goes wrong
|
23
|
-
def self.generate!(destination_url, owner: nil, custom_key: nil)
|
26
|
+
def self.generate!(destination_url, owner: nil, custom_key: nil, expires_at: nil)
|
24
27
|
# if we get a shortened_url object with a different owner, generate
|
25
28
|
# new one for the new owner. Otherwise return same object
|
26
29
|
if destination_url.is_a? Shortener::ShortenedUrl
|
27
30
|
if destination_url.owner == owner
|
28
31
|
result = destination_url
|
29
32
|
else
|
30
|
-
result = generate!(destination_url.url, owner: owner, custom_key: custom_key)
|
33
|
+
result = generate!(destination_url.url, owner: owner, custom_key: custom_key, expires_at: expires_at)
|
31
34
|
end
|
32
35
|
else
|
33
36
|
scope = owner ? owner.shortened_urls : self
|
34
|
-
result = scope.where(url: clean_url(destination_url)).first_or_create
|
37
|
+
result = scope.where(url: clean_url(destination_url)).first_or_create(unique_key: custom_key, expires_at: expires_at)
|
35
38
|
end
|
36
39
|
|
37
40
|
result
|
38
41
|
end
|
39
42
|
|
40
43
|
# return shortened url on success, nil on failure
|
41
|
-
def self.generate(destination_url, owner: nil, custom_key: nil)
|
44
|
+
def self.generate(destination_url, owner: nil, custom_key: nil, expires_at: nil)
|
42
45
|
begin
|
43
|
-
generate!(destination_url, owner: owner, custom_key: custom_key)
|
44
|
-
rescue
|
46
|
+
generate!(destination_url, owner: owner, custom_key: custom_key, expires_at: expires_at)
|
47
|
+
rescue => e
|
48
|
+
logger.info e
|
45
49
|
nil
|
46
50
|
end
|
47
51
|
end
|
data/lib/shortener.rb
CHANGED
data/lib/shortener/version.rb
CHANGED
data/shortener.gemspec
CHANGED
@@ -12,9 +12,6 @@ describe Shortener::ShortenedUrlsController, type: :controller do
|
|
12
12
|
|
13
13
|
context 'valid keys' do
|
14
14
|
context 'real key' do
|
15
|
-
before do
|
16
|
-
short_url
|
17
|
-
end
|
18
15
|
let(:key) { short_url.unique_key }
|
19
16
|
|
20
17
|
it 'redirects to the destination url' do
|
@@ -71,6 +68,16 @@ describe Shortener::ShortenedUrlsController, type: :controller do
|
|
71
68
|
end
|
72
69
|
end
|
73
70
|
end
|
71
|
+
|
72
|
+
context 'expired code' do
|
73
|
+
let(:expired_url) { Shortener::ShortenedUrl.generate(Faker::Internet.url, expires_at: 1.hour.ago) }
|
74
|
+
describe "GET show with expired code" do
|
75
|
+
let(:key) { expired_url.unique_key }
|
76
|
+
it 'redirects to the default url' do
|
77
|
+
expect(response).to redirect_to Shortener.default_redirect
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
74
81
|
end
|
75
82
|
end
|
76
83
|
end
|
@@ -11,7 +11,7 @@ Dummy::Application.configure do
|
|
11
11
|
|
12
12
|
# Show full error reports and disable caching
|
13
13
|
config.consider_all_requests_local = true
|
14
|
-
config.action_view.debug_rjs = true
|
14
|
+
#config.action_view.debug_rjs = true
|
15
15
|
config.action_controller.perform_caching = false
|
16
16
|
|
17
17
|
# Print deprecation notices to the Rails logger
|
@@ -6,7 +6,7 @@ class CreateShortenedUrlsTable < ActiveRecord::Migration
|
|
6
6
|
t.string :owner_type, limit: 20
|
7
7
|
|
8
8
|
# the real url that we will redirect to
|
9
|
-
t.
|
9
|
+
t.text :url, null: false
|
10
10
|
|
11
11
|
# the unique key
|
12
12
|
t.string :unique_key, limit: 10, null: false
|
@@ -14,6 +14,9 @@ class CreateShortenedUrlsTable < ActiveRecord::Migration
|
|
14
14
|
# how many times the link has been clicked
|
15
15
|
t.integer :use_count, null: false, default: 0
|
16
16
|
|
17
|
+
# valid until date for expirable urls
|
18
|
+
t.datetime :expires_at
|
19
|
+
|
17
20
|
t.timestamps
|
18
21
|
end
|
19
22
|
|
data/spec/dummy/db/schema.rb
CHANGED
@@ -9,26 +9,28 @@
|
|
9
9
|
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
|
10
10
|
# you'll amass, the slower it'll run and the greater likelihood for issues).
|
11
11
|
#
|
12
|
-
# It's strongly recommended
|
12
|
+
# It's strongly recommended that you check this file into your version control system.
|
13
13
|
|
14
|
-
ActiveRecord::Schema.define(:
|
14
|
+
ActiveRecord::Schema.define(version: 20150919033108) do
|
15
15
|
|
16
|
-
create_table "shortened_urls", :
|
16
|
+
create_table "shortened_urls", force: true do |t|
|
17
17
|
t.integer "owner_id"
|
18
|
-
t.string "owner_type", :
|
19
|
-
t.
|
20
|
-
t.string "unique_key", :
|
21
|
-
t.integer "use_count",
|
22
|
-
t.datetime "
|
23
|
-
t.datetime "
|
18
|
+
t.string "owner_type", limit: 20
|
19
|
+
t.text "url", null: false
|
20
|
+
t.string "unique_key", limit: 10, null: false
|
21
|
+
t.integer "use_count", default: 0, null: false
|
22
|
+
t.datetime "expires_at"
|
23
|
+
t.datetime "created_at"
|
24
|
+
t.datetime "updated_at"
|
24
25
|
end
|
25
26
|
|
26
|
-
add_index "shortened_urls", ["owner_id", "owner_type"], :
|
27
|
-
add_index "shortened_urls", ["unique_key"], :
|
27
|
+
add_index "shortened_urls", ["owner_id", "owner_type"], name: "index_shortened_urls_on_owner_id_and_owner_type"
|
28
|
+
add_index "shortened_urls", ["unique_key"], name: "index_shortened_urls_on_unique_key", unique: true
|
29
|
+
add_index "shortened_urls", ["url"], name: "index_shortened_urls_on_url"
|
28
30
|
|
29
|
-
create_table "users", :
|
30
|
-
t.datetime "created_at"
|
31
|
-
t.datetime "updated_at"
|
31
|
+
create_table "users", force: true do |t|
|
32
|
+
t.datetime "created_at"
|
33
|
+
t.datetime "updated_at"
|
32
34
|
end
|
33
35
|
|
34
36
|
end
|
@@ -62,6 +62,33 @@ describe Shortener::ShortenedUrl, type: :model do
|
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
|
+
context 'same url as existing' do
|
66
|
+
it 'returns the same shortened link record' do
|
67
|
+
expect(Shortener::ShortenedUrl.generate!(url)).to eq existing_shortened_url
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'same url as existing, but with a different owner' do
|
72
|
+
let(:owner) { User.create }
|
73
|
+
it 'returns the a new shortened link record' do
|
74
|
+
expect(Shortener::ShortenedUrl.generate!(url, owner: owner)).not_to eq existing_shortened_url
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context 'existing shortened url as argument' do
|
79
|
+
let(:owner) { User.create }
|
80
|
+
it 'returns the a new shortened link record' do
|
81
|
+
expect(Shortener::ShortenedUrl.generate!(existing_shortened_url)).to eq existing_shortened_url
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context 'existing shortened url as argument, with new owner' do
|
86
|
+
let(:owner) { User.create }
|
87
|
+
it 'returns the a new shortened link record' do
|
88
|
+
expect(Shortener::ShortenedUrl.generate!(existing_shortened_url, owner: owner)).not_to eq existing_shortened_url
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
65
92
|
context "duplicate unique key" do
|
66
93
|
before do
|
67
94
|
expect_any_instance_of(Shortener::ShortenedUrl).to receive(:generate_unique_key).
|
@@ -101,4 +128,17 @@ describe Shortener::ShortenedUrl, type: :model do
|
|
101
128
|
end
|
102
129
|
end
|
103
130
|
end
|
131
|
+
|
132
|
+
describe 'unexpired scope' do
|
133
|
+
let(:permanent_url) { described_class.generate(Faker::Internet.url) }
|
134
|
+
let!(:expired_url) { described_class.generate(Faker::Internet.url, expires_at: 2.hour.ago) }
|
135
|
+
let!(:unexpired_url) { described_class.generate(Faker::Internet.url, expires_at: 1.hour.since) }
|
136
|
+
let!(:unexpired_scope) { described_class.unexpired }
|
137
|
+
|
138
|
+
it "should contain permanent and unexpired records" do
|
139
|
+
expect(unexpired_scope).to include(permanent_url)
|
140
|
+
expect(unexpired_scope).to include(unexpired_url)
|
141
|
+
expect(unexpired_scope).not_to include(expired_url)
|
142
|
+
end
|
143
|
+
end
|
104
144
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
# user defined in dummy app, uses has_shortened_urls
|
5
|
+
describe User do
|
6
|
+
it { should have_many :shortened_urls }
|
7
|
+
|
8
|
+
context 'shortened url created with owner' do
|
9
|
+
let (:user) { User.create }
|
10
|
+
let (:shortened_url) { Shortener::ShortenedUrl.generate(Faker::Internet.url, owner: user) }
|
11
|
+
specify 'shorted_urls will contains the url' do
|
12
|
+
expect(user.shortened_urls).to include shortened_url
|
13
|
+
expect(user.shortened_urls.size).to be 1
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shortener
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James P. McGrath
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-09-
|
12
|
+
date: 2015-09-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -115,7 +115,6 @@ files:
|
|
115
115
|
- app/controllers/shortener/shortened_urls_controller.rb
|
116
116
|
- app/helpers/shortener/shortener_helper.rb
|
117
117
|
- app/models/shortener/shortened_url.rb
|
118
|
-
- config/routes.rb
|
119
118
|
- lib/generators/shortener/shortener_generator.rb
|
120
119
|
- lib/generators/shortener/templates/migration.rb
|
121
120
|
- lib/shortener.rb
|
@@ -149,11 +148,14 @@ files:
|
|
149
148
|
- spec/dummy/db/.gitkeep
|
150
149
|
- spec/dummy/db/migrate/20120213084304_create_shortened_urls_table.rb
|
151
150
|
- spec/dummy/db/migrate/20120214023758_create_users.rb
|
151
|
+
- spec/dummy/db/migrate/20150919033038_change_url_field_to_text_on_shortened_url.rb
|
152
|
+
- spec/dummy/db/migrate/20150919033108_add_expires_at_to_shortened_url.rb
|
152
153
|
- spec/dummy/db/schema.rb
|
153
154
|
- spec/dummy/public/favicon.ico
|
154
155
|
- spec/dummy/script/rails
|
155
156
|
- spec/helpers/shortener_helper_spec.rb
|
156
157
|
- spec/models/shortened_url_spec.rb
|
158
|
+
- spec/models/user_spec.rb
|
157
159
|
- spec/shortener/shorten_url_interceptor_spec.rb
|
158
160
|
- spec/spec_helper.rb
|
159
161
|
homepage: http://jamespmcgrath.com/projects/shortener
|
data/config/routes.rb
DELETED