Class: FestivalsLab

Inherits:
Object
  • Object
show all
Defined in:
lib/festivals_lab.rb,
lib/festivals_lab/version.rb

Constant Summary collapse

SCHEME =
"http".freeze
HOST =
"api.edinburghfestivalcity.com".freeze
Error =
Class.new(StandardError)
ArgumentError =
Class.new(::ArgumentError)
ApiError =
Class.new(StandardError) do
  attr_reader :response

  def initialize(response)
    @response = response
  end
end
VERSION =
"0.0.4".freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(access_key, secret_token) ⇒ FestivalsLab

Returns a new instance of FestivalsLab.


11
12
13
14
# File 'lib/festivals_lab.rb', line 11

def initialize(access_key, secret_token)
  @access_key   = access_key
  @secret_token = secret_token
end

Instance Attribute Details

#access_keyObject

Returns the value of attribute access_key


6
7
8
# File 'lib/festivals_lab.rb', line 6

def access_key
  @access_key
end

#secret_tokenObject

Returns the value of attribute secret_token


6
7
8
# File 'lib/festivals_lab.rb', line 6

def secret_token
  @secret_token
end

Class Method Details

.request(access_key, secret_token, endpoint, params = {}) ⇒ Object

Makes a signed API request to the given endpoint

Requests the data in JSON format and parses the response as JSON


58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/festivals_lab.rb', line 58

def request(access_key, secret_token, endpoint, params = {})
  uri = FestivalsLab.signed_uri access_key, secret_token, endpoint, params
  Net::HTTP.start(uri.host, uri.port) do |http|
    request = Net::HTTP::Get.new uri.request_uri
    request["Accept"] = "application/json"
    response = http.request request
    if Net::HTTPSuccess === response
      JSON.parse(response.body)
    else
      raise ApiError, response
    end
  end
end

.signature(secret_token, url) ⇒ Object

Returns the correct API signature for the given URL and secret token


95
96
97
# File 'lib/festivals_lab.rb', line 95

def signature(secret_token, url)
  OpenSSL::HMAC.hexdigest "sha1", secret_token, url
end

.signed_uri(access_key, secret_token, endpoint, params = {}) ⇒ Object

Returns a URI containing the correct signature for the given endpoint and query string parameters

Raises:


74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/festivals_lab.rb', line 74

def signed_uri(access_key, secret_token, endpoint, params = {})
  params = params.dup
  raise Error, "Missing API access key" unless access_key
  raise Error, "Missing API secret token" unless secret_token
  # Start with a generic URI representing just the path
  # This is convenient because the URI represents the string which gets signed
  uri = URI(endpoint)

  params[:key] = access_key
  uri.query = URI.encode_www_form(params)

  params[:signature] = FestivalsLab.signature secret_token, uri.to_s
  uri.query = URI.encode_www_form(params)

  uri.scheme = SCHEME
  uri.host   = HOST
  # Now the URI has a scheme we can convert it to an actual URI::HTTP
  URI.parse(uri.to_s)
end

Instance Method Details

#event(uuid) ⇒ Object

Returns the known data for an event based on the event's UUID

The only way to obtain the UUID for an event is to extract it from the `url` property returned by the `events` endpoint


50
51
52
# File 'lib/festivals_lab.rb', line 50

def event(uuid)
  FestivalsLab.request access_key, secret_token, "/event/#{uuid}"
end

#events(params = {}) ⇒ Object

Searches the API for events matching the given `params`

See the API documentation at api.festivalslab.com/documentation#Querying%20the%20API for valid parameters

Raises:


21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/festivals_lab.rb', line 21

def events(params = {})
  params = params.dup

  # Exact field options
  valid_options = %i[festival genre country code year]
  # Fulltext search options
  valid_options += %i[title description artist]
  # Event date options
  valid_options += %i[date_from date_to]
  # Venue options
  valid_options += %i[venue_name venue_code post_code distance lat lng]
  # Price options
  valid_options += %i[price_from price_to]
  # Update options
  valid_options += [:modified_from]
  # Pagination options
  valid_options += %i[size from]

  invalid_keys = params.reject { |k, _v| valid_options.include? k }.keys

  raise ArgumentError, "Unexpected events parameter: #{invalid_keys.join ', '}" if invalid_keys.any?

  FestivalsLab.request access_key, secret_token, "/events", params
end