madcowley-jambase4r 1.1.3

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -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