budurl 0.0.1
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 +7 -0
- data/README.md +14 -0
- data/Rakefile +9 -0
- data/bin/expand +9 -0
- data/bin/shorten +9 -0
- data/bin/stats +21 -0
- data/budurl.gemspec +26 -0
- data/lib/budurl.rb +9 -0
- data/lib/budurl/client.rb +67 -0
- data/lib/budurl/url.rb +31 -0
- data/lib/budurl/version.rb +3 -0
- data/test/helpers/budurl_mock.rb +112 -0
- data/test/unit/client_spec.rb +141 -0
- data/test/unit/url_spec.rb +87 -0
- metadata +153 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# BudURL
|
2
|
+
|
3
|
+
### About
|
4
|
+
|
5
|
+
This gem provides a simple interface to the BudURL.Pro API, documented [here](http://budurl.com/page/budurlpro-api). BudURL provides URL shortening services as well as analytics, some of which is available externally. In particular, the API allows:
|
6
|
+
* **Shortening URLs** along with adding notes, setting redirect types, and checking for duplicates,
|
7
|
+
* **Expanding URLs** which have been shortened using the service,
|
8
|
+
* **Gathering analytics** such as click counts either since link creation or on a day-by-day basis, filterable by time period.
|
9
|
+
|
10
|
+
### Usage
|
11
|
+
|
12
|
+
The BudURL API requires an API key for any usage other than URL expansion. More details at their website, [BudURL.Pro](http://budurl.pro).
|
13
|
+
|
14
|
+
Initialise a client using `Budurl.new(<API_KEY>)`. It provides `shorten(url, opts)` and `expand(short_url)` functionality; the resulting `Budurl::Url` objects can be used to acquire additional information such as click counts. Options not exposed in code can be passed in as options; generally speaking, any option available through the API should be accessible.
|
data/Rakefile
ADDED
data/bin/expand
ADDED
data/bin/shorten
ADDED
data/bin/stats
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'date'
|
3
|
+
|
4
|
+
$:.push("lib")
|
5
|
+
|
6
|
+
require 'budurl'
|
7
|
+
|
8
|
+
budurl = Budurl.new(ARGV[0])
|
9
|
+
|
10
|
+
url = budurl.expand(ARGV[1])
|
11
|
+
|
12
|
+
date_from = ARGV[2] ? Date.parse(ARGV[2]) : nil
|
13
|
+
date_to = ARGV[3] ? Date.parse(ARGV[3]) : nil
|
14
|
+
|
15
|
+
count = url.clicks(false, date_from, date_to)
|
16
|
+
dates = url.clicks(true, date_from, date_to)
|
17
|
+
|
18
|
+
puts "URL: #{url.long_url}"
|
19
|
+
puts "Total clicks: #{count}"
|
20
|
+
puts "Per date:"
|
21
|
+
dates.each {|date,clicks| puts "#{date}: #{clicks}"}
|
data/budurl.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "budurl/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "budurl"
|
7
|
+
s.version = Budurl::VERSION
|
8
|
+
s.authors = ["Anuj Das"]
|
9
|
+
s.email = ["anuj.das@mylookout.com"]
|
10
|
+
s.homepage = "https://github.com/lookout/budurl-gem"
|
11
|
+
s.summary = %q{A gem for interfacing with the BudURL.Pro url shortener API}
|
12
|
+
s.description = %q{Supported operations include shrinking, expanding, and counting clicks.}
|
13
|
+
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
|
19
|
+
s.add_dependency 'httparty'
|
20
|
+
|
21
|
+
# specify any dependencies here; for example:
|
22
|
+
s.add_development_dependency 'ruby-debug'
|
23
|
+
s.add_development_dependency 'rspec'
|
24
|
+
s.add_development_dependency 'mimic'
|
25
|
+
s.add_development_dependency 'json'
|
26
|
+
end
|
data/lib/budurl.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
module Budurl
|
2
|
+
def self.new(api_key, uri = BUDURL_PRO_BASE_URI)
|
3
|
+
Budurl::Client.new(api_key, uri)
|
4
|
+
end
|
5
|
+
|
6
|
+
class Client
|
7
|
+
include HTTParty
|
8
|
+
|
9
|
+
format :json
|
10
|
+
|
11
|
+
# Returns a Budurl client which can be used to query API services.
|
12
|
+
# uri is the base uri for the BudURL API.
|
13
|
+
def initialize(api_key, uri)
|
14
|
+
self.class.base_uri uri
|
15
|
+
@default_query_opts = { :api_key => api_key }
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns a Budurl::Url object containing a shorturl.
|
19
|
+
# opts allow duplicate checking, notes, etc. For all options,
|
20
|
+
# see the BudURL API: http://budurl.com/page/budurlpro-api
|
21
|
+
def shorten(url, opts = {})
|
22
|
+
query_opts = {:long_url => url}.merge(opts)
|
23
|
+
response = get('/links/shrink', :query => query_opts)
|
24
|
+
Budurl::Url.new(self, response)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns a Budurl::Url object containing a longurl.
|
28
|
+
def expand(short_url)
|
29
|
+
query_opts = {:link => short_url}
|
30
|
+
response = get('/links/expand', :query => query_opts)
|
31
|
+
Budurl::Url.new(self, response)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Returns a hash containing click counts since creation.
|
35
|
+
# opts allow daily click counts and date filters. For all options,
|
36
|
+
# see the BudURL API: http://budurl.com/page/budurlpro-api
|
37
|
+
def clicks(short_url, opts = {})
|
38
|
+
query_opts = {:link => short_url}.merge(opts)
|
39
|
+
response = get('/clicks/count', :query => query_opts)
|
40
|
+
end
|
41
|
+
|
42
|
+
def get(uri, opts = {})
|
43
|
+
opts[:query] ||= {}
|
44
|
+
opts[:query].merge!(@default_query_opts)
|
45
|
+
response = self.class.get(uri, opts).parsed_response
|
46
|
+
if response.nil?
|
47
|
+
raise Error.new('No response from server.', 0)
|
48
|
+
elsif response['success'] == 1
|
49
|
+
response
|
50
|
+
else
|
51
|
+
raise Error.new(response['error_message'], response['error_code'])
|
52
|
+
end
|
53
|
+
end
|
54
|
+
private :get
|
55
|
+
end
|
56
|
+
|
57
|
+
# This class encapsulates BudURL API errors into a usable form.
|
58
|
+
class Error < StandardError
|
59
|
+
attr_reader :code
|
60
|
+
|
61
|
+
def initialize(message, code)
|
62
|
+
@code = code
|
63
|
+
super("#{code} - #{message}")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
data/lib/budurl/url.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
module Budurl
|
4
|
+
class Url
|
5
|
+
|
6
|
+
attr_accessor :link, :long_url, :hash
|
7
|
+
|
8
|
+
# Create a Url with values filled in from a Client response.
|
9
|
+
def initialize(client, response = nil)
|
10
|
+
@client = client
|
11
|
+
|
12
|
+
if response && response.is_a?(Hash)
|
13
|
+
@link = response['link']
|
14
|
+
@long_url = response['long_url']
|
15
|
+
@hash = response['hash']
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Retrieve click counts for this shorturl.
|
20
|
+
# daily flag allows day-by-day breakdowns.
|
21
|
+
# date_from and date_to are Date objects which allow filtering.
|
22
|
+
def clicks(daily=false, date_from=nil, date_to=nil)
|
23
|
+
opts = { :daily => daily ? 1 : 0 }
|
24
|
+
opts.merge!(:date_from => date_from.to_s) if date_from
|
25
|
+
opts.merge!(:date_to => date_to.to_s) if date_to
|
26
|
+
|
27
|
+
response = @client.clicks(@link, opts)
|
28
|
+
daily ? response['dates'] : response['count']
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'mimic'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
class BudurlMock
|
6
|
+
|
7
|
+
API_KEY_ERROR = 100
|
8
|
+
LONG_URL_ERROR = 200
|
9
|
+
SHORT_URL_ERROR = 400
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
self.clear
|
13
|
+
end
|
14
|
+
|
15
|
+
[:api_keys, :short_to_long_urls].each do |var|
|
16
|
+
class_eval %{
|
17
|
+
def self.#{var.to_s}
|
18
|
+
@@#{var}
|
19
|
+
end
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.clear
|
24
|
+
# valid api keys
|
25
|
+
@@api_keys = []
|
26
|
+
|
27
|
+
# url mappings: short_url => {link, api_key, count, dates => {date => count, ...}}
|
28
|
+
@@short_to_long_urls = {}
|
29
|
+
|
30
|
+
# next unused short_url
|
31
|
+
@@next_hash = 0
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.hash_from_short_url(url)
|
35
|
+
url.match(/^http:\/\/Ez\.com\/(\d{4})$/)[1]
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.short_url_from_hash(hash)
|
39
|
+
"http://Ez.com/#{hash}"
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.find_by_long_url(long_url)
|
43
|
+
short_url = @@short_to_long_urls.select{|k,v| v[:link] == long_url}.last
|
44
|
+
short_url ? short_url[0] : nil
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.error_response(code)
|
48
|
+
{:success => 0, :error_code => code, :error_message => "Error"}
|
49
|
+
end
|
50
|
+
|
51
|
+
Mimic.mimic do
|
52
|
+
get '/links/shrink' do
|
53
|
+
if !@@api_keys.include?(params[:api_key])
|
54
|
+
response = BudurlMock.error_response(API_KEY_ERROR)
|
55
|
+
elsif params[:long_url].empty?
|
56
|
+
response = BudurlMock.error_response(LONG_URL_ERROR)
|
57
|
+
else
|
58
|
+
if params[:dupe_check] != '1' || !(short_url = BudurlMock.find_by_long_url(params[:long_url]))
|
59
|
+
short_url = BudurlMock.short_url_from_hash("%04d" % @@next_hash += 1)
|
60
|
+
@@short_to_long_urls[short_url] = {:link => params[:long_url],
|
61
|
+
:api_key => params[:api_key],
|
62
|
+
:count => 0,
|
63
|
+
:date => {}}
|
64
|
+
end
|
65
|
+
response = {:success => 1,
|
66
|
+
:link => short_url,
|
67
|
+
:hash => BudurlMock.hash_from_short_url(short_url),
|
68
|
+
:link_preview => short_url + '?'}
|
69
|
+
end
|
70
|
+
|
71
|
+
return [200, response.to_json]
|
72
|
+
end
|
73
|
+
|
74
|
+
get '/links/expand' do
|
75
|
+
if !@@api_keys.include?(params[:api_key])
|
76
|
+
response = BudurlMock.error_response(API_KEY_ERROR)
|
77
|
+
elsif params[:link].nil?
|
78
|
+
return [200, nil]
|
79
|
+
else
|
80
|
+
url = @@short_to_long_urls[params[:link]]
|
81
|
+
if url.nil?
|
82
|
+
response = BudurlMock.error_response(SHORT_URL_ERROR)
|
83
|
+
else
|
84
|
+
response = {:success => 1,
|
85
|
+
:long_url => url[:link]}
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
return [200, response.to_json]
|
90
|
+
end
|
91
|
+
|
92
|
+
get '/clicks/count' do
|
93
|
+
if !@@api_keys.include?(params[:api_key])
|
94
|
+
response = BudurlMock.error_response(API_KEY_ERROR)
|
95
|
+
elsif params[:link].nil?
|
96
|
+
return [200, nil]
|
97
|
+
elsif !(url = @@short_to_long_urls[params[:link]])
|
98
|
+
response = BudurlMock.error_response(SHORT_URL_ERROR)
|
99
|
+
elsif params[:api_key] != url[:api_key]
|
100
|
+
response = BudurlMock.error_response(API_KEY_ERROR)
|
101
|
+
else
|
102
|
+
response = {:success => 1,
|
103
|
+
:link => params[:link],
|
104
|
+
:hash => BudurlMock.hash_from_short_url(params[:link]),
|
105
|
+
:count => url[:count]}
|
106
|
+
response.merge!(:dates => url[:dates]) if params[:daily] == '1'
|
107
|
+
end
|
108
|
+
|
109
|
+
return [200, response.to_json]
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rspec'
|
3
|
+
require 'budurl'
|
4
|
+
require 'budurl/client'
|
5
|
+
require File.dirname(__FILE__) + '/../helpers/budurl_mock'
|
6
|
+
|
7
|
+
require 'ruby-debug'
|
8
|
+
|
9
|
+
describe Budurl::Client do
|
10
|
+
|
11
|
+
MIMIC_BASE_URI = 'http://127.0.0.1:11988'
|
12
|
+
API_KEY = '12345'
|
13
|
+
|
14
|
+
SHORT_URL = 'http://Ez.com/1234'
|
15
|
+
LONG_URL = 'http://www.example.com'
|
16
|
+
|
17
|
+
def create_short_url(long_url, short_url, opts={})
|
18
|
+
data = {:link => long_url,
|
19
|
+
:api_key => API_KEY,
|
20
|
+
:count => 0,
|
21
|
+
:dates => {}}.merge(opts)
|
22
|
+
BudurlMock.short_to_long_urls[short_url] = data
|
23
|
+
end
|
24
|
+
|
25
|
+
before :all do
|
26
|
+
@budurl = Budurl.new(API_KEY, MIMIC_BASE_URI)
|
27
|
+
end
|
28
|
+
|
29
|
+
before :each do
|
30
|
+
BudurlMock.clear
|
31
|
+
BudurlMock.api_keys << API_KEY
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'initialises with the correct API key' do
|
35
|
+
@budurl.instance_variable_get(:@default_query_opts).should == {:api_key => API_KEY}
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'returns a Budurl::Client object' do
|
39
|
+
@budurl.should be_an_instance_of(Budurl::Client)
|
40
|
+
end
|
41
|
+
|
42
|
+
describe '#shorten' do
|
43
|
+
it 'successfully shortens a URL' do
|
44
|
+
url = @budurl.shorten(LONG_URL)
|
45
|
+
|
46
|
+
url.link.should == BudurlMock.find_by_long_url(LONG_URL)
|
47
|
+
url.hash.should == BudurlMock.hash_from_short_url(url.link)
|
48
|
+
url.long_url.should be_nil
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'creates unique short URLs if dupe_check is off' do
|
52
|
+
create_short_url(LONG_URL, SHORT_URL)
|
53
|
+
url = @budurl.shorten(LONG_URL)
|
54
|
+
|
55
|
+
url.link.should_not == SHORT_URL
|
56
|
+
url.hash.should_not == BudurlMock.hash_from_short_url(SHORT_URL)
|
57
|
+
url.long_url.should be_nil
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'returns the last address if dupe_check is on' do
|
61
|
+
create_short_url(LONG_URL, SHORT_URL)
|
62
|
+
url = @budurl.shorten(LONG_URL, :dupe_check => 1)
|
63
|
+
|
64
|
+
url.link.should == SHORT_URL
|
65
|
+
url.hash.should == BudurlMock.hash_from_short_url(SHORT_URL)
|
66
|
+
url.long_url.should be_nil
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'creates a new short URL if dupe_check is on but no duplicates exist' do
|
70
|
+
url = @budurl.shorten(LONG_URL, :dupe_check => 1)
|
71
|
+
|
72
|
+
url.link.should == BudurlMock.find_by_long_url(LONG_URL)
|
73
|
+
url.hash.should == BudurlMock.hash_from_short_url(url.link)
|
74
|
+
url.long_url.should be_nil
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'reports Error 200 when called without a URL' do
|
78
|
+
lambda { @budurl.shorten(nil) }.should raise_error(Budurl::Error, /200/)
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'reports Error 100 when called with an invalid API key' do
|
82
|
+
BudurlMock.api_keys.delete(API_KEY)
|
83
|
+
lambda { @budurl.shorten(LONG_URL) }.should raise_error(Budurl::Error, /100/)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe '#expand' do
|
88
|
+
it 'successfully expands an extant short URL' do
|
89
|
+
create_short_url(LONG_URL, SHORT_URL)
|
90
|
+
url = @budurl.expand(SHORT_URL)
|
91
|
+
|
92
|
+
url.long_url.should == LONG_URL
|
93
|
+
url.link.should be_nil
|
94
|
+
url.hash.should be_nil
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'reports Error 400 when passed an invalid short URL' do
|
98
|
+
lambda { @budurl.expand(SHORT_URL) }.should raise_error(Budurl::Error, /400/)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe '#clicks' do
|
103
|
+
it 'produces a total click count' do
|
104
|
+
create_short_url(LONG_URL, SHORT_URL, :count => 10)
|
105
|
+
count = @budurl.clicks(SHORT_URL)
|
106
|
+
|
107
|
+
count.should be_an_instance_of(Hash)
|
108
|
+
count['link'].should == SHORT_URL
|
109
|
+
count['hash'].should == BudurlMock.hash_from_short_url(SHORT_URL)
|
110
|
+
count['count'].should == 10
|
111
|
+
count['dates'].should be_nil
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'produces a day-to-day click count hash with the correct options' do
|
115
|
+
dates = {'2012-01-01' => 3, '2012-01-02' => 4, '2012-01-03' => 3}
|
116
|
+
create_short_url(LONG_URL, SHORT_URL, :count => 10, :dates => dates)
|
117
|
+
count = @budurl.clicks(SHORT_URL, :daily => 1)
|
118
|
+
|
119
|
+
count.should be_an_instance_of(Hash)
|
120
|
+
count['link'].should == SHORT_URL
|
121
|
+
count['hash'].should == BudurlMock.hash_from_short_url(SHORT_URL)
|
122
|
+
count['count'].should == 10
|
123
|
+
count['dates'].should be_an_instance_of(Hash)
|
124
|
+
count['dates'].should == dates
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'reports Error 400 when passed an invalid short URL' do
|
128
|
+
lambda { @budurl.clicks(SHORT_URL) }.should raise_error(Budurl::Error, /400/)
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'reports Error 100 when passed a short URL not belonging to us' do
|
132
|
+
create_short_url(LONG_URL, SHORT_URL, :api_key => '00000')
|
133
|
+
lambda { @budurl.clicks(SHORT_URL) }.should raise_error(Budurl::Error, /100/)
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'reports Error 100 when called with an invalid API key' do
|
137
|
+
BudurlMock.api_keys.delete(API_KEY)
|
138
|
+
lambda { @budurl.clicks(SHORT_URL) }.should raise_error(Budurl::Error, /100/)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rspec'
|
3
|
+
require 'budurl'
|
4
|
+
require 'budurl/url'
|
5
|
+
require File.dirname(__FILE__) + '/../helpers/budurl_mock'
|
6
|
+
|
7
|
+
require 'ruby-debug'
|
8
|
+
|
9
|
+
describe Budurl::Url do
|
10
|
+
|
11
|
+
MIMIC_BASE_URI = 'http://127.0.0.1:11988'
|
12
|
+
API_KEY = '12345'
|
13
|
+
|
14
|
+
SHORT_URL = 'http://Ez.com/1234'
|
15
|
+
LONG_URL = 'http://www.example.com'
|
16
|
+
|
17
|
+
def create_short_url(long_url, short_url, opts={})
|
18
|
+
data = {:link => long_url,
|
19
|
+
:api_key => API_KEY,
|
20
|
+
:count => 0,
|
21
|
+
:dates => {}}.merge(opts)
|
22
|
+
BudurlMock.short_to_long_urls[short_url] = data
|
23
|
+
end
|
24
|
+
|
25
|
+
before :all do
|
26
|
+
@budurl = Budurl.new(API_KEY, MIMIC_BASE_URI)
|
27
|
+
end
|
28
|
+
|
29
|
+
before :each do
|
30
|
+
BudurlMock.clear
|
31
|
+
BudurlMock.api_keys << API_KEY
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'saves the calling Budurl client internally' do
|
35
|
+
url = Budurl::Url.new(@budurl)
|
36
|
+
url.instance_variable_get(:@client).should be_an_instance_of(Budurl::Client)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'internalizes relevant information from a hash' do
|
40
|
+
data = {'success' => '1',
|
41
|
+
'link' => SHORT_URL,
|
42
|
+
'long_url' => LONG_URL,
|
43
|
+
'hash' => BudurlMock.hash_from_short_url(SHORT_URL)}
|
44
|
+
url = Budurl::Url.new(@budurl, data)
|
45
|
+
|
46
|
+
url.link.should == SHORT_URL
|
47
|
+
url.long_url.should == LONG_URL
|
48
|
+
url.hash.should == BudurlMock.hash_from_short_url(SHORT_URL)
|
49
|
+
end
|
50
|
+
|
51
|
+
describe '#clicks' do
|
52
|
+
it 'returns the click count for a short URL' do
|
53
|
+
create_short_url(LONG_URL, SHORT_URL, :count => 10, :dates => {'2012-01-01' => 10})
|
54
|
+
|
55
|
+
data = {'success' => '1',
|
56
|
+
'link' => SHORT_URL,
|
57
|
+
'long_url' => LONG_URL,
|
58
|
+
'hash' => BudurlMock.hash_from_short_url(SHORT_URL)}
|
59
|
+
url = Budurl::Url.new(@budurl, data)
|
60
|
+
|
61
|
+
url.clicks.should == 10
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'returns the daily click counts for a URL with daily = true' do
|
65
|
+
create_short_url(LONG_URL, SHORT_URL, :count => 10, :dates => {'2012-01-01' => 10})
|
66
|
+
|
67
|
+
data = {'success' => '1',
|
68
|
+
'link' => SHORT_URL,
|
69
|
+
'long_url' => LONG_URL,
|
70
|
+
'hash' => BudurlMock.hash_from_short_url(SHORT_URL)}
|
71
|
+
url = Budurl::Url.new(@budurl, data)
|
72
|
+
|
73
|
+
url.clicks(true).should == {'2012-01-01' => 10}
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'raises Error 0 for a long URL with no short URL associated' do
|
77
|
+
data = {'success' => '1',
|
78
|
+
'link' => SHORT_URL,
|
79
|
+
'long_url' => LONG_URL,
|
80
|
+
'hash' => BudurlMock.hash_from_short_url(SHORT_URL)}
|
81
|
+
url = Budurl::Url.new(@budurl)
|
82
|
+
|
83
|
+
lambda { url.clicks }.should raise_error(Budurl::Error, /0/)
|
84
|
+
lambda { url.clicks(true) }.should raise_error(Budurl::Error, /0/)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
metadata
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: budurl
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Anuj Das
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2012-04-25 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: httparty
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 3
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
version: "0"
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: ruby-debug
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
none: false
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
hash: 3
|
43
|
+
segments:
|
44
|
+
- 0
|
45
|
+
version: "0"
|
46
|
+
type: :development
|
47
|
+
version_requirements: *id002
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: rspec
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
hash: 3
|
57
|
+
segments:
|
58
|
+
- 0
|
59
|
+
version: "0"
|
60
|
+
type: :development
|
61
|
+
version_requirements: *id003
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: mimic
|
64
|
+
prerelease: false
|
65
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
hash: 3
|
71
|
+
segments:
|
72
|
+
- 0
|
73
|
+
version: "0"
|
74
|
+
type: :development
|
75
|
+
version_requirements: *id004
|
76
|
+
- !ruby/object:Gem::Dependency
|
77
|
+
name: json
|
78
|
+
prerelease: false
|
79
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
80
|
+
none: false
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
hash: 3
|
85
|
+
segments:
|
86
|
+
- 0
|
87
|
+
version: "0"
|
88
|
+
type: :development
|
89
|
+
version_requirements: *id005
|
90
|
+
description: Supported operations include shrinking, expanding, and counting clicks.
|
91
|
+
email:
|
92
|
+
- anuj.das@mylookout.com
|
93
|
+
executables:
|
94
|
+
- expand
|
95
|
+
- shorten
|
96
|
+
- stats
|
97
|
+
extensions: []
|
98
|
+
|
99
|
+
extra_rdoc_files: []
|
100
|
+
|
101
|
+
files:
|
102
|
+
- .gitignore
|
103
|
+
- Gemfile
|
104
|
+
- README.md
|
105
|
+
- Rakefile
|
106
|
+
- bin/expand
|
107
|
+
- bin/shorten
|
108
|
+
- bin/stats
|
109
|
+
- budurl.gemspec
|
110
|
+
- lib/budurl.rb
|
111
|
+
- lib/budurl/client.rb
|
112
|
+
- lib/budurl/url.rb
|
113
|
+
- lib/budurl/version.rb
|
114
|
+
- test/helpers/budurl_mock.rb
|
115
|
+
- test/unit/client_spec.rb
|
116
|
+
- test/unit/url_spec.rb
|
117
|
+
homepage: https://github.com/lookout/budurl-gem
|
118
|
+
licenses: []
|
119
|
+
|
120
|
+
post_install_message:
|
121
|
+
rdoc_options: []
|
122
|
+
|
123
|
+
require_paths:
|
124
|
+
- lib
|
125
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
126
|
+
none: false
|
127
|
+
requirements:
|
128
|
+
- - ">="
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
hash: 3
|
131
|
+
segments:
|
132
|
+
- 0
|
133
|
+
version: "0"
|
134
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
135
|
+
none: false
|
136
|
+
requirements:
|
137
|
+
- - ">="
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
hash: 3
|
140
|
+
segments:
|
141
|
+
- 0
|
142
|
+
version: "0"
|
143
|
+
requirements: []
|
144
|
+
|
145
|
+
rubyforge_project:
|
146
|
+
rubygems_version: 1.8.23
|
147
|
+
signing_key:
|
148
|
+
specification_version: 3
|
149
|
+
summary: A gem for interfacing with the BudURL.Pro url shortener API
|
150
|
+
test_files:
|
151
|
+
- test/helpers/budurl_mock.rb
|
152
|
+
- test/unit/client_spec.rb
|
153
|
+
- test/unit/url_spec.rb
|