shortener 0.3.1 → 0.4.0
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/.travis.yml +1 -0
- data/README.rdoc +17 -14
- data/app/controllers/shortener/shortened_urls_controller.rb +2 -2
- data/app/helpers/shortener/shortener_helper.rb +1 -1
- data/app/models/shortener/shortened_url.rb +12 -9
- data/config/routes.rb +1 -1
- data/lib/generators/shortener/shortener_generator.rb +5 -3
- data/lib/generators/shortener/templates/migration.rb +5 -5
- data/lib/shortener/active_record_extension.rb +1 -1
- data/lib/shortener/shorten_url_interceptor.rb +1 -1
- data/lib/shortener/version.rb +1 -1
- data/lib/shortener.rb +7 -2
- data/shortener.gemspec +3 -1
- data/spec/controllers/shortened_urls_controller_spec.rb +62 -29
- data/spec/dummy/config/application.rb +1 -1
- data/spec/dummy/config/environments/development.rb +2 -0
- data/spec/dummy/config/environments/test.rb +2 -0
- data/spec/dummy/config/initializers/session_store.rb +1 -1
- data/spec/dummy/config/routes.rb +1 -1
- data/spec/dummy/db/migrate/20120213084304_create_shortened_urls_table.rb +5 -5
- data/spec/helpers/shortener_helper_spec.rb +20 -5
- data/spec/models/shortened_url_spec.rb +80 -48
- data/spec/shortener/shorten_url_interceptor_spec.rb +9 -9
- data/spec/spec_helper.rb +2 -0
- metadata +33 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2f4d4b7d3190fc69489c4b1801b999f68d343d63
|
4
|
+
data.tar.gz: 56ab4d022830a4fa77fd076bde77d0d24d995e81
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f6aa5e1de18874e3c1df7ce6fe526c3ac4cc13a36dfa23c985c625b0d66b714e779409dcb9ddef2ca048fe52a0d0367628bf0384d537e05450f99d8c293cb0b3
|
7
|
+
data.tar.gz: 86253d34dcb01f8db8636a0df687dce67d0ca486fcab4f9754a98a01a91f3b1fc1d77b5040265a0f79ab7718f1209a73eca06c19fb08034aa903fc2b9ba50189
|
data/.travis.yml
CHANGED
data/README.rdoc
CHANGED
@@ -36,29 +36,34 @@ The majority of the Shortener consists of three parts:
|
|
36
36
|
You can use the latest Rails 3 gem with the latest Shortener gem. In your Gemfile:
|
37
37
|
|
38
38
|
gem 'shortener'
|
39
|
-
|
39
|
+
|
40
40
|
After you install Shortener run the generator:
|
41
41
|
|
42
42
|
rails generate shortener
|
43
|
-
|
43
|
+
|
44
44
|
This generator will create a migration to create the shortened_urls table where your shortened URLs will be stored.
|
45
45
|
|
46
46
|
Then add to your routes:
|
47
47
|
|
48
48
|
match '/:id' => "shortener/shortened_urls#show"
|
49
49
|
|
50
|
-
==
|
51
|
-
|
52
|
-
By default, the shortener will generate keys that are 5 characters long. You can change that by specifying the length of the key in the config/initializers/shortener.rb file.
|
50
|
+
== Configuration
|
51
|
+
The gem can be configured in a config/initializers/shortener.rb file.
|
53
52
|
|
53
|
+
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;
|
54
|
+
```
|
54
55
|
Shortener.unique_key_length = 6
|
55
|
-
|
56
|
+
```
|
57
|
+
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;
|
58
|
+
```
|
59
|
+
Shortener.default_redirect = "http://www.someurl.com"
|
60
|
+
```
|
56
61
|
== Usage
|
57
62
|
|
58
63
|
To generate a Shortened URL object for the URL "http://dealush.com" within your controller / models do the following:
|
59
|
-
|
64
|
+
|
60
65
|
Shortener::ShortenedUrl.generate("http://dealush.com")
|
61
|
-
|
66
|
+
|
62
67
|
or
|
63
68
|
|
64
69
|
Shortener::ShortenedUrl.generate("dealush.com")
|
@@ -66,7 +71,7 @@ or
|
|
66
71
|
To generate and display a shortened URL in your application use the helper method:
|
67
72
|
|
68
73
|
short_url("dealush.com")
|
69
|
-
|
74
|
+
|
70
75
|
This will generate a shortened URL. store it to the db and return a string representing the shortened URL.
|
71
76
|
|
72
77
|
=== Shortened URLs with owner
|
@@ -79,7 +84,7 @@ You can link shortened URLs to an owner, to scope them. To do so, add the follow
|
|
79
84
|
|
80
85
|
This will allow you to pass the owner when generating URLs:
|
81
86
|
|
82
|
-
Shortener::ShortenedUrl.generate("
|
87
|
+
Shortener::ShortenedUrl.generate("example.com", user)
|
83
88
|
|
84
89
|
And to access those URLs:
|
85
90
|
|
@@ -103,16 +108,14 @@ The interceptor supports a few more arguments, see the implementation for detail
|
|
103
108
|
|
104
109
|
== Origins
|
105
110
|
|
106
|
-
Shortener is based on code from Dealush[http://
|
111
|
+
Shortener is based on code from Dealush[http://example.com], for a bit of backstory to Shortener see this {blog post}[http://jamespmcgrath.com/a-simple-link-shortener-in-rails/].
|
107
112
|
|
108
113
|
== In The Wild
|
109
114
|
|
110
|
-
Shortener is used in a number of production systems:
|
115
|
+
Shortener is used in a number of production systems, including, but not limited to:
|
111
116
|
|
112
117
|
{Doorkeeper - An Event Management Tool}[http://www.doorkeeperhq.com/]
|
113
118
|
|
114
|
-
{Dealush - A Local shopping Sales Notification Service}[http://dealush.com]
|
115
|
-
|
116
119
|
If you are using Shortener in your project and would like to be added to this list, please get in touch!
|
117
120
|
|
118
121
|
== Authors
|
@@ -18,11 +18,11 @@ class Shortener::ShortenedUrlsController < ActionController::Base
|
|
18
18
|
ActiveRecord::Base.connection.close
|
19
19
|
end
|
20
20
|
# do a 301 redirect to the destination url
|
21
|
-
redirect_to sl.url, :
|
21
|
+
redirect_to sl.url, status: :moved_permanently
|
22
22
|
else
|
23
23
|
# if we don't find the shortened link, redirect to the root
|
24
24
|
# make this configurable in future versions
|
25
|
-
redirect_to
|
25
|
+
redirect_to Shortener.default_redirect
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
@@ -3,7 +3,7 @@ module Shortener::ShortenerHelper
|
|
3
3
|
# generate a url from a url string
|
4
4
|
def short_url(url, owner=nil)
|
5
5
|
short_url = Shortener::ShortenedUrl.generate(url, owner)
|
6
|
-
short_url ? url_for(:
|
6
|
+
short_url ? url_for(controller: :"shortener/shortened_urls", action: :show, id: short_url.unique_key, only_path: false) : url
|
7
7
|
end
|
8
8
|
|
9
9
|
end
|
@@ -3,10 +3,10 @@ class Shortener::ShortenedUrl < ActiveRecord::Base
|
|
3
3
|
URL_PROTOCOL_HTTP = "http://"
|
4
4
|
REGEX_LINK_HAS_PROTOCOL = Regexp.new('\Ahttp:\/\/|\Ahttps:\/\/', Regexp::IGNORECASE)
|
5
5
|
|
6
|
-
validates :url, :
|
6
|
+
validates :url, presence: true
|
7
7
|
|
8
8
|
# allows the shortened link to be associated with a user
|
9
|
-
belongs_to :owner, :
|
9
|
+
belongs_to :owner, polymorphic: true
|
10
10
|
|
11
11
|
# ensure the url starts with it protocol and is normalized
|
12
12
|
def self.clean_url(url)
|
@@ -21,15 +21,18 @@ class Shortener::ShortenedUrl < ActiveRecord::Base
|
|
21
21
|
def self.generate!(orig_url, owner=nil)
|
22
22
|
# if we get a shortened_url object with a different owner, generate
|
23
23
|
# new one for the new owner. Otherwise return same object
|
24
|
-
if orig_url.is_a?
|
25
|
-
|
24
|
+
if orig_url.is_a? Shortener::ShortenedUrl
|
25
|
+
if orig_url.owner == owner
|
26
|
+
result = orig_url
|
27
|
+
else
|
28
|
+
result generate!(orig_url.url, owner)
|
29
|
+
end
|
30
|
+
else
|
31
|
+
scope = owner ? owner.shortened_urls : self
|
32
|
+
result = scope.where(url: clean_url(orig_url)).first_or_create
|
26
33
|
end
|
27
34
|
|
28
|
-
|
29
|
-
# so check the datastore
|
30
|
-
cleaned_url = clean_url(orig_url)
|
31
|
-
scope = owner ? owner.shortened_urls : self
|
32
|
-
scope.where(:url => cleaned_url).first_or_create
|
35
|
+
result
|
33
36
|
end
|
34
37
|
|
35
38
|
# return shortened url on success, nil on failure
|
data/config/routes.rb
CHANGED
@@ -3,10 +3,11 @@ require 'rails/generators/migration'
|
|
3
3
|
|
4
4
|
class ShortenerGenerator < Rails::Generators::Base
|
5
5
|
include Rails::Generators::Migration
|
6
|
+
|
6
7
|
def self.source_root
|
7
8
|
@source_root ||= File.join(File.dirname(__FILE__), 'templates')
|
8
9
|
end
|
9
|
-
|
10
|
+
|
10
11
|
def self.next_migration_number(dirname)
|
11
12
|
if ActiveRecord::Base.timestamped_migrations
|
12
13
|
Time.new.utc.strftime("%Y%m%d%H%M%S")
|
@@ -14,8 +15,9 @@ class ShortenerGenerator < Rails::Generators::Base
|
|
14
15
|
"%.3d" % (current_migration_number(dirname) + 1)
|
15
16
|
end
|
16
17
|
end
|
17
|
-
|
18
|
+
|
18
19
|
def create_migration_file
|
19
20
|
migration_template 'migration.rb', 'db/migrate/create_shortened_urls_table.rb'
|
20
21
|
end
|
21
|
-
|
22
|
+
|
23
|
+
end
|
@@ -3,23 +3,23 @@ class CreateShortenedUrlsTable < ActiveRecord::Migration
|
|
3
3
|
create_table :shortened_urls do |t|
|
4
4
|
# we can link this to a user for interesting things
|
5
5
|
t.integer :owner_id
|
6
|
-
t.string :owner_type, :
|
6
|
+
t.string :owner_type, limit: 20
|
7
7
|
|
8
8
|
# the real url that we will redirect to
|
9
|
-
t.string :url, :
|
9
|
+
t.string :url, null: false
|
10
10
|
|
11
11
|
# the unique key
|
12
|
-
t.string :unique_key, :
|
12
|
+
t.string :unique_key, limit: 10, null: false
|
13
13
|
|
14
14
|
# how many times the link has been clicked
|
15
|
-
t.integer :use_count, :
|
15
|
+
t.integer :use_count, null: false, default: 0
|
16
16
|
|
17
17
|
t.timestamps
|
18
18
|
end
|
19
19
|
|
20
20
|
# we will lookup the links in the db by key, urls and owners.
|
21
21
|
# also make sure the unique keys are actually unique
|
22
|
-
add_index :shortened_urls, :unique_key, :
|
22
|
+
add_index :shortened_urls, :unique_key, unique: true
|
23
23
|
add_index :shortened_urls, :url
|
24
24
|
add_index :shortened_urls, [:owner_id, :owner_type]
|
25
25
|
end
|
data/lib/shortener/version.rb
CHANGED
data/lib/shortener.rb
CHANGED
@@ -6,8 +6,9 @@ module Shortener
|
|
6
6
|
autoload :ShortenUrlInterceptor, "shortener/shorten_url_interceptor"
|
7
7
|
|
8
8
|
CHARSETS = {
|
9
|
-
:
|
10
|
-
:
|
9
|
+
alphanum: ('a'..'z').to_a + (0..9).to_a,
|
10
|
+
alphanumcase: ('a'..'z').to_a + ('A'..'Z').to_a + (0..9).to_a
|
11
|
+
}
|
11
12
|
|
12
13
|
# default key length: 5 characters
|
13
14
|
mattr_accessor :unique_key_length
|
@@ -19,6 +20,10 @@ module Shortener
|
|
19
20
|
mattr_accessor :charset
|
20
21
|
self.charset = :alphanum
|
21
22
|
|
23
|
+
#The default redirection url when the key isn't found
|
24
|
+
mattr_accessor :default_redirect
|
25
|
+
self.default_redirect = '/'
|
26
|
+
|
22
27
|
def self.key_chars
|
23
28
|
CHARSETS[charset]
|
24
29
|
end
|
data/shortener.gemspec
CHANGED
@@ -16,8 +16,10 @@ Gem::Specification.new do |s|
|
|
16
16
|
s.required_rubygems_version = "> 1.3.6"
|
17
17
|
s.add_dependency "rails", ">= 3.0.7"
|
18
18
|
s.add_development_dependency "sqlite3"
|
19
|
-
s.add_development_dependency "rspec-rails", '~>
|
19
|
+
s.add_development_dependency "rspec-rails", '~> 3.3.0'
|
20
20
|
s.add_development_dependency "shoulda-matchers"
|
21
|
+
s.add_development_dependency "faker"
|
22
|
+
s.add_development_dependency "byebug"
|
21
23
|
s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
|
22
24
|
s.require_path = 'lib'
|
23
25
|
end
|
@@ -1,40 +1,73 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
require 'spec_helper'
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
response.should redirect_to("http://www.doorkeeperhq.com/")
|
8
|
-
end
|
9
|
-
end
|
4
|
+
describe Shortener::ShortenedUrlsController, type: :controller do
|
5
|
+
let(:destination) { Faker::Internet.url }
|
6
|
+
let(:short_url) { Shortener::ShortenedUrl.generate(destination) }
|
10
7
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
end
|
16
|
-
end
|
8
|
+
describe '#show' do
|
9
|
+
before do
|
10
|
+
get :show, id: key
|
11
|
+
end
|
17
12
|
|
18
|
-
|
19
|
-
|
13
|
+
context 'valid keys' do
|
14
|
+
context 'real key' do
|
15
|
+
let(:key) { short_url.unique_key}
|
20
16
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
17
|
+
it 'redirects to the destination url' do
|
18
|
+
expect(response).to redirect_to destination
|
19
|
+
end
|
20
|
+
end
|
25
21
|
|
26
|
-
|
27
|
-
|
28
|
-
it_should_behave_like "good code"
|
29
|
-
end
|
22
|
+
context 'real key with trailing characters' do
|
23
|
+
let(:key) { "#{short_url.unique_key}-" }
|
30
24
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
25
|
+
it 'redirects to the destination url' do
|
26
|
+
expect(response).to redirect_to destination
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'invalid keys' do
|
32
|
+
context 'non existant key' do
|
33
|
+
let(:key) { "nonexistantkey" }
|
34
|
+
|
35
|
+
it 'redirects to the root url' do
|
36
|
+
expect(response).to redirect_to root_url
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'key with invalid characters' do
|
41
|
+
let(:key) { "-" }
|
42
|
+
|
43
|
+
it 'redirects to the root url' do
|
44
|
+
expect(response).to redirect_to root_url
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context "custom default redirect set" do
|
49
|
+
before do
|
50
|
+
Shortener.default_redirect = 'http://www.default_redirect.com'
|
51
|
+
# call again for the get is done with the setting
|
52
|
+
get :show, id: key
|
53
|
+
end
|
54
|
+
|
55
|
+
context 'non existant key' do
|
56
|
+
let(:key) { "nonexistantkey" }
|
57
|
+
|
58
|
+
it 'redirects to the root url' do
|
59
|
+
expect(response).to redirect_to 'http://www.default_redirect.com'
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'key with invalid characters' do
|
64
|
+
let(:key) { "-" }
|
35
65
|
|
36
|
-
|
37
|
-
|
38
|
-
|
66
|
+
it 'redirects to the root url' do
|
67
|
+
expect(response).to redirect_to 'http://www.default_redirect.com'
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
39
72
|
end
|
40
73
|
end
|
@@ -37,6 +37,6 @@ module Dummy
|
|
37
37
|
# Configure sensitive parameters which will be filtered from the log file.
|
38
38
|
config.filter_parameters += [:password]
|
39
39
|
|
40
|
-
config.action_mailer.default_url_options = { :
|
40
|
+
config.action_mailer.default_url_options = { host: "mbln.jp" }
|
41
41
|
end
|
42
42
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# Be sure to restart your server when you modify this file.
|
2
2
|
|
3
|
-
Dummy::Application.config.session_store :cookie_store, :
|
3
|
+
Dummy::Application.config.session_store :cookie_store, key: '_dummy_session'
|
4
4
|
|
5
5
|
# Use the database for sessions instead of the cookie-based default,
|
6
6
|
# which shouldn't be used to store highly confidential information
|
data/spec/dummy/config/routes.rb
CHANGED
@@ -3,23 +3,23 @@ class CreateShortenedUrlsTable < ActiveRecord::Migration
|
|
3
3
|
create_table :shortened_urls do |t|
|
4
4
|
# we can link this to a user for interesting things
|
5
5
|
t.integer :owner_id
|
6
|
-
t.string :owner_type, :
|
6
|
+
t.string :owner_type, limit: 20
|
7
7
|
|
8
8
|
# the real url that we will redirect to
|
9
|
-
t.string :url, :
|
9
|
+
t.string :url, null: false
|
10
10
|
|
11
11
|
# the unique key
|
12
|
-
t.string :unique_key, :
|
12
|
+
t.string :unique_key, limit: 10, null: false
|
13
13
|
|
14
14
|
# how many times the link has been clicked
|
15
|
-
t.integer :use_count, :
|
15
|
+
t.integer :use_count, null: false, default: 0
|
16
16
|
|
17
17
|
t.timestamps
|
18
18
|
end
|
19
19
|
|
20
20
|
# we will lookup the links in the db by key and owners.
|
21
21
|
# also make sure the unique keys are actually unique
|
22
|
-
add_index :shortened_urls, :unique_key, :
|
22
|
+
add_index :shortened_urls, :unique_key, unique: true
|
23
23
|
add_index :shortened_urls, :url
|
24
24
|
add_index :shortened_urls, [:owner_id, :owner_type]
|
25
25
|
end
|
@@ -1,12 +1,27 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
require 'spec_helper'
|
3
3
|
|
4
|
-
describe Shortener::ShortenerHelper do
|
5
|
-
|
4
|
+
describe Shortener::ShortenerHelper, type: :helper do
|
5
|
+
describe '#short_url' do
|
6
|
+
let(:destination) { Faker::Internet.url }
|
7
|
+
before do
|
8
|
+
expect(Shortener::ShortenedUrl).to receive(:generate).with(destination, nil).and_return(shortened_url)
|
9
|
+
end
|
10
|
+
|
11
|
+
context 'short url was generated' do
|
12
|
+
let(:shortened_url) { instance_double('ShortenedUrl', unique_key: '12345') }
|
13
|
+
|
14
|
+
it "shortens the url" do
|
15
|
+
expect(helper.short_url(destination)).to eq "http://test.host/12345"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'short url could not be generated' do
|
20
|
+
let(:shortened_url) { nil }
|
6
21
|
|
7
|
-
|
8
|
-
|
9
|
-
|
22
|
+
it 'returns the original url' do
|
23
|
+
expect(helper.short_url(destination)).to eq destination
|
24
|
+
end
|
10
25
|
end
|
11
26
|
end
|
12
27
|
end
|
@@ -1,67 +1,99 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
require 'spec_helper'
|
3
3
|
|
4
|
-
describe Shortener::ShortenedUrl do
|
4
|
+
describe Shortener::ShortenedUrl, type: :model do
|
5
5
|
it { should belong_to :owner }
|
6
6
|
it { should validate_presence_of :url }
|
7
7
|
|
8
|
-
|
9
|
-
let(:short_url) { Shortener::ShortenedUrl.generate!(long_url, owner) }
|
10
|
-
it "should be shortened" do
|
11
|
-
short_url.should_not be_nil
|
12
|
-
short_url.url.should == expected_long_url
|
13
|
-
short_url.unique_key.length.should == 5
|
14
|
-
short_url.owner.should == owner
|
15
|
-
end
|
16
|
-
end
|
8
|
+
describe '#generate!' do
|
17
9
|
|
18
|
-
|
19
|
-
|
20
|
-
let(:expected_long_url) { long_url }
|
21
|
-
let(:owner) { nil }
|
22
|
-
it_should_behave_like "shortened url"
|
23
|
-
end
|
10
|
+
context 'shortened url record for requested url does not exist' do
|
11
|
+
let(:expected_url) { Faker::Internet.url }
|
24
12
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
13
|
+
shared_examples_for "shortened url" do
|
14
|
+
let(:short_url) { Shortener::ShortenedUrl.generate!(long_url, owner) }
|
15
|
+
it 'creates a shortened url record for the url' do
|
16
|
+
expect{short_url}.to change{Shortener::ShortenedUrl.count}.by(1)
|
17
|
+
expect(short_url.url).to eq expected_url
|
18
|
+
expect(short_url.unique_key.length).to eq 5
|
19
|
+
expect(short_url.owner).to eq owner
|
20
|
+
end
|
21
|
+
end
|
31
22
|
|
32
|
-
|
33
|
-
|
34
|
-
let(:expected_long_url) { long_url }
|
35
|
-
let(:owner) { nil }
|
36
|
-
it_should_behave_like "shortened url"
|
37
|
-
end
|
23
|
+
context 'userless url' do
|
24
|
+
let(:owner) { nil }
|
38
25
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
26
|
+
context 'shortened url ' do
|
27
|
+
it_should_behave_like "shortened url" do
|
28
|
+
let(:long_url) { expected_url }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'shortened url with partial URL' do
|
33
|
+
it_should_behave_like "shortened url" do
|
34
|
+
let(:long_url) { expected_url.gsub('http://', '') }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context "shortened url with i18n path" do
|
39
|
+
it_should_behave_like "shortened url" do
|
40
|
+
let(:long_url) { "#{Faker::Internet.url}/%E6%97%A5%E6%9C%AC%E8%AA%9E" }
|
41
|
+
let(:expected_url) { long_url }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
45
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
46
|
+
context "shortened url with user" do
|
47
|
+
it_should_behave_like "shortened url" do
|
48
|
+
let(:owner) { User.create }
|
49
|
+
let(:long_url) { expected_url }
|
50
|
+
end
|
51
|
+
end
|
51
52
|
end
|
52
|
-
|
53
|
-
|
53
|
+
|
54
|
+
context "existing shortened URL" do
|
55
|
+
let(:url) { Faker::Internet.url }
|
56
|
+
let!(:existing_shortened_url) { Shortener::ShortenedUrl.generate!(url) }
|
57
|
+
|
58
|
+
context 'same url as existing' do
|
59
|
+
let(:protocol_free_url) { url.gsub('http://', '') }
|
60
|
+
|
61
|
+
it 'finds the shortened url from protocol free url' do
|
62
|
+
expect(Shortener::ShortenedUrl.generate!(protocol_free_url)).to eq existing_shortened_url
|
63
|
+
end
|
64
|
+
it "should look up exsiting URL" do
|
65
|
+
expect(Shortener::ShortenedUrl.generate!(url)).to eq existing_shortened_url
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'different url from existing' do
|
70
|
+
it "generates a new shortened url record for a different url" do
|
71
|
+
expect(Shortener::ShortenedUrl.generate!(Faker::Internet.url)).not_to eq existing_shortened_url
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context "duplicate unique key" do
|
76
|
+
before do
|
77
|
+
expect_any_instance_of(Shortener::ShortenedUrl).to receive(:generate_unique_key).
|
78
|
+
and_return(existing_shortened_url.unique_key, 'ABCDEF')
|
79
|
+
Shortener::ShortenedUrl.where(unique_key: 'ABCDEF').delete_all
|
80
|
+
end
|
81
|
+
it 'should try until it finds a non-dup key' do
|
82
|
+
short_url = Shortener::ShortenedUrl.generate!(Faker::Internet.url)
|
83
|
+
expect(short_url).not_to be_nil
|
84
|
+
expect(short_url.unique_key).to eq "ABCDEF"
|
85
|
+
end
|
86
|
+
end
|
54
87
|
end
|
88
|
+
end
|
55
89
|
|
56
|
-
|
90
|
+
describe '#generate' do
|
91
|
+
context 'cannot generate a unique key' do
|
57
92
|
before do
|
58
|
-
Shortener::ShortenedUrl.
|
59
|
-
and_return(@existing.unique_key, "ABCDEF")
|
93
|
+
expect(Shortener::ShortenedUrl).to receive(:generate!).and_raise(ActiveRecord::RecordNotUnique.new(nil))
|
60
94
|
end
|
61
|
-
it
|
62
|
-
|
63
|
-
short_url.should_not be_nil
|
64
|
-
short_url.unique_key.should == "ABCDEF"
|
95
|
+
it 'returns nil' do
|
96
|
+
expect(Shortener::ShortenedUrl.generate(Faker::Internet.url)).to eq nil
|
65
97
|
end
|
66
98
|
end
|
67
99
|
end
|
@@ -5,7 +5,7 @@ require 'mail'
|
|
5
5
|
describe Shortener::ShortenUrlInterceptor do
|
6
6
|
|
7
7
|
def create_email(body)
|
8
|
-
Mail.new(:
|
8
|
+
Mail.new(from: 'test@mbln.jp', to: 'test@mbln.jp', body: body).tap do |m|
|
9
9
|
m.encoded
|
10
10
|
Shortener::ShortenUrlInterceptor.new.delivering_email(m)
|
11
11
|
end
|
@@ -17,27 +17,27 @@ describe Shortener::ShortenUrlInterceptor do
|
|
17
17
|
"Test with URL: %{url}. hu!",
|
18
18
|
"Test with URL: <a href='%{url}'>test</a>",
|
19
19
|
"Test with URL: <a href=\"%{url}\">test</a>" ]
|
20
|
-
|
20
|
+
|
21
21
|
shared_examples_for "shortens URL in text" do |url|
|
22
22
|
TEXTS.each do |raw_email_body_text|
|
23
|
-
email_body_text = raw_email_body_text % {:url
|
23
|
+
email_body_text = raw_email_body_text % { url: url }
|
24
24
|
it("shortens for #{email_body_text}") do
|
25
25
|
email = create_email(email_body_text)
|
26
26
|
short_url = Shortener::ShortenedUrl.find_by_url(url)
|
27
|
-
short_url.
|
28
|
-
email.body.
|
27
|
+
expect(short_url).not_to be_nil
|
28
|
+
expect(email.body).to eq (raw_email_body_text % { url: "http://mbln.jp/#{short_url.unique_key}" })
|
29
29
|
end
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
33
|
shared_examples_for "does not shorten URL" do |url|
|
34
34
|
TEXTS.each do |raw_email_body_text|
|
35
|
-
email_body_text = raw_email_body_text % {:url
|
35
|
+
email_body_text = raw_email_body_text % { url: url }
|
36
36
|
it("keeps URL for #{email_body_text}") do
|
37
37
|
email = create_email(email_body_text)
|
38
38
|
short_url = Shortener::ShortenedUrl.find_by_url(url)
|
39
|
-
short_url.
|
40
|
-
email.body.
|
39
|
+
expect(short_url).to be_nil
|
40
|
+
expect(email.body).to eq email_body_text
|
41
41
|
end
|
42
42
|
end
|
43
43
|
end
|
@@ -57,6 +57,6 @@ describe Shortener::ShortenUrlInterceptor do
|
|
57
57
|
"http://d1dqic1fklzs1z.cloudfront.net/assets/doorkeeper_group_normal-3a3292fd09e39a70084c247aef60cba9.gif" # asset URL
|
58
58
|
].each do |url|
|
59
59
|
it_should_behave_like "does not shorten URL", url
|
60
|
-
end
|
60
|
+
end
|
61
61
|
|
62
62
|
end
|
data/spec/spec_helper.rb
CHANGED
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.
|
4
|
+
version: 0.4.0
|
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:
|
12
|
+
date: 2015-09-18 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -45,14 +45,14 @@ dependencies:
|
|
45
45
|
requirements:
|
46
46
|
- - "~>"
|
47
47
|
- !ruby/object:Gem::Version
|
48
|
-
version:
|
48
|
+
version: 3.3.0
|
49
49
|
type: :development
|
50
50
|
prerelease: false
|
51
51
|
version_requirements: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
53
|
- - "~>"
|
54
54
|
- !ruby/object:Gem::Version
|
55
|
-
version:
|
55
|
+
version: 3.3.0
|
56
56
|
- !ruby/object:Gem::Dependency
|
57
57
|
name: shoulda-matchers
|
58
58
|
requirement: !ruby/object:Gem::Requirement
|
@@ -67,6 +67,34 @@ dependencies:
|
|
67
67
|
- - ">="
|
68
68
|
- !ruby/object:Gem::Version
|
69
69
|
version: '0'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: faker
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: byebug
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
type: :development
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
70
98
|
description: Shortener is a Rails Engine Gem that makes it easy to create and interpret
|
71
99
|
shortened URLs on your own domain from within your Rails application. Once installed
|
72
100
|
Shortener will generate, store URLS and "unshorten" shortened URLs for your applications
|
@@ -147,7 +175,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
147
175
|
version: 1.3.6
|
148
176
|
requirements: []
|
149
177
|
rubyforge_project: shortener
|
150
|
-
rubygems_version: 2.
|
178
|
+
rubygems_version: 2.4.5.1
|
151
179
|
signing_key:
|
152
180
|
specification_version: 4
|
153
181
|
summary: Shortener is a Rails Engine that makes it easy to create shortened URLs for
|