madcowley-jambase4r 1.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README +124 -0
- data/jambase4r.gemspec +22 -0
- data/lib/api.rb +111 -0
- data/lib/extensions.rb +44 -0
- data/lib/http_gateway.rb +43 -0
- data/lib/jambase4r.rb +51 -0
- data/lib/jambase4r_view_helper.rb +24 -0
- data/lib/models/artist.rb +20 -0
- data/lib/models/event.rb +33 -0
- data/lib/models/model.rb +31 -0
- data/lib/models/venue.rb +25 -0
- data/lib/utility.rb +13 -0
- data/spec/lib/api_spec.rb +167 -0
- data/spec/lib/http_gateway_spec.rb +38 -0
- data/spec/lib/jambase4r_spec.rb +51 -0
- data/spec/lib/models/artist_spec.rb +36 -0
- data/spec/lib/models/event_spec.rb +102 -0
- data/spec/lib/models/model_spec.rb +30 -0
- data/spec/lib/models/venue_spec.rb +73 -0
- data/spec/spec_helper.rb +473 -0
- metadata +96 -0
data/README
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
JamBase4R
|
2
|
+
=============
|
3
|
+
|
4
|
+
JamBase4R is a framework agnostic Ruby wrapper around the JamBase live music search API.
|
5
|
+
(http://developer.jambase.com/docs)
|
6
|
+
|
7
|
+
This gem can be used to create mashups where your users might want to search for live music. This gem is a
|
8
|
+
replacement for a Ruby on Rails plugin that I wrote a while back called JamBase4Rails. Since Rails is no longer
|
9
|
+
promoting the use of traditional plugins, but rather gems, I thought it was time to do a re-write.
|
10
|
+
|
11
|
+
**Note: JamBase requires that any site making use of it's API provide attribution.
|
12
|
+
See http://developer.jambase.com/docs for more information. This gem provides
|
13
|
+
helpers to make adding attribution to your site easy.
|
14
|
+
|
15
|
+
This gem adds helper methods to your views (if you are using Rails), but does not alter controllers or
|
16
|
+
models in any way.
|
17
|
+
|
18
|
+
This is a forked version from Matt Payne's original, to include new start/end date parameters allowed in the jambase api.
|
19
|
+
|
20
|
+
Installation
|
21
|
+
============
|
22
|
+
|
23
|
+
1) get and install the gem
|
24
|
+
sudo gem install madcowley-jambase4r
|
25
|
+
- OR -
|
26
|
+
If using Rails:
|
27
|
+
a) Add config.gem 'madcowley-jambase4r', :lib => "jambase4r"
|
28
|
+
to your environment.rb file.
|
29
|
+
b) rake gems:install from your project root
|
30
|
+
|
31
|
+
Configuration
|
32
|
+
=============
|
33
|
+
|
34
|
+
Using the JamBase API requires that you register for an API key. Get one here:
|
35
|
+
http://developer.jambase.com/member/register
|
36
|
+
|
37
|
+
JamBase4R is configured via the configure method. The configure method takes a block that is
|
38
|
+
passed a settings object. 2 properties can be set: 1) api_key (required) 2) logger (optional)
|
39
|
+
|
40
|
+
FOR RAILS
|
41
|
+
=========
|
42
|
+
In an initializer, add the following configuration:
|
43
|
+
|
44
|
+
#app_specific_initializers.rb
|
45
|
+
|
46
|
+
JamBase4R.configure do |config|
|
47
|
+
config.api_key = "XXXXXXXXXXXXX"
|
48
|
+
config.logger = RAILS_DEFAULT_LOGGER - This is optional if you want to enable logging. You can pass an instance of
|
49
|
+
any class that conforms to the same interface as RAILS_DEFAULT_LOGGER (Specifically, it must respond to #info(msg) and #error(msg))
|
50
|
+
end
|
51
|
+
|
52
|
+
FOR SINATRA
|
53
|
+
===========
|
54
|
+
|
55
|
+
I would typically configure JamBase4R with a Sinatra configure block.
|
56
|
+
|
57
|
+
configure do
|
58
|
+
JamBase4R.configure do |config|
|
59
|
+
config.api_key = "XXXXXXXXXXXXX"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
FOR OTHERS
|
64
|
+
==========
|
65
|
+
|
66
|
+
Check the documentation of the framework you are using. All should allow for this type of configuration.
|
67
|
+
|
68
|
+
ATTRIBUTION
|
69
|
+
===========
|
70
|
+
JamBase requires that you indicate where your data comes from (attribution). To make this easy, there is a JamBase4R::ViewHelper module that gets automatically included into ActionView::Base if using Rails and into Sinatra's helpers if using Sinatra.
|
71
|
+
|
72
|
+
There are a couple of methods:
|
73
|
+
1) jambase_text_attribution
|
74
|
+
2) jambase_image_attribution
|
75
|
+
3) jambase_flavicon
|
76
|
+
|
77
|
+
Example
|
78
|
+
=======
|
79
|
+
|
80
|
+
To make use of JamBase4R just use the JamBase4R::API object.
|
81
|
+
|
82
|
+
Available methods (all are class methods):
|
83
|
+
|
84
|
+
All methods return an instance of an Array, which contains zero or more Event objects
|
85
|
+
|
86
|
+
1) JamBase4R::API.search(options)
|
87
|
+
2) JamBase4R::API.search_by_artist(artist_name, additional_options={})
|
88
|
+
3) JamBase4R::API.search_by_zipcode(zipcode, additional_options={})
|
89
|
+
4) JamBase4R::API.search_by_user(user, additional_options={})
|
90
|
+
|
91
|
+
Possible options:
|
92
|
+
|
93
|
+
:band (or :artist (an alias for :band)) => The name of the band to search for.
|
94
|
+
:zip => The zipcode to search within
|
95
|
+
:radius => The distance from the zipcode to include in the search
|
96
|
+
:user => The registered user - this limits the results to those within the user's favorite artists
|
97
|
+
:startdate => return results on or after this date
|
98
|
+
:enddate => return results before this date
|
99
|
+
|
100
|
+
ie: JamBase4R::API.search(:band => "A Band", :zip => "90210", :radius => 20)
|
101
|
+
JamBase4R::API.search_by_artist("A Band", {:zip => "90210"})
|
102
|
+
JamBase4R::API.search_by_zipcode("90210")
|
103
|
+
JamBase4R::API.search_by_user("Matt")
|
104
|
+
|
105
|
+
The general schema of the results is:
|
106
|
+
|
107
|
+
- events
|
108
|
+
- event
|
109
|
+
- event_id (String)
|
110
|
+
- event_date (String)
|
111
|
+
- event_url (String)
|
112
|
+
- ticket_url (String)
|
113
|
+
- venue (Venue)
|
114
|
+
- venue_id (String)
|
115
|
+
- venue_name (String)
|
116
|
+
- venue_city (String)
|
117
|
+
- venue_state (String)
|
118
|
+
- venue_zip (String)
|
119
|
+
- artists (Artists)
|
120
|
+
- Artist(s) (Artist)
|
121
|
+
- artist_id
|
122
|
+
- artist_name
|
123
|
+
|
124
|
+
Copyright (c) 2009 [Matt Payne], released under the MIT license
|
data/jambase4r.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
#The GemSpec to build the gem
|
2
|
+
Gem::Specification.new do |s|
|
3
|
+
s.name = 'madcowley-jambase4r'
|
4
|
+
s.version = '1.1.3'
|
5
|
+
s.date = "2010-06-30"
|
6
|
+
s.summary = "Ruby JamBase API library."
|
7
|
+
s.description = %{A Ruby library use to access the JamBase API. Forked from Matt Payne's original.}
|
8
|
+
s.has_rdoc = false
|
9
|
+
s.authors = ["Matt Payne", "Matt Cowley"]
|
10
|
+
s.email = ["matt@mattpayne.ca", "madcowley@gmail.com"]
|
11
|
+
s.homepage = "http://github.com/madcowley/jambase4r"
|
12
|
+
s.files = [
|
13
|
+
'README', 'jambase4r.gemspec', 'lib/jambase4r.rb', 'lib/utility.rb', 'lib/api.rb',
|
14
|
+
'lib/extensions.rb', 'lib/http_gateway.rb', 'lib/jambase4r_view_helper.rb', 'lib/models/model.rb',
|
15
|
+
'lib/models/artist.rb', 'lib/models/venue.rb', 'lib/models/event.rb'
|
16
|
+
]
|
17
|
+
s.test_files = [
|
18
|
+
'spec/spec_helper.rb', 'spec/lib/api_spec.rb', 'spec/lib/http_gateway_spec.rb',
|
19
|
+
'spec/lib/jambase4r_spec.rb', 'spec/lib/models/artist_spec.rb',
|
20
|
+
'spec/lib/models/event_spec.rb', 'spec/lib/models/venue_spec.rb', "spec/lib/models/model_spec.rb"
|
21
|
+
]
|
22
|
+
end
|
data/lib/api.rb
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
require "rexml/document"
|
2
|
+
|
3
|
+
module JamBase4R
|
4
|
+
class API
|
5
|
+
class << self
|
6
|
+
include Utility
|
7
|
+
|
8
|
+
API_URL = "http://api.jambase.com/search".freeze
|
9
|
+
JAMBASE_PARAMETERS = [:zip, :radius, :band, :user, :startdate, :enddate].freeze
|
10
|
+
PARAMETER_ALIAS_MAP = {:artist => :band}.freeze
|
11
|
+
|
12
|
+
#Search Options:
|
13
|
+
#:artist = The name of an artist
|
14
|
+
#:band = alias for artist
|
15
|
+
#:zip = The zipcode to search
|
16
|
+
#:radius = The distance around the zipcode to search
|
17
|
+
#These can be combined, although I doubt that :artist combined with :radius
|
18
|
+
#would do anything useful ;)
|
19
|
+
def search(search_options={})
|
20
|
+
result = jambase_search(search_options)
|
21
|
+
return convert(result.body) unless result.blank?
|
22
|
+
end
|
23
|
+
|
24
|
+
#Additional Filters - As above, but without :artist/band
|
25
|
+
def search_by_artist(artist_name, additional_filters={})
|
26
|
+
additional_filters[:artist] = artist_name
|
27
|
+
return search(additional_filters)
|
28
|
+
end
|
29
|
+
|
30
|
+
#Additional Filters - As above, but without :zip
|
31
|
+
def search_by_zipcode(zipcode, additional_filters={})
|
32
|
+
additional_filters[:zip] = zipcode
|
33
|
+
return search(additional_filters)
|
34
|
+
end
|
35
|
+
|
36
|
+
#Additional filters - As above, but without :user
|
37
|
+
def search_by_user(user, additional_filters={})
|
38
|
+
additional_filters[:user] = user
|
39
|
+
return search(additional_filters)
|
40
|
+
end
|
41
|
+
|
42
|
+
protected
|
43
|
+
|
44
|
+
def jambase_search(search_args)
|
45
|
+
check_api_key
|
46
|
+
return if search_args.blank?
|
47
|
+
search_args = search_args.symbolize_keys
|
48
|
+
replace_aliased_keys!(search_args)
|
49
|
+
remove_unnecessary_params!(search_args)
|
50
|
+
return if search_args.blank?
|
51
|
+
query = create_query_string(search_args)
|
52
|
+
log_info("Calling JamBase with the requested search: #{query}")
|
53
|
+
return jambase_gateway.get(query)
|
54
|
+
end
|
55
|
+
|
56
|
+
def check_api_key
|
57
|
+
if JamBase4R.api_key.blank?
|
58
|
+
log_error("No API key has been set for JamBase. Please set it before attempting to use the service.")
|
59
|
+
raise ArgumentError.new("No JamBase API key configured. Please configure JamBase4R before using.")
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def replace_aliased_keys!(options)
|
64
|
+
PARAMETER_ALIAS_MAP.each do |alias_param, real_param|
|
65
|
+
if options.key?(alias_param)
|
66
|
+
check_for_alias_and_real_param!(options, alias_param, real_param)
|
67
|
+
value = options[alias_param]
|
68
|
+
options[real_param] = value
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def check_for_alias_and_real_param!(options, alias_param, real_param)
|
74
|
+
unless options[real_param].blank?
|
75
|
+
log_error("Cannot have both #{alias_param} and #{real_param} in search.")
|
76
|
+
raise ArgumentError.new("Cannot have both #{alias_param} and #{real_param}.")
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def remove_unnecessary_params!(options)
|
81
|
+
options.reject! do |key, value|
|
82
|
+
!JAMBASE_PARAMETERS.include?(key) ||
|
83
|
+
value.blank?
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def create_query_string(search_args)
|
88
|
+
"#{API_URL}?#{search_args.to_param}&apikey=#{JamBase4R.api_key}"
|
89
|
+
end
|
90
|
+
|
91
|
+
def jambase_gateway
|
92
|
+
@@gateway ||= JamBase4R::HttpGateway.new
|
93
|
+
end
|
94
|
+
|
95
|
+
def convert(xml)
|
96
|
+
begin
|
97
|
+
results = []
|
98
|
+
return results if xml.blank?
|
99
|
+
doc = REXML::Document.new(xml)
|
100
|
+
doc.elements.each("//event") do |event|
|
101
|
+
results << Event.new(event)
|
102
|
+
end
|
103
|
+
rescue Exception => e
|
104
|
+
log_error(e.message)
|
105
|
+
end
|
106
|
+
results
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
data/lib/extensions.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'rubygems' unless defined? RubyGems
|
2
|
+
require 'uri' unless defined? URI
|
3
|
+
|
4
|
+
#Hack URI::HTTP to include a method that gets us both the path and the querystring
|
5
|
+
#since path_query is private
|
6
|
+
module URI
|
7
|
+
class HTTP < Generic
|
8
|
+
def path_with_querystring
|
9
|
+
path_query
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
unless defined?(ActiveSupport)
|
15
|
+
class Object
|
16
|
+
def blank?
|
17
|
+
respond_to?(:empty?) ? empty? : !self
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_param
|
21
|
+
to_s
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_query(key)
|
25
|
+
require 'cgi' unless defined?(CGI) && defined?(CGI::escape)
|
26
|
+
"#{CGI.escape(key.to_s)}=#{CGI.escape(to_param.to_s)}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class Hash
|
31
|
+
def symbolize_keys
|
32
|
+
inject({}) do |options, (key, value)|
|
33
|
+
options[(key.to_sym rescue key) || key] = value
|
34
|
+
options
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_param(namespace=nil)
|
39
|
+
collect do |key, value|
|
40
|
+
value.to_query(namespace ? "#{namespace}[#{key}]" : key)
|
41
|
+
end.sort * '&'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/http_gateway.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
module JamBase4R
|
4
|
+
|
5
|
+
class JamBaseError < StandardError
|
6
|
+
|
7
|
+
attr_reader :message, :response_code
|
8
|
+
|
9
|
+
def initialize(message, response_code=nil)
|
10
|
+
@message = message
|
11
|
+
@response_code = response_code
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
class HttpGateway
|
17
|
+
include Utility
|
18
|
+
|
19
|
+
def get(url)
|
20
|
+
log_info("#{self.class.name} - Performing GET with URL: #{url}.")
|
21
|
+
url = URI.parse(url)
|
22
|
+
request = Net::HTTP::Get.new(url.path_with_querystring)
|
23
|
+
response = Net::HTTP.start(url.host, url.port) { |http| http.request(request) }
|
24
|
+
handle_response(response)
|
25
|
+
rescue Timeout::Error => e
|
26
|
+
log_error("Connection to JamBase timed out: #{e.message}")
|
27
|
+
raise JamBaseError.new(e.message)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def handle_response(response)
|
33
|
+
case response.code.to_i
|
34
|
+
when 200...400
|
35
|
+
response
|
36
|
+
else
|
37
|
+
log_error("Unexpect response occurred. Code: #{response.code}, Message: #{response.body}")
|
38
|
+
raise(JamBaseError.new(response.body, response.code))
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
data/lib/jambase4r.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
local_path = File.dirname(__FILE__)
|
2
|
+
|
3
|
+
[ 'extensions',
|
4
|
+
'utility',
|
5
|
+
'http_gateway',
|
6
|
+
'jambase4r_view_helper',
|
7
|
+
'models/model',
|
8
|
+
'models/artist',
|
9
|
+
'models/venue',
|
10
|
+
'models/event',
|
11
|
+
'api'].each { |file| require File.join(local_path, file) }
|
12
|
+
|
13
|
+
|
14
|
+
module JamBase4R
|
15
|
+
extend Utility
|
16
|
+
|
17
|
+
@@api_key = nil
|
18
|
+
@@logger = nil
|
19
|
+
|
20
|
+
def self.api_key
|
21
|
+
@@api_key
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.api_key=(key)
|
25
|
+
@@api_key = key
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.logger
|
29
|
+
@@logger
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.logger=(logger)
|
33
|
+
@@logger = logger
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.configure(&block)
|
37
|
+
raise ArgumentError.new("A block is expected.") unless block_given?
|
38
|
+
block.call(self)
|
39
|
+
log_error("You must supply an API key.") if api_key.blank?
|
40
|
+
raise ArgumentError.new("You must supply an api key.") if api_key.blank?
|
41
|
+
if defined? ActionView
|
42
|
+
ActionView::Base.send(:include, JamBase4R::ViewHelper)
|
43
|
+
end
|
44
|
+
if defined? Sinatra
|
45
|
+
helpers do
|
46
|
+
include JamBase4R::ViewHelper
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module JamBase4R
|
2
|
+
|
3
|
+
module ViewHelper
|
4
|
+
|
5
|
+
def jambase_text_attribution
|
6
|
+
%{**Concert information provided by <a href="http://www.jambase.com">JamBase</a>**}
|
7
|
+
end
|
8
|
+
|
9
|
+
def jambase_image_attribution
|
10
|
+
%{<a href="http://www.JamBase.com" target="_top" title="JamBase Concert Search">
|
11
|
+
<img src= "http://images.jambase.com/logos/jambase140x70.gif" alt="Search JamBase Concerts" border="0" />
|
12
|
+
</a>}
|
13
|
+
end
|
14
|
+
|
15
|
+
def jambase_favicon
|
16
|
+
%{<a href="http://www.JamBase.com" target="_top" title="JamBase Concert Search">
|
17
|
+
<img src= "http://www.jambase.com/favicon.ico" alt="Search JamBase Concerts" border="0" />
|
18
|
+
</a>
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module JamBase4R
|
2
|
+
class Artist
|
3
|
+
include Model
|
4
|
+
|
5
|
+
attr_reader :id, :name
|
6
|
+
|
7
|
+
def initialize(element)
|
8
|
+
return if element.blank?
|
9
|
+
build(element)
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def build(element)
|
15
|
+
@id = get_value(element, ARTIST_ID)
|
16
|
+
@name = get_value(element, ARTIST_NAME)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|