shortener 0.1.2 → 0.2.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.
- data/.gitignore +1 -0
- data/README.rdoc +16 -0
- data/app/controllers/shortener/shortened_urls_controller.rb +4 -1
- data/lib/shortener.rb +1 -0
- data/lib/shortener/railtie.rb +3 -1
- data/lib/shortener/shorten_url_interceptor.rb +63 -0
- data/lib/shortener/version.rb +1 -1
- data/spec/controllers/shortened_urls_controller_spec.rb +30 -9
- data/spec/dummy/config/application.rb +3 -5
- data/spec/shortener/shorten_url_interceptor_spec.rb +62 -0
- metadata +13 -11
data/.gitignore
CHANGED
data/README.rdoc
CHANGED
@@ -77,6 +77,22 @@ And to access those URLs:
|
|
77
77
|
|
78
78
|
user.shortened_urls
|
79
79
|
|
80
|
+
=== Shorten URLs in generated emails
|
81
|
+
|
82
|
+
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:
|
83
|
+
|
84
|
+
class MyMailer < ActionMailer::Base
|
85
|
+
register_interceptor Shortener::ShortenUrlInterceptor.new
|
86
|
+
end
|
87
|
+
|
88
|
+
This will replace all long URLs in the emails generated by MyMailer with shortened versions. The base URL for the shortener will be infered from the mailer's default_url_options. If you use a different hostname for your shortener, you can use:
|
89
|
+
|
90
|
+
class MyMailer < ActionMailer::Base
|
91
|
+
register_interceptor Shortener::ShortenUrlInterceptor.new :base_url => "http://shortener.host"
|
92
|
+
end
|
93
|
+
|
94
|
+
The interceptor supports a few more arguments, see the implementation for details.
|
95
|
+
|
80
96
|
== Origins
|
81
97
|
|
82
98
|
Shortener is based on code from Dealush[http://dealush.com], for a bit of backstory to Shortener see this {blog post}[http://jamespmcgrath.com/a-simple-link-shortener-in-rails/].
|
@@ -2,8 +2,11 @@ class Shortener::ShortenedUrlsController < ActionController::Base
|
|
2
2
|
|
3
3
|
# find the real link for the shortened link key and redirect
|
4
4
|
def show
|
5
|
+
# only use the leading valid characters
|
6
|
+
token = /^([#{Shortener.key_chars.join}]*).*/.match(params[:id])[1]
|
7
|
+
|
5
8
|
# pull the link out of the db
|
6
|
-
sl = ::Shortener::ShortenedUrl.find_by_unique_key(
|
9
|
+
sl = ::Shortener::ShortenedUrl.find_by_unique_key(token)
|
7
10
|
|
8
11
|
if sl
|
9
12
|
# don't want to wait for the increment to happen, make it snappy!
|
data/lib/shortener.rb
CHANGED
data/lib/shortener/railtie.rb
CHANGED
@@ -6,6 +6,8 @@ class Shortener::Railtie < ::Rails::Railtie #:nodoc:
|
|
6
6
|
ActiveSupport.on_load :active_record do
|
7
7
|
extend Shortener::ActiveRecordExtension
|
8
8
|
end
|
9
|
-
|
9
|
+
ActiveSupport.on_load :action_view do
|
10
|
+
include Shortener::ShortenerHelper
|
11
|
+
end
|
10
12
|
end
|
11
13
|
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module Shortener
|
3
|
+
=begin
|
4
|
+
The Shorten URL Interceptor is a mail interceptor which shortens any URLs
|
5
|
+
in generated emails.
|
6
|
+
|
7
|
+
Usage:
|
8
|
+
|
9
|
+
class MyMailer < ActionMailer::Base
|
10
|
+
register_interceptor Shortener::ShortenUrlInterceptor.new
|
11
|
+
end
|
12
|
+
=end
|
13
|
+
class ShortenUrlInterceptor
|
14
|
+
|
15
|
+
DEFAULT_NOT_SHORTEN = [ 'twitter\.com/',
|
16
|
+
'facebook\.com/',
|
17
|
+
'cloudfront\.net/' ].map {|r| Regexp.new(r) }
|
18
|
+
DEFAULT_LENGTH_THRESHOLD = 20
|
19
|
+
|
20
|
+
URL_REGEX = /\b((https?):\/\/\w+\.)[-A-Z0-9+&@#\/%?=~_|$!:,.;]*[-A-Z0-9+&@#\/%=~_|$]/i
|
21
|
+
MIME_TYPES = %w(text/plain text/html application/xhtml+xml)
|
22
|
+
|
23
|
+
def initialize(opts = {})
|
24
|
+
@not_shorten = opts[:not_shorten] || DEFAULT_NOT_SHORTEN
|
25
|
+
@length_threshold = opts[:length_threshold] || DEFAULT_LENGTH_THRESHOLD
|
26
|
+
@base_url = opts[:base_url] || ShortenUrlInterceptor.infer_base_url
|
27
|
+
end
|
28
|
+
|
29
|
+
def delivering_email(email)
|
30
|
+
[email, email.all_parts].flatten.compact.each do |part|
|
31
|
+
if MIME_TYPES.include?(part.mime_type)
|
32
|
+
part.body = part.body.decoded.gsub(URL_REGEX) do |url|
|
33
|
+
shorten_url(url)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
protected
|
40
|
+
|
41
|
+
def shorten_url(url)
|
42
|
+
if url.length > @length_threshold && ! @not_shorten.any?{|r| r =~ url}
|
43
|
+
short_url = Shortener::ShortenedUrl.generate!(url)
|
44
|
+
File.join(@base_url, short_url.unique_key)
|
45
|
+
else
|
46
|
+
url
|
47
|
+
end
|
48
|
+
rescue => err
|
49
|
+
raise err if Rails.env.test?
|
50
|
+
Airbrake.notify(err, :url => url) if defined?(Airbrake)
|
51
|
+
return url
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.infer_base_url
|
55
|
+
host = ActionMailer::Base.default_url_options[:host]
|
56
|
+
if host.blank?
|
57
|
+
raise "Please supply :base_url for ShortenUrlInterceptor or define default_url_options for mailer"
|
58
|
+
else
|
59
|
+
"http://#{host}/"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/lib/shortener/version.rb
CHANGED
@@ -1,19 +1,40 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
require 'spec_helper'
|
3
3
|
|
4
|
+
shared_examples_for "good code" do
|
5
|
+
it "redirects to actual url" do
|
6
|
+
get :show, :id => code
|
7
|
+
response.should redirect_to("http://www.doorkeeperhq.com/")
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
shared_examples_for "wrong code" do
|
12
|
+
it "redirects to actual url" do
|
13
|
+
get :show, :id => code
|
14
|
+
response.should redirect_to("/")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
4
18
|
describe Shortener::ShortenedUrlsController do
|
5
19
|
let(:short_url) { Shortener::ShortenedUrl.generate("www.doorkeeperhq.com") }
|
6
20
|
|
7
|
-
describe "GET show with
|
8
|
-
|
9
|
-
|
10
|
-
response.should redirect_to("http://www.doorkeeperhq.com/")
|
11
|
-
end
|
21
|
+
describe "GET show with actual code" do
|
22
|
+
let(:code) { short_url.unique_key}
|
23
|
+
it_should_behave_like "good code"
|
12
24
|
end
|
25
|
+
|
26
|
+
describe "GET show with good code but trailing characters" do
|
27
|
+
let(:code) { "#{short_url.unique_key}-" }
|
28
|
+
it_should_behave_like "good code"
|
29
|
+
end
|
30
|
+
|
13
31
|
describe "GET show with wrong code" do
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
32
|
+
let(:code) { "testing" }
|
33
|
+
it_should_behave_like "wrong code"
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "GET show with code of invalid characters" do
|
37
|
+
let(:code) { "-" }
|
38
|
+
it_should_behave_like "wrong code"
|
18
39
|
end
|
19
40
|
end
|
@@ -1,10 +1,6 @@
|
|
1
1
|
require File.expand_path('../boot', __FILE__)
|
2
2
|
|
3
|
-
require "
|
4
|
-
require "active_record/railtie"
|
5
|
-
require "action_controller/railtie"
|
6
|
-
require "action_view/railtie"
|
7
|
-
|
3
|
+
require "rails/all"
|
8
4
|
Bundler.require
|
9
5
|
require "shortener"
|
10
6
|
|
@@ -40,5 +36,7 @@ module Dummy
|
|
40
36
|
|
41
37
|
# Configure sensitive parameters which will be filtered from the log file.
|
42
38
|
config.filter_parameters += [:password]
|
39
|
+
|
40
|
+
config.action_mailer.default_url_options = { :host => "mbln.jp" }
|
43
41
|
end
|
44
42
|
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'mail'
|
4
|
+
|
5
|
+
describe Shortener::ShortenUrlInterceptor do
|
6
|
+
|
7
|
+
def create_email(body)
|
8
|
+
Mail.new(:from => 'test@mbln.jp', :to => 'test@mbln.jp', :body => body).tap do |m|
|
9
|
+
m.encoded
|
10
|
+
Shortener::ShortenUrlInterceptor.new.delivering_email(m)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
TEXTS = [ "Test with URL: %{url}",
|
15
|
+
"Test with URL: %{url}!",
|
16
|
+
"Test with URL: %{url}, hu!",
|
17
|
+
"Test with URL: %{url}. hu!",
|
18
|
+
"Test with URL: <a href='%{url}'>test</a>",
|
19
|
+
"Test with URL: <a href=\"%{url}\">test</a>" ]
|
20
|
+
|
21
|
+
shared_examples_for "shortens URL in text" do |url|
|
22
|
+
TEXTS.each do |raw_email_body_text|
|
23
|
+
email_body_text = raw_email_body_text % {:url => url}
|
24
|
+
it("shortens for #{email_body_text}") do
|
25
|
+
email = create_email(email_body_text)
|
26
|
+
short_url = Shortener::ShortenedUrl.find_by_url(url)
|
27
|
+
short_url.should_not be_nil
|
28
|
+
email.body.should == (raw_email_body_text % {:url => "http://mbln.jp/#{short_url.unique_key}"})
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
shared_examples_for "does not shorten URL" do |url|
|
34
|
+
TEXTS.each do |raw_email_body_text|
|
35
|
+
email_body_text = raw_email_body_text % {:url => url}
|
36
|
+
it("keeps URL for #{email_body_text}") do
|
37
|
+
email = create_email(email_body_text)
|
38
|
+
short_url = Shortener::ShortenedUrl.find_by_url(url)
|
39
|
+
short_url.should be_nil
|
40
|
+
email.body.should == email_body_text
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
[ "http://client.doorkeeper.jp/events/124-title",
|
46
|
+
"http://client.doorkeeper.jp/events/124-",
|
47
|
+
"http://client.doorkeeper.jp/events/124-title?auth_token=xabagangs",
|
48
|
+
"http://client.doorkeeper.jp/events/124-%E4%F6%A0",
|
49
|
+
].each do |url|
|
50
|
+
it_should_behave_like "shortens URL in text", url
|
51
|
+
end
|
52
|
+
|
53
|
+
# we won't shorten certain URLs:
|
54
|
+
[ "http://t.co/asdvk", # short URL
|
55
|
+
"http://twitter.com/doorkeeper_app", # twitter URL
|
56
|
+
"http://facebook.com/doorkeeper_app", # facebook URL
|
57
|
+
"http://d1dqic1fklzs1z.cloudfront.net/assets/doorkeeper_group_normal-3a3292fd09e39a70084c247aef60cba9.gif" # asset URL
|
58
|
+
].each do |url|
|
59
|
+
it_should_behave_like "does not shorten URL", url
|
60
|
+
end
|
61
|
+
|
62
|
+
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.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,11 +10,11 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2012-04-
|
13
|
+
date: 2012-04-29 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rails
|
17
|
-
requirement: &
|
17
|
+
requirement: &70307977503340 !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ! '>='
|
@@ -22,10 +22,10 @@ dependencies:
|
|
22
22
|
version: 3.0.7
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
|
-
version_requirements: *
|
25
|
+
version_requirements: *70307977503340
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: sqlite3
|
28
|
-
requirement: &
|
28
|
+
requirement: &70307977519260 !ruby/object:Gem::Requirement
|
29
29
|
none: false
|
30
30
|
requirements:
|
31
31
|
- - ! '>='
|
@@ -33,10 +33,10 @@ dependencies:
|
|
33
33
|
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
|
-
version_requirements: *
|
36
|
+
version_requirements: *70307977519260
|
37
37
|
- !ruby/object:Gem::Dependency
|
38
38
|
name: rspec-rails
|
39
|
-
requirement: &
|
39
|
+
requirement: &70307977518620 !ruby/object:Gem::Requirement
|
40
40
|
none: false
|
41
41
|
requirements:
|
42
42
|
- - ! '>='
|
@@ -44,10 +44,10 @@ dependencies:
|
|
44
44
|
version: '0'
|
45
45
|
type: :development
|
46
46
|
prerelease: false
|
47
|
-
version_requirements: *
|
47
|
+
version_requirements: *70307977518620
|
48
48
|
- !ruby/object:Gem::Dependency
|
49
49
|
name: shoulda-matchers
|
50
|
-
requirement: &
|
50
|
+
requirement: &70307977517720 !ruby/object:Gem::Requirement
|
51
51
|
none: false
|
52
52
|
requirements:
|
53
53
|
- - ! '>='
|
@@ -55,7 +55,7 @@ dependencies:
|
|
55
55
|
version: '0'
|
56
56
|
type: :development
|
57
57
|
prerelease: false
|
58
|
-
version_requirements: *
|
58
|
+
version_requirements: *70307977517720
|
59
59
|
description: Shortener is a Rails Engine Gem that makes it easy to create and interpret
|
60
60
|
shortened URLs on your own domain from within your Rails application. Once installed
|
61
61
|
Shortener will generate, store URLS and "unshorten" shortened URLs for your applications
|
@@ -82,6 +82,7 @@ files:
|
|
82
82
|
- lib/shortener/active_record_extension.rb
|
83
83
|
- lib/shortener/engine.rb
|
84
84
|
- lib/shortener/railtie.rb
|
85
|
+
- lib/shortener/shorten_url_interceptor.rb
|
85
86
|
- lib/shortener/version.rb
|
86
87
|
- shortener.gemspec
|
87
88
|
- spec/controllers/shortened_urls_controller_spec.rb
|
@@ -113,6 +114,7 @@ files:
|
|
113
114
|
- spec/dummy/script/rails
|
114
115
|
- spec/helpers/shortener_helper_spec.rb
|
115
116
|
- spec/models/shortened_url_spec.rb
|
117
|
+
- spec/shortener/shorten_url_interceptor_spec.rb
|
116
118
|
- spec/spec_helper.rb
|
117
119
|
homepage: http://jamespmcgrath.com/projects/shortener
|
118
120
|
licenses: []
|
@@ -134,7 +136,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
134
136
|
version: 1.3.6
|
135
137
|
requirements: []
|
136
138
|
rubyforge_project: shortener
|
137
|
-
rubygems_version: 1.8.
|
139
|
+
rubygems_version: 1.8.17
|
138
140
|
signing_key:
|
139
141
|
specification_version: 3
|
140
142
|
summary: Shortener is a Rails Engine that makes it easy to create shortened URLs for
|