ducklink 0.0.2
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 +4 -0
- data/Gemfile +4 -0
- data/README.markdown +96 -0
- data/Rakefile +1 -0
- data/ducklink.gemspec +20 -0
- data/lib/ducklink.rb +70 -0
- data/lib/ducklink/version.rb +3 -0
- metadata +63 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.markdown
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Ducklink #
|
|
2
|
+
|
|
3
|
+
Ducklink is a super-simple way of centrally managing the format of URLs which should be used for links to other sites. Quack.
|
|
4
|
+
|
|
5
|
+
## Why ##
|
|
6
|
+
|
|
7
|
+
* Maybe you have an affiliate deal with a site which requires redirecting through a third-party platform
|
|
8
|
+
* Maybe you need to add parameters to URLs for campaign management
|
|
9
|
+
* Er..
|
|
10
|
+
* Hmm.
|
|
11
|
+
|
|
12
|
+
## How ##
|
|
13
|
+
|
|
14
|
+
Given a URL, Ducklink will extract the host and try to match against one of its configured formats.
|
|
15
|
+
|
|
16
|
+
If nothing matches, the URL is returned untouched. If a match is found, then the URL returned will be based on the format together with any run-time parameters you passed in.
|
|
17
|
+
|
|
18
|
+
### Add parameters ###
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
Ducklink::Decorator.configure do
|
|
22
|
+
host 'www.example.com' do
|
|
23
|
+
format '{{url}}?extra=params&added=here'
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
Ducklink.decorate 'http://www.example.com/some/path'
|
|
28
|
+
=> http://www.example.com/some/path?extra=params&added=here
|
|
29
|
+
|
|
30
|
+
### Redirects ###
|
|
31
|
+
|
|
32
|
+
Ducklink::Decorator.configure do
|
|
33
|
+
host 'www.example.com' do
|
|
34
|
+
format 'http://affiliate.example.com?clickref=42&url={{url}}'
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
Ducklink.decorate 'http://www.example.com/some/path'
|
|
39
|
+
=> http://affiliate.example.com?clickref=42&url=http://www.example.com/some/path
|
|
40
|
+
|
|
41
|
+
If you need to, you can URLEncode the target URL explicitly:
|
|
42
|
+
|
|
43
|
+
Ducklink::Decorator.configure do
|
|
44
|
+
host 'www.example.com' do
|
|
45
|
+
format 'http://affiliate.example.com?clickref=42&url={{url}}'
|
|
46
|
+
set :url, CGI::escape(self[:url])
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
Ducklink.decorate 'http://www.example.com/some/path'
|
|
51
|
+
=> http://affiliate.example.com?clickref=42&url=http%3A%2F%2Fwww.example.com%2Fsome%2Fpath
|
|
52
|
+
|
|
53
|
+
### Run-time parameters ###
|
|
54
|
+
|
|
55
|
+
Ducklink::Decorator.configure do
|
|
56
|
+
host 'www.example.com' do |context|
|
|
57
|
+
format 'http://affiliate.example.com?clickref={{reference}}&url={{url}}'
|
|
58
|
+
set :reference, context[:reference]
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
Ducklink.decorate 'http://www.example.com/some/path', :reference => 100
|
|
63
|
+
=> http://affiliate.example.com?clickref=100&url=http://www.example.com/some/path
|
|
64
|
+
|
|
65
|
+
### Specify format of groups ###
|
|
66
|
+
|
|
67
|
+
Ducklink::Decorator.configure do
|
|
68
|
+
group do
|
|
69
|
+
format 'http://affiliate.example.com?clickref={{reference}}&url={{url}}#campaign={{campaign}}'
|
|
70
|
+
host 'buy.example.com', 'shop.example.com' do |context|
|
|
71
|
+
set :campaign, 'campaign1'
|
|
72
|
+
set :reference, context[:reference]
|
|
73
|
+
end
|
|
74
|
+
host 'another.com' do |context|
|
|
75
|
+
set :campaign, 'campaign2'
|
|
76
|
+
set :reference, context[:reference]
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
Ducklink.decorate 'http://shop.example.com/goodies', :reference => 100
|
|
82
|
+
=> http://affiliate.example.com?clickref=100&url=http://shop.example.com/goodies#campaign=campaign1
|
|
83
|
+
|
|
84
|
+
## TODO ##
|
|
85
|
+
|
|
86
|
+
1. Tests!
|
|
87
|
+
2. URL validity checks
|
|
88
|
+
3. Merge parameters if url already has them
|
|
89
|
+
4. Intelligently URL encode parameters
|
|
90
|
+
5. Support introspection of keys expected in context so calling code knows what to provide
|
|
91
|
+
|
|
92
|
+
## Licence ##
|
|
93
|
+
|
|
94
|
+
Ducklink is released under the MIT Licence.
|
|
95
|
+
|
|
96
|
+
Copyright © 2011 Henry Garner
|
data/Rakefile
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require 'bundler/gem_tasks'
|
data/ducklink.gemspec
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
|
3
|
+
require "ducklink/version"
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |s|
|
|
6
|
+
s.name = "ducklink"
|
|
7
|
+
s.version = Ducklink::VERSION
|
|
8
|
+
s.authors = ["Henry Garner"]
|
|
9
|
+
s.email = ["henry.garner@mac.com"]
|
|
10
|
+
s.homepage = ""
|
|
11
|
+
s.summary = %q{Decorates URLs according to a format specification}
|
|
12
|
+
s.description = %q{}
|
|
13
|
+
|
|
14
|
+
s.rubyforge_project = "ducklink"
|
|
15
|
+
|
|
16
|
+
s.files = `git ls-files`.split("\n")
|
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
|
19
|
+
s.require_paths = ["lib"]
|
|
20
|
+
end
|
data/lib/ducklink.rb
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
require "ducklink/version"
|
|
2
|
+
require 'uri'
|
|
3
|
+
require 'cgi'
|
|
4
|
+
|
|
5
|
+
module Ducklink
|
|
6
|
+
def self.decorate(url)
|
|
7
|
+
Decorator.decorate(url)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
class Decorator
|
|
11
|
+
class << self
|
|
12
|
+
@@hosts = {}
|
|
13
|
+
|
|
14
|
+
def configure(&block)
|
|
15
|
+
Params.new.instance_exec &block
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def hosts
|
|
19
|
+
@@hosts
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def host(domain, params, &block)
|
|
23
|
+
@@hosts[domain] = [params, block]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def decorate(url, context = {})
|
|
27
|
+
params, block = hosts[URI.parse(url).host]
|
|
28
|
+
return url unless params
|
|
29
|
+
|
|
30
|
+
params.set :url, url
|
|
31
|
+
params.instance_exec context, &block
|
|
32
|
+
|
|
33
|
+
format = params[:format]
|
|
34
|
+
format.scan(/\{\{([a-z_]+?)\}\}/i).inject(format) do |result, matches|
|
|
35
|
+
params[matches.first] ? result.gsub("{{#{matches.first}}}", params[matches.first]) : result
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
class Params
|
|
42
|
+
attr_reader :settings
|
|
43
|
+
|
|
44
|
+
def initialize(settings = {})
|
|
45
|
+
@settings = settings
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def format(format)
|
|
49
|
+
set :format, format
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def group(&block)
|
|
53
|
+
Params.new(settings.clone).instance_exec &block
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def set(key, value)
|
|
57
|
+
@settings[key.to_s] = value.to_s
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def [](key)
|
|
61
|
+
@settings[key.to_s]
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def host(*domains, &block)
|
|
65
|
+
domains.each do |domain|
|
|
66
|
+
Ducklink::Decorator.host domain, Params.new(settings.clone), &block
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: ducklink
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
prerelease:
|
|
5
|
+
version: 0.0.2
|
|
6
|
+
platform: ruby
|
|
7
|
+
authors:
|
|
8
|
+
- Henry Garner
|
|
9
|
+
autorequire:
|
|
10
|
+
bindir: bin
|
|
11
|
+
cert_chain: []
|
|
12
|
+
|
|
13
|
+
date: 2011-07-23 00:00:00 +01:00
|
|
14
|
+
default_executable:
|
|
15
|
+
dependencies: []
|
|
16
|
+
|
|
17
|
+
description: ""
|
|
18
|
+
email:
|
|
19
|
+
- henry.garner@mac.com
|
|
20
|
+
executables: []
|
|
21
|
+
|
|
22
|
+
extensions: []
|
|
23
|
+
|
|
24
|
+
extra_rdoc_files: []
|
|
25
|
+
|
|
26
|
+
files:
|
|
27
|
+
- .gitignore
|
|
28
|
+
- Gemfile
|
|
29
|
+
- README.markdown
|
|
30
|
+
- Rakefile
|
|
31
|
+
- ducklink.gemspec
|
|
32
|
+
- lib/ducklink.rb
|
|
33
|
+
- lib/ducklink/version.rb
|
|
34
|
+
has_rdoc: true
|
|
35
|
+
homepage: ""
|
|
36
|
+
licenses: []
|
|
37
|
+
|
|
38
|
+
post_install_message:
|
|
39
|
+
rdoc_options: []
|
|
40
|
+
|
|
41
|
+
require_paths:
|
|
42
|
+
- lib
|
|
43
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
44
|
+
none: false
|
|
45
|
+
requirements:
|
|
46
|
+
- - ">="
|
|
47
|
+
- !ruby/object:Gem::Version
|
|
48
|
+
version: "0"
|
|
49
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
50
|
+
none: false
|
|
51
|
+
requirements:
|
|
52
|
+
- - ">="
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: "0"
|
|
55
|
+
requirements: []
|
|
56
|
+
|
|
57
|
+
rubyforge_project: ducklink
|
|
58
|
+
rubygems_version: 1.6.2
|
|
59
|
+
signing_key:
|
|
60
|
+
specification_version: 3
|
|
61
|
+
summary: Decorates URLs according to a format specification
|
|
62
|
+
test_files: []
|
|
63
|
+
|