festivals_lab 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ /pkg/
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,16 @@
1
+ # Contributing #
2
+
3
+ Thanks for reading this! Contributions are very welcome via Github pull request, but first bear in mind a couple of general guidelines that I'm starting out with:
4
+
5
+ * The gem is designed to lightly wrap the Festivals Lab API, and not be too smart about processing the input or output. The API is currently in beta and behaviour is subject to change
6
+
7
+ * Create separate pull requests for each feature, and try not to include changes that aren't relevant to the request (for example, `.gitignore`)
8
+
9
+ ## Getting started ##
10
+
11
+ To start hacking at the code, it should be as simple as checking out the code and running the tests
12
+
13
+ > git clone https://github.com/gareth/festivals_lab.git
14
+ > cd festivals_lab
15
+ > bundle
16
+ > bundle exec rake
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- festivals_lab (0.0.1)
4
+ festivals_lab (0.0.2)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ (The MIT License)
2
+
3
+ Copyright (c) 2013 Gareth Adams
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ 'Software'), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -0,0 +1,63 @@
1
+ # Festivals Lab API #
2
+
3
+ An unofficial library to access festival data from the Edinburgh Festivals Innovation Lab API
4
+
5
+ ## Description ##
6
+
7
+ Festivals Lab is an open data initiative which provides free access to the events of the 12 annual Edinburgh festivals.
8
+
9
+ The `festivals_lab` gem wraps the API and ties it with a Ruby bow
10
+
11
+ ## Compatibility ##
12
+
13
+ * As an alpha, `festivals_lab` is only developed and tested against Ruby 1.9.3 (other rubies should work, but run the tests first).
14
+ * There are no external dependencies for use other than the Ruby standard library.
15
+
16
+ ## Installation ##
17
+
18
+ Install festivals_lab like any other ruby gem:
19
+
20
+ > gem install festivals_lab
21
+
22
+ Or, to use it in a project with Bundler, add this to your Gemfile:
23
+
24
+ gem 'festivals_lab'
25
+
26
+ …and then run the bundle install command from your shell:
27
+
28
+ > bundle
29
+
30
+ ## Usage ##
31
+
32
+ To use the FestivalsLab API you will need an API key, which can be obtained from the [Festivals Lab website][gettingstarted].
33
+
34
+ The parameters for library method calls match the [official documentation][querying], with the following considerations:
35
+
36
+ * The `key` and `signature` parameters are automatically added for you based on your authentication details, so there is no need to supply those to each API call.
37
+ * All parameters should be passed as `String` or `Numeric` (e.g. `Integer` or `Float`), specifically `Date`s aren't converted into the API's expected format yet
38
+ * The library exclusively requests JSON responses from the API, and the `pretty` parameter is invalid.
39
+
40
+ [gettingstarted]: http://api.festivalslab.com/documentation#gettingstarted
41
+ [querying]: http://api.festivalslab.com/documentation#Querying the API
42
+
43
+ ### Sample usage ###
44
+
45
+ api = FestivalsLab.new("xxAPIAccessKeyxx", "xxAPISecretKeyxxxxAPISecretKeyxx")
46
+
47
+ api.events # The first page of events (using the API's default of 25 per page)
48
+
49
+ api.events(festival: 'book', size: 50, from: 100)
50
+
51
+ api.events(festival: 'fringe', post_code: 'EH1', price_to: 5)
52
+
53
+ The library returns the data as returned from the API, run through a JSON parser
54
+
55
+ ### License ###
56
+
57
+ This software is open source and is licensed under the MIT license.
58
+
59
+ See the LICENSE file for more details
60
+
61
+ ### Contributing ###
62
+
63
+ See the CONTRIBUTING file
@@ -1,3 +1,3 @@
1
1
  class FestivalsLab
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
data/lib/festivals_lab.rb CHANGED
@@ -4,14 +4,14 @@ require 'openssl' # Provides HMAC-SHA1
4
4
 
5
5
  class FestivalsLab
6
6
 
7
- attr_accessor :access_token, :access_key
7
+ attr_accessor :access_key, :secret_token
8
8
 
9
9
  SCHEME = "http"
10
10
  HOST = "api.festivalslab.com"
11
11
 
12
- def initialize access_token, access_key
13
- @access_token = access_token
12
+ def initialize access_key, secret_token
14
13
  @access_key = access_key
14
+ @secret_token = secret_token
15
15
  end
16
16
 
17
17
  def events params = {}
@@ -36,47 +36,54 @@ class FestivalsLab
36
36
 
37
37
  raise ArgumentError, "Unexpected events parameter: #{invalid_keys.join ", "}" if invalid_keys.any?
38
38
 
39
- request '/events', params
39
+ FestivalsLab.request access_key, secret_token, '/events', params
40
40
  end
41
41
 
42
- def request endpoint, params = {}
43
- uri = signed_uri endpoint, params
44
- Net::HTTP.start(uri.host, uri.port) do |http|
45
- request = Net::HTTP::Get.new uri.request_uri
46
- request['Accept'] = 'application/json'
47
- response = http.request request
48
- if Net::HTTPSuccess === response
49
- JSON.parse(response.body)
50
- else
51
- raise ApiError.new(response)
42
+ def event uuid
43
+ FestivalsLab.request access_key, secret_token, "/event/#{uuid}"
44
+ end
45
+
46
+ class << self
47
+ def request access_key, secret_token, endpoint, params = {}
48
+ uri = FestivalsLab.signed_uri access_key, secret_token, endpoint, params
49
+ Net::HTTP.start(uri.host, uri.port) do |http|
50
+ request = Net::HTTP::Get.new uri.request_uri
51
+ request['Accept'] = 'application/json'
52
+ response = http.request request
53
+ if Net::HTTPSuccess === response
54
+ JSON.parse(response.body)
55
+ else
56
+ raise ApiError.new(response)
57
+ end
52
58
  end
53
59
  end
54
- end
55
60
 
56
- def signed_uri endpoint, params = {}
57
- params = params.dup
58
- raise Error, "Missing API access key" unless access_key
59
- raise Error, "Missing API access token" unless access_token
60
- # Start with a generic URI representing just the path
61
- # This is convenient because the URI represents the string which gets signed
62
- uri = URI(endpoint)
63
-
64
- params[:key] = access_token
65
- uri.query = URI.encode_www_form(params)
66
-
67
- params[:signature] = self.signature uri.to_s
68
- uri.query = URI.encode_www_form(params)
69
-
70
- uri.scheme = SCHEME
71
- uri.host = HOST
72
- # Now the URI has a scheme we can convert it to an actual URI::HTTP
73
- URI.parse(uri.to_s)
74
- end
61
+ def signed_uri access_key, secret_token, endpoint, params = {}
62
+ params = params.dup
63
+ raise Error, "Missing API access key" unless access_key
64
+ raise Error, "Missing API secret token" unless secret_token
65
+ # Start with a generic URI representing just the path
66
+ # This is convenient because the URI represents the string which gets signed
67
+ uri = URI(endpoint)
68
+
69
+ params[:key] = access_key
70
+ uri.query = URI.encode_www_form(params)
75
71
 
76
- def signature url
77
- OpenSSL::HMAC.hexdigest 'sha1', access_key, url
72
+ params[:signature] = FestivalsLab.signature secret_token, uri.to_s
73
+ uri.query = URI.encode_www_form(params)
74
+
75
+ uri.scheme = SCHEME
76
+ uri.host = HOST
77
+ # Now the URI has a scheme we can convert it to an actual URI::HTTP
78
+ URI.parse(uri.to_s)
79
+ end
80
+
81
+ def signature secret_token, url
82
+ OpenSSL::HMAC.hexdigest 'sha1', secret_token, url
83
+ end
78
84
  end
79
85
 
86
+
80
87
  Error = Class.new(StandardError)
81
88
  ArgumentError = Class.new(::ArgumentError)
82
89
  ApiError = Class.new(StandardError) do
@@ -21,13 +21,13 @@ describe FestivalsLab do
21
21
  it "sets an access token" do
22
22
  api = FestivalsLab.new "123", nil
23
23
 
24
- api.access_token.must_equal "123"
24
+ api.access_key.must_equal "123"
25
25
  end
26
26
 
27
27
  it "sets an access key" do
28
28
  api = FestivalsLab.new nil, "456"
29
29
 
30
- api.access_key.must_equal "456"
30
+ api.secret_token.must_equal "456"
31
31
  end
32
32
  end
33
33
 
@@ -84,7 +84,27 @@ describe FestivalsLab do
84
84
  end
85
85
  end
86
86
 
87
- describe "#request" do
87
+ describe "#event" do
88
+ it "requests the event from the API" do
89
+ stub = stub_http_request(:get, %r{//api\.festivalslab\.com/event/00000000000000000000000000000000deadbeef})
90
+ .to_return(@successful_response)
91
+
92
+ response = @api.event '00000000000000000000000000000000deadbeef'
93
+
94
+ assert_requested(stub)
95
+ end
96
+
97
+ it "returns the parsed event" do
98
+ stub = stub_http_request(:get, %r{//api\.festivalslab\.com/event/00000000000000000000000000000000deadbeef})
99
+ .to_return(@successful_response)
100
+
101
+ response = @api.event '00000000000000000000000000000000deadbeef'
102
+
103
+ assert_equal [{}], response
104
+ end
105
+ end
106
+
107
+ describe "request" do
88
108
  before do
89
109
  @uri = "http://api.festivalslab.com/events?key=123&signature=742969faae86a4ba4223c7d93d05ead4b1397c23"
90
110
  end
@@ -92,7 +112,7 @@ describe FestivalsLab do
92
112
  it "makes a request to the signed endpoint URI" do
93
113
  stub_request(:get, @uri).to_return(@successful_response)
94
114
 
95
- @api.request '/events'
115
+ FestivalsLab.request @api.access_key, @api.secret_token, '/events'
96
116
 
97
117
  assert_requested(:get, @uri)
98
118
  end
@@ -101,7 +121,7 @@ describe FestivalsLab do
101
121
  stub = stub_http_request(:get, @uri)
102
122
  .to_return(@successful_response)
103
123
 
104
- response = @api.request '/events'
124
+ response = FestivalsLab.request @api.access_key, @api.secret_token, '/events'
105
125
 
106
126
  assert_equal [{}], response
107
127
  end
@@ -110,32 +130,32 @@ describe FestivalsLab do
110
130
  stub = stub_http_request(:get, @uri)
111
131
  .to_return(@failed_response)
112
132
 
113
- lambda { @api.request '/events' }.must_raise(FestivalsLab::ApiError)
133
+ lambda { FestivalsLab.request @api.access_key, @api.secret_token, '/events' }.must_raise(FestivalsLab::ApiError)
114
134
  end
115
135
  end
116
136
 
117
- describe "#signed_uri" do
137
+ describe "signed_uri" do
118
138
  it "requires an access key to be set" do
119
- @api.access_key = nil
120
- lambda { @api.signed_uri('/events') }.must_raise(FestivalsLab::Error, "Missing API access key")
139
+ @api.secret_token = nil
140
+ lambda { FestivalsLab.signed_uri(@api.access_key, @api.secret_token, '/events') }.must_raise(FestivalsLab::Error, "Missing API access key")
121
141
  end
122
142
 
123
143
  it "requires an access token to be set" do
124
- @api.access_token = nil
125
- lambda { @api.signed_uri('/events') }.must_raise(FestivalsLab::Error, "Missing API access token")
144
+ @api.access_key = nil
145
+ lambda { FestivalsLab.signed_uri(@api.access_key, @api.secret_token, '/events') }.must_raise(FestivalsLab::Error, "Missing API access token")
126
146
  end
127
147
 
128
148
  it "appends the correct signature to the request URI" do
129
- uri = @api.signed_uri('/events', {:key => 123})
149
+ uri = FestivalsLab.signed_uri(@api.access_key, @api.secret_token, '/events', {:key => 123})
130
150
  uri.must_be_kind_of(URI)
131
151
  uri.to_s.must_equal 'http://api.festivalslab.com/events?key=123&signature=742969faae86a4ba4223c7d93d05ead4b1397c23'
132
152
  end
133
153
  end
134
154
 
135
- describe "#signature" do
155
+ describe "signature" do
136
156
  it "calculates the HMAC-SHA1 signature based on the access key" do
137
157
  ## Because `OpenSSL#HMAC.hexdigest('sha1', '456', '/events?key=123')` # => '742969faae86a4ba4223c7d93d05ead4b1397c23'
138
- @api.signature('/events?key=123').must_equal '742969faae86a4ba4223c7d93d05ead4b1397c23'
158
+ FestivalsLab.signature(@api.secret_token, '/events?key=123').must_equal '742969faae86a4ba4223c7d93d05ead4b1397c23'
139
159
  end
140
160
  end
141
161
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: festivals_lab
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -66,9 +66,12 @@ executables: []
66
66
  extensions: []
67
67
  extra_rdoc_files: []
68
68
  files:
69
+ - .gitignore
69
70
  - .rvmrc
71
+ - CONTRIBUTING.md
70
72
  - Gemfile
71
73
  - Gemfile.lock
74
+ - LICENSE
72
75
  - README.md
73
76
  - Rakefile
74
77
  - festivals_lab.gemspec
@@ -90,7 +93,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
90
93
  version: '0'
91
94
  segments:
92
95
  - 0
93
- hash: -2264928236337400198
96
+ hash: 4234472854470534461
94
97
  required_rubygems_version: !ruby/object:Gem::Requirement
95
98
  none: false
96
99
  requirements:
@@ -99,7 +102,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
99
102
  version: '0'
100
103
  segments:
101
104
  - 0
102
- hash: -2264928236337400198
105
+ hash: 4234472854470534461
103
106
  requirements: []
104
107
  rubyforge_project:
105
108
  rubygems_version: 1.8.24