europeana 0.1.0
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 +17 -0
- data/Gemfile +4 -0
- data/LICENSE.pdf +0 -0
- data/README.md +57 -0
- data/Rakefile +1 -0
- data/europeana.gemspec +28 -0
- data/lib/europeana/errors.rb +52 -0
- data/lib/europeana/record.rb +105 -0
- data/lib/europeana/search.rb +101 -0
- data/lib/europeana/version.rb +3 -0
- data/lib/europeana.rb +77 -0
- data/spec/europeana/errors_spec.rb +13 -0
- data/spec/europeana/record_spec.rb +132 -0
- data/spec/europeana/search_spec.rb +92 -0
- data/spec/europeana_spec.rb +81 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/support/shared_examples/api_request.rb +56 -0
- data/spec/support/shared_examples/record_request.rb +32 -0
- data/spec/support/shared_examples/search_request.rb +40 -0
- metadata +169 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.pdf
ADDED
Binary file
|
data/README.md
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
# Europeana
|
2
|
+
|
3
|
+
Ruby client library for the search and retrieval of records from the [Europeana
|
4
|
+
REST API](http://labs.europeana.eu/api/introduction/).
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
gem 'europeana'
|
11
|
+
|
12
|
+
And then execute:
|
13
|
+
|
14
|
+
$ bundle
|
15
|
+
|
16
|
+
Or install it yourself as:
|
17
|
+
|
18
|
+
$ gem install europeana
|
19
|
+
|
20
|
+
## Usage
|
21
|
+
|
22
|
+
### Authentication
|
23
|
+
|
24
|
+
Authentication is *required* for all requests to the Europeana API.
|
25
|
+
|
26
|
+
Only Basic Authentication (by API key) is supported.
|
27
|
+
|
28
|
+
Sign up for an API key at: http://labs.europeana.eu/api/registration/
|
29
|
+
|
30
|
+
Configure your application with the API key:
|
31
|
+
|
32
|
+
Europeana.api_key = "xyz"
|
33
|
+
|
34
|
+
### Search
|
35
|
+
|
36
|
+
search = Europeana.search(:query => '"first world war"') # => { "success" => true, "items2 => [ ... ], "totalResults" => 1234, ... }
|
37
|
+
search["items"] # => [ item1, item2, ... ]
|
38
|
+
search["totalResults"] # => 1234
|
39
|
+
|
40
|
+
See http://labs.europeana.eu/api/search/ for details of the data returned in
|
41
|
+
the search response.
|
42
|
+
|
43
|
+
### Record
|
44
|
+
|
45
|
+
record = Europeana.record("abc/1234") # => { "success" => true, "object" => { ... }, ... }
|
46
|
+
record["object"] # => { "title" => "...", "proxies" => [ ... ], "aggregations" => [ ... ]
|
47
|
+
|
48
|
+
See http://labs.europeana.eu/api/record/ for details of the data returned in
|
49
|
+
the record response.
|
50
|
+
|
51
|
+
## Contributing
|
52
|
+
|
53
|
+
1. Fork it
|
54
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
55
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
56
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
57
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/europeana.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'europeana/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "europeana"
|
8
|
+
spec.version = Europeana::VERSION
|
9
|
+
spec.authors = ["Richard Doe"]
|
10
|
+
spec.email = ["richard.doe@rwdit.net"]
|
11
|
+
spec.description = %q{Search and retrieve records from the Europeana REST API}
|
12
|
+
spec.summary = %q{Ruby client library for the Europeana API}
|
13
|
+
spec.homepage = "https://github.com/europeana/europeana-client-ruby"
|
14
|
+
spec.license = "EUPL 1.1"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "activesupport", "~> 3.0"
|
22
|
+
spec.add_dependency "multi_json", "~> 1.0"
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
25
|
+
spec.add_development_dependency "rake"
|
26
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
27
|
+
spec.add_development_dependency "webmock", "~> 1.18.0"
|
28
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Europeana
|
2
|
+
module Errors
|
3
|
+
##
|
4
|
+
# Raised if API requests are attempted without the API key having been set.
|
5
|
+
#
|
6
|
+
class MissingAPIKeyError < StandardError
|
7
|
+
def initialize(msg = nil)
|
8
|
+
msg ||= <<-MSG
|
9
|
+
Missing API key.
|
10
|
+
|
11
|
+
The Europeana API key has not been set.
|
12
|
+
|
13
|
+
Sign up for an API key at: http://labs.europeana.eu/api/registration/
|
14
|
+
|
15
|
+
Set the key with:
|
16
|
+
|
17
|
+
Europeana.api_key = "xyz"
|
18
|
+
MSG
|
19
|
+
super(msg)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
##
|
24
|
+
# Raised if the API response success flag is false, indicating a problem
|
25
|
+
# with the request.
|
26
|
+
#
|
27
|
+
class RequestError < StandardError
|
28
|
+
def initialize(msg = nil)
|
29
|
+
msg ||= <<-MSG
|
30
|
+
Request error.
|
31
|
+
|
32
|
+
There was a problem with your request to the Europeana API.
|
33
|
+
MSG
|
34
|
+
super(msg)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
##
|
39
|
+
# Raised if the API response is not valid JSON.
|
40
|
+
#
|
41
|
+
class ResponseError < StandardError
|
42
|
+
def initialize(msg = nil)
|
43
|
+
msg ||= <<-MSG
|
44
|
+
Response error.
|
45
|
+
|
46
|
+
Unable to parse the response from the Europeana API.
|
47
|
+
MSG
|
48
|
+
super(msg)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end # Europeana::Errors
|
52
|
+
end # Europeana
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require "uri"
|
2
|
+
|
3
|
+
module Europeana
|
4
|
+
##
|
5
|
+
# Interface to the Europeana API Record method
|
6
|
+
#
|
7
|
+
# @see http://labs.europeana.eu/api/record/
|
8
|
+
#
|
9
|
+
class Record
|
10
|
+
# Europeana ID of the record
|
11
|
+
attr_accessor :id
|
12
|
+
|
13
|
+
# Request parameters to send to the API
|
14
|
+
attr_accessor :params
|
15
|
+
|
16
|
+
##
|
17
|
+
# @param [String] id Europeana ID of the record
|
18
|
+
# @param [Hash] params Request parameters
|
19
|
+
#
|
20
|
+
def initialize(id, params = {})
|
21
|
+
self.id = id
|
22
|
+
self.params = params
|
23
|
+
end
|
24
|
+
|
25
|
+
##
|
26
|
+
# Returns query params with API key added
|
27
|
+
#
|
28
|
+
# @return [Hash]
|
29
|
+
#
|
30
|
+
def params_with_authentication
|
31
|
+
raise Europeana::Errors::MissingAPIKeyError unless Europeana.api_key.present?
|
32
|
+
params.merge(:wskey => Europeana.api_key)
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# Sets record ID attribute after validating format.
|
37
|
+
#
|
38
|
+
# @param [String] id Record ID
|
39
|
+
#
|
40
|
+
def id=(id)
|
41
|
+
raise ArgumentError, "Invalid Europeana record ID." unless id.is_a?(String) && id.match(/\A\/[^\/]+\/[^\/]+\B/)
|
42
|
+
@id = id
|
43
|
+
end
|
44
|
+
|
45
|
+
##
|
46
|
+
# Sets request parameters after validating keys
|
47
|
+
#
|
48
|
+
# Valid parameter keys:
|
49
|
+
# * :callback
|
50
|
+
#
|
51
|
+
# For explanations of these request parameters, see: http://labs.europeana.eu/api/record/
|
52
|
+
#
|
53
|
+
# @param (see #initialize)
|
54
|
+
# @return [Hash] Request parameters
|
55
|
+
#
|
56
|
+
def params=(params = {})
|
57
|
+
params.assert_valid_keys(:callback)
|
58
|
+
@params = params
|
59
|
+
end
|
60
|
+
|
61
|
+
##
|
62
|
+
# Gets the URI for this Record request with parameters
|
63
|
+
#
|
64
|
+
# @return [URI]
|
65
|
+
#
|
66
|
+
def request_uri
|
67
|
+
uri = URI.parse(Europeana::URL + "/record" + "#{@id}.json")
|
68
|
+
uri.query = params_with_authentication.to_query
|
69
|
+
uri
|
70
|
+
end
|
71
|
+
|
72
|
+
##
|
73
|
+
# Sends a request for this record to the API
|
74
|
+
#
|
75
|
+
# @return [Hash] Record data
|
76
|
+
#
|
77
|
+
def get
|
78
|
+
uri = request_uri
|
79
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
80
|
+
request = Net::HTTP::Get.new(uri.request_uri)
|
81
|
+
retries = Europeana.max_retries
|
82
|
+
|
83
|
+
begin
|
84
|
+
response = http.request(request)
|
85
|
+
rescue Timeout::Error, Errno::ECONNREFUSED, EOFError
|
86
|
+
retries -= 1
|
87
|
+
raise unless retries > 0
|
88
|
+
sleep Europeana.retry_delay
|
89
|
+
retry
|
90
|
+
end
|
91
|
+
|
92
|
+
json = JSON.parse(response.body)
|
93
|
+
raise Errors::RequestError, json['error'] unless json['success']
|
94
|
+
json
|
95
|
+
rescue JSON::ParserError
|
96
|
+
if response.code.to_i == 404
|
97
|
+
# Handle HTML 404 responses on malformed record ID, emulating API's
|
98
|
+
# JSON response.
|
99
|
+
raise Errors::RequestError, "Invalid record identifier: #{@id}"
|
100
|
+
else
|
101
|
+
raise Errors::ResponseError
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
module Europeana
|
2
|
+
##
|
3
|
+
# Interface to Europeana API's Search method
|
4
|
+
#
|
5
|
+
class Search
|
6
|
+
# Query params
|
7
|
+
attr_accessor :params
|
8
|
+
|
9
|
+
##
|
10
|
+
# @param [Hash] params Europeana API request parameters for Search query
|
11
|
+
# @see #params=
|
12
|
+
#
|
13
|
+
def initialize(params = {})
|
14
|
+
self.params = params
|
15
|
+
end
|
16
|
+
|
17
|
+
##
|
18
|
+
# Sends the Search request to the API
|
19
|
+
#
|
20
|
+
def execute
|
21
|
+
uri = request_uri
|
22
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
23
|
+
request = Net::HTTP::Get.new(uri.request_uri)
|
24
|
+
retries = Europeana.max_retries
|
25
|
+
|
26
|
+
begin
|
27
|
+
response = http.request(request)
|
28
|
+
rescue Timeout::Error, Errno::ECONNREFUSED, EOFError
|
29
|
+
retries -= 1
|
30
|
+
raise unless retries > 0
|
31
|
+
sleep Europeana.retry_delay
|
32
|
+
retry
|
33
|
+
end
|
34
|
+
|
35
|
+
json = JSON.parse(response.body)
|
36
|
+
raise Errors::RequestError, json['error'] unless json['success']
|
37
|
+
json
|
38
|
+
rescue JSON::ParserError
|
39
|
+
raise Errors::ResponseError
|
40
|
+
end
|
41
|
+
|
42
|
+
##
|
43
|
+
# Returns query params with API key added
|
44
|
+
#
|
45
|
+
# @return [Hash]
|
46
|
+
#
|
47
|
+
def params_with_authentication
|
48
|
+
raise Europeana::Errors::MissingAPIKeyError unless Europeana.api_key.present?
|
49
|
+
params.merge(:wskey => Europeana.api_key).reverse_merge(:query => "")
|
50
|
+
end
|
51
|
+
|
52
|
+
##
|
53
|
+
# Sets request parameters after validating keys
|
54
|
+
#
|
55
|
+
# Valid parameter keys:
|
56
|
+
# * :query
|
57
|
+
# * :profile
|
58
|
+
# * :qf
|
59
|
+
# * :rows
|
60
|
+
# * :start
|
61
|
+
# * :callback
|
62
|
+
#
|
63
|
+
# For explanations of these request parameters, see: http://labs.europeana.eu/api/search/
|
64
|
+
#
|
65
|
+
# Multiple `qf` parameters can be passed as a {Hash}:
|
66
|
+
#
|
67
|
+
# Europeana::Search.new(:qf => { :what => "Photograph", :where => [ "Paris", "London" ] })
|
68
|
+
#
|
69
|
+
# @param (see #initialize)
|
70
|
+
# @return [Hash] Passed params, if valid
|
71
|
+
#
|
72
|
+
def params=(params = {})
|
73
|
+
params.assert_valid_keys(:query, :profile, :qf, :rows, :start, :callback)
|
74
|
+
@params = params
|
75
|
+
end
|
76
|
+
|
77
|
+
##
|
78
|
+
# Gets the URI for this Search request with parameters
|
79
|
+
#
|
80
|
+
# @return [URI]
|
81
|
+
#
|
82
|
+
def request_uri
|
83
|
+
uri = URI.parse(Europeana::URL + "/search.json")
|
84
|
+
request_params = params_with_authentication
|
85
|
+
|
86
|
+
if request_params[:qf].is_a?(Hash)
|
87
|
+
qf = request_params.delete(:qf)
|
88
|
+
uri.query = request_params.to_query
|
89
|
+
qf.each_pair do |name, criteria|
|
90
|
+
[ criteria ].flatten.each do |criterion|
|
91
|
+
uri.query = uri.query + "&qf=" + CGI::escape(name.to_s) + ":" + CGI::escape(criterion)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
else
|
95
|
+
uri.query = request_params.to_query
|
96
|
+
end
|
97
|
+
|
98
|
+
uri
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
data/lib/europeana.rb
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
require "europeana/version"
|
2
|
+
require "net/http"
|
3
|
+
require "uri"
|
4
|
+
require "active_support/core_ext/object"
|
5
|
+
|
6
|
+
module Europeana
|
7
|
+
URL = 'http://www.europeana.eu/api/v2'
|
8
|
+
|
9
|
+
autoload :Errors, 'europeana/errors'
|
10
|
+
autoload :Record, 'europeana/record'
|
11
|
+
autoload :Search, 'europeana/search'
|
12
|
+
|
13
|
+
class << self
|
14
|
+
# The Europeana API key, required for authentication
|
15
|
+
attr_accessor :api_key
|
16
|
+
|
17
|
+
##
|
18
|
+
# The maximum number of retries permitted
|
19
|
+
#
|
20
|
+
# Retries occur when a network request to the API fails. The default is 5
|
21
|
+
# retries before giving up.
|
22
|
+
#
|
23
|
+
# @return [Integer]
|
24
|
+
#
|
25
|
+
attr_accessor :max_retries
|
26
|
+
|
27
|
+
##
|
28
|
+
# The number of seconds to wait between retries
|
29
|
+
#
|
30
|
+
# The default is 10 seconds.
|
31
|
+
#
|
32
|
+
# @return [Integer]
|
33
|
+
#
|
34
|
+
attr_accessor :retry_delay
|
35
|
+
|
36
|
+
##
|
37
|
+
# Sets configuration values to their defaults
|
38
|
+
#
|
39
|
+
def defaults!
|
40
|
+
self.max_retries = 5
|
41
|
+
self.retry_delay = 10
|
42
|
+
end
|
43
|
+
|
44
|
+
##
|
45
|
+
# Sends a Search request to the Europeana API
|
46
|
+
#
|
47
|
+
# Equivalent to:
|
48
|
+
# search = Europeana::Search.new(params)
|
49
|
+
# search.execute
|
50
|
+
#
|
51
|
+
# @param [Hash] params Query parameters
|
52
|
+
# @return [Hash] search response
|
53
|
+
# @see Europeana::Search#execute
|
54
|
+
#
|
55
|
+
def search(params = {})
|
56
|
+
Search.new(params).execute
|
57
|
+
end
|
58
|
+
|
59
|
+
##
|
60
|
+
# Sends a Record request to the Europeana API
|
61
|
+
#
|
62
|
+
# Equivalent to:
|
63
|
+
# search = Europeana::Record.new(record_id, params)
|
64
|
+
# record.get
|
65
|
+
#
|
66
|
+
# @param [String] Record ID
|
67
|
+
# @param [Hash] params Query parameters
|
68
|
+
# @return [Hash] search response
|
69
|
+
# @see Europeana::Record#get
|
70
|
+
#
|
71
|
+
def record(record_id, params = {})
|
72
|
+
Record.new(record_id, params).get
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
self.defaults!
|
77
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Europeana
|
4
|
+
describe "Errors" do
|
5
|
+
describe "MissingAPIKeyError" do
|
6
|
+
subject { Europeana::Errors::MissingAPIKeyError.new }
|
7
|
+
|
8
|
+
it "has an informative message" do
|
9
|
+
expect(subject.message).to match("Missing API key.")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Europeana
|
4
|
+
describe Record do
|
5
|
+
before(:each) do
|
6
|
+
@api_key = "xyz"
|
7
|
+
Europeana.api_key = @api_key
|
8
|
+
@record_id = "/abc/1234"
|
9
|
+
@params = { :callback => "doSomething();" }
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#new" do
|
13
|
+
context "without record ID" do
|
14
|
+
it "raises error" do
|
15
|
+
expect { subject }.to raise_error(ArgumentError)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context "with record ID" do
|
20
|
+
context "without params" do
|
21
|
+
subject { Europeana::Record.new(@record_id) }
|
22
|
+
|
23
|
+
it "should not raise error" do
|
24
|
+
expect { subject }.to_not raise_error
|
25
|
+
end
|
26
|
+
|
27
|
+
it "sets id attribute" do
|
28
|
+
expect(subject.instance_variable_get(:@id)).to eq(@record_id)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context "with params" do
|
33
|
+
subject { Europeana::Record.new(@record_id, @params) }
|
34
|
+
|
35
|
+
it "should not raise error" do
|
36
|
+
expect { subject }.to_not raise_error
|
37
|
+
end
|
38
|
+
|
39
|
+
it "sets params attribute" do
|
40
|
+
expect(subject.instance_variable_get(:@params)).to eq(@params)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#id" do
|
47
|
+
subject { Europeana::Record.new(@record_id) }
|
48
|
+
it "gets id attribute" do
|
49
|
+
expect(subject.id).to eq(subject.instance_variable_get(:@id))
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "#id=" do
|
54
|
+
subject { Europeana::Record.new(@record_id) }
|
55
|
+
|
56
|
+
context "with valid ID" do
|
57
|
+
it "sets id attribute" do
|
58
|
+
subject.id = "/xyz/5678"
|
59
|
+
expect(subject.instance_variable_get(:@id)).to eq("/xyz/5678")
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context "invalid ID" do
|
64
|
+
it "raises error" do
|
65
|
+
expect { subject.id = "invalid" }.to raise_error("Invalid Europeana record ID.")
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "#params" do
|
73
|
+
subject { Europeana::Record.new(@record_id, @params) }
|
74
|
+
it "gets params attribute" do
|
75
|
+
expect(subject.params).to eq(subject.instance_variable_get(:@params))
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "#params=" do
|
80
|
+
subject { Europeana::Record.new(@record_id, {}) }
|
81
|
+
|
82
|
+
context "valid params" do
|
83
|
+
it "sets params attribute" do
|
84
|
+
subject.params = @params
|
85
|
+
expect(subject.instance_variable_get(:@params)).to eq(@params)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
it "validates param names" do
|
90
|
+
expect { subject.params = { :invalid => "parameter" } }.to raise_error("Unknown key: invalid")
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe "#params_with_authentication" do
|
95
|
+
subject { Europeana::Record.new(@record_id, @params) }
|
96
|
+
|
97
|
+
context "with API key" do
|
98
|
+
it "adds API key to params" do
|
99
|
+
expect(subject.params_with_authentication).to eq(@params.merge(:wskey => @api_key))
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
context "without API key" do
|
104
|
+
it "raises an error" do
|
105
|
+
Europeana.api_key = nil
|
106
|
+
expect { subject.params_with_authentication }.to raise_error(Europeana::Errors::MissingAPIKeyError)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
describe "#request_uri" do
|
112
|
+
subject { Europeana::Record.new(@record_id, @params) }
|
113
|
+
|
114
|
+
it "returns a URI" do
|
115
|
+
expect(subject.request_uri).to be_a(URI)
|
116
|
+
end
|
117
|
+
|
118
|
+
it "includes the record ID" do
|
119
|
+
expect(subject.request_uri.to_s).to include(@record_id)
|
120
|
+
end
|
121
|
+
|
122
|
+
it "includes the query params" do
|
123
|
+
expect(subject.request_uri.to_s).to include(@params.to_query)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
describe "#get" do
|
128
|
+
subject { Europeana::Record.new(@record_id, @params).get }
|
129
|
+
it_behaves_like "record request"
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Europeana
|
4
|
+
describe Search do
|
5
|
+
before(:all) do
|
6
|
+
@params = { :query => "test", :profile => "standard", :qf => "where:London", :rows => 100, :start => 1, :callback => "" }
|
7
|
+
@api_key = "xyz"
|
8
|
+
end
|
9
|
+
|
10
|
+
before(:each) do
|
11
|
+
Europeana.api_key = @api_key
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#new" do
|
15
|
+
context "with no API request params" do
|
16
|
+
subject { lambda { Europeana::Search.new } }
|
17
|
+
it { should_not raise_error }
|
18
|
+
end
|
19
|
+
|
20
|
+
context "with API request params" do
|
21
|
+
subject { Europeana::Search.new(@params) }
|
22
|
+
it "should not raise error" do
|
23
|
+
expect { subject }.not_to raise_error
|
24
|
+
end
|
25
|
+
it "stores the request params" do
|
26
|
+
expect(subject.instance_variable_get(:@params)).to eq(@params)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#params" do
|
32
|
+
subject { Europeana::Search.new(@params) }
|
33
|
+
it "gets params attribute" do
|
34
|
+
expect(subject.params).to eq(@params)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "#params=" do
|
39
|
+
subject { Europeana::Search.new }
|
40
|
+
|
41
|
+
context "valid params" do
|
42
|
+
it "sets params attribute" do
|
43
|
+
subject.params = @params
|
44
|
+
expect(subject.instance_variable_get(:@params)).to eq(@params)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
it "validates param names" do
|
49
|
+
expect { subject.params = { :invalid => "parameter" } }.to raise_error("Unknown key: invalid")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "#request_uri" do
|
54
|
+
it "returns a URI" do
|
55
|
+
expect(subject.request_uri).to be_a(URI)
|
56
|
+
end
|
57
|
+
|
58
|
+
it "includes request params" do
|
59
|
+
expect(subject.request_uri.to_s).to eq("http://www.europeana.eu/api/v2/search.json?query=&wskey=#{@api_key}")
|
60
|
+
end
|
61
|
+
|
62
|
+
it "handles Hash of qf params" do
|
63
|
+
subject.params[:qf] = { :where => [ "London", "Paris" ], :what => "Photograph" }
|
64
|
+
expect(subject.request_uri.to_s).to eq("http://www.europeana.eu/api/v2/search.json?query=&wskey=#{@api_key}&qf=where:London&qf=where:Paris&qf=what:Photograph")
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "#params_with_authentication" do
|
69
|
+
subject { Europeana::Search.new }
|
70
|
+
|
71
|
+
context "with API key" do
|
72
|
+
it "adds API key to params" do
|
73
|
+
subject.params = @params
|
74
|
+
expect(subject.params_with_authentication).to eq(@params.merge(:wskey => @api_key))
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context "without API key" do
|
79
|
+
it "raises an error" do
|
80
|
+
subject.params = @params
|
81
|
+
Europeana.api_key = nil
|
82
|
+
expect { subject.params_with_authentication }.to raise_error(Europeana::Errors::MissingAPIKeyError)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "#execute" do
|
88
|
+
subject { Europeana::Search.new(@params).execute }
|
89
|
+
it_behaves_like "search request"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Europeana do
|
4
|
+
before(:each) do
|
5
|
+
Europeana.defaults!
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "::URL" do
|
9
|
+
it "returns 'http://www.europeana.eu/api/v2'" do
|
10
|
+
expect(Europeana::URL).to eq("http://www.europeana.eu/api/v2")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe ".api_key=" do
|
15
|
+
before(:all) do
|
16
|
+
@api_key = "xyz"
|
17
|
+
end
|
18
|
+
it "sets the API key" do
|
19
|
+
Europeana.api_key = @api_key
|
20
|
+
expect(Europeana.instance_variable_get(:@api_key)).to eq(@api_key)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe ".api_key" do
|
25
|
+
before(:all) do
|
26
|
+
@api_key = "xyz"
|
27
|
+
end
|
28
|
+
it "gets the API key" do
|
29
|
+
Europeana.instance_variable_set(:@api_key, @api_key)
|
30
|
+
expect(Europeana.api_key).to eq(@api_key)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe ".max_retries" do
|
35
|
+
it "defaults to 5" do
|
36
|
+
expect(Europeana.max_retries).to eq(5)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe ".max_retries=" do
|
41
|
+
it "sets the maximum number of retries" do
|
42
|
+
Europeana.max_retries = 2
|
43
|
+
expect(Europeana.max_retries).to eq(2)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe ".retry_delay" do
|
48
|
+
it "defaults to 10" do
|
49
|
+
expect(Europeana.retry_delay).to eq(10)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe ".retry_delay=" do
|
54
|
+
it "sets the retry delay" do
|
55
|
+
Europeana.retry_delay = 3
|
56
|
+
expect(Europeana.retry_delay).to eq(3)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe ".defaults!" do
|
61
|
+
it "sets retry delay to its default" do
|
62
|
+
Europeana.retry_delay = 3
|
63
|
+
expect { Europeana.defaults! }.to change { Europeana.retry_delay }.from(3).to(10)
|
64
|
+
end
|
65
|
+
|
66
|
+
it "sets max retries to its default" do
|
67
|
+
Europeana.max_retries = 3
|
68
|
+
expect { Europeana.defaults! }.to change { Europeana.max_retries }.from(3).to(5)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe ".search" do
|
73
|
+
subject { Europeana.search(@params) }
|
74
|
+
it_behaves_like "search request"
|
75
|
+
end
|
76
|
+
|
77
|
+
describe ".search" do
|
78
|
+
subject { Europeana.record(@record_id, @params) }
|
79
|
+
it_behaves_like "record request"
|
80
|
+
end
|
81
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
shared_examples "API request" do
|
2
|
+
context "without API key" do
|
3
|
+
before(:each) do
|
4
|
+
Europeana.api_key = nil
|
5
|
+
end
|
6
|
+
|
7
|
+
it "sends no HTTP request" do
|
8
|
+
begin
|
9
|
+
subject
|
10
|
+
rescue Europeana::Errors::MissingAPIKeyError
|
11
|
+
end
|
12
|
+
expect(a_request(:get, /www.europeana.eu\/api\/v2/)).not_to have_been_made
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context "with API key" do
|
17
|
+
before(:all) do
|
18
|
+
Europeana.api_key = "xyz"
|
19
|
+
end
|
20
|
+
|
21
|
+
it "returns the response as a Hash" do
|
22
|
+
response = subject
|
23
|
+
expect(response).to be_a(Hash)
|
24
|
+
end
|
25
|
+
|
26
|
+
context "when the API is unavailable" do
|
27
|
+
before(:each) do
|
28
|
+
Europeana.retry_delay = 0
|
29
|
+
end
|
30
|
+
|
31
|
+
it "waits then retries" do
|
32
|
+
stub_request(:get, /www.europeana.eu\/api\/v2/).
|
33
|
+
to_timeout.times(1).then.
|
34
|
+
to_return(:body => '{"success":true}')
|
35
|
+
subject
|
36
|
+
expect(a_request(:get, /www.europeana.eu\/api\/v2/)).to have_been_made.times(2)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context "when API response is unsuccessful" do
|
41
|
+
it "raises a RequestError" do
|
42
|
+
stub_request(:get, /www.europeana.eu\/api\/v2/).to_return(:body => '{"success":false,"error":"Something went wrong"}')
|
43
|
+
expect { subject }.to raise_error(Europeana::Errors::RequestError, "Something went wrong")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context "when API response is invalid JSON" do
|
48
|
+
it "raises a ResponseError" do
|
49
|
+
stub_request(:get, /www.europeana.eu\/api\/v2/).to_return(:body => 'invalid JSON')
|
50
|
+
expect { subject }.to raise_error(Europeana::Errors::ResponseError)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
shared_examples "record request" do
|
2
|
+
before(:all) do
|
3
|
+
@api_key = "xyz"
|
4
|
+
@record_id = "/abc/1234"
|
5
|
+
@params = { :callback => "doSomething();" }
|
6
|
+
end
|
7
|
+
|
8
|
+
before(:each) do
|
9
|
+
stub_request(:get, /www.europeana.eu\/api\/v2\/record#{@record_id}\.json/).to_return(:body => '{"success":true}')
|
10
|
+
end
|
11
|
+
|
12
|
+
it_behaves_like "API request"
|
13
|
+
|
14
|
+
context "with API key" do
|
15
|
+
before(:all) do
|
16
|
+
Europeana.api_key = @api_key
|
17
|
+
end
|
18
|
+
|
19
|
+
it "sends a Record request to the API" do
|
20
|
+
subject
|
21
|
+
expect(a_request(:get, /www.europeana.eu\/api\/v2\/record#{@record_id}\.json/)).to have_been_made.once
|
22
|
+
end
|
23
|
+
|
24
|
+
context "when record ID is invalid" do
|
25
|
+
it "raises RequestError from HTML 404 response" do
|
26
|
+
stub_request(:get, /www.europeana.eu\/api\/v2\/record#{@record_id}\.json/).
|
27
|
+
to_return(:body => '<html></html>', :headers => { 'Content-Type' => 'text/html' }, :status => 404)
|
28
|
+
expect { subject }.to raise_error(Europeana::Errors::RequestError, "Invalid record identifier: #{@record_id}")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
shared_examples "search request" do
|
2
|
+
before(:all) do
|
3
|
+
@api_key = "xyz"
|
4
|
+
@params = {}
|
5
|
+
end
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
stub_request(:get, /www.europeana.eu\/api\/v2\/search\.json/).to_return(:body => '{"success":true}')
|
9
|
+
end
|
10
|
+
|
11
|
+
it_behaves_like "API request"
|
12
|
+
|
13
|
+
context "with API key" do
|
14
|
+
before(:all) do
|
15
|
+
Europeana.api_key = @api_key
|
16
|
+
end
|
17
|
+
|
18
|
+
it "sends a Search request to the API" do
|
19
|
+
subject
|
20
|
+
expect(a_request(:get, /www.europeana.eu\/api\/v2\/search\.json/)).to have_been_made.once
|
21
|
+
end
|
22
|
+
|
23
|
+
context "without query" do
|
24
|
+
it "sets an empty query" do
|
25
|
+
subject
|
26
|
+
expect(a_request(:get, /www.europeana.eu\/api\/v2\/search\.json\?query=/)).to have_been_made.once
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context "with query" do
|
31
|
+
before(:all) do
|
32
|
+
@params = { :query => "test" }
|
33
|
+
end
|
34
|
+
it "sends query" do
|
35
|
+
subject
|
36
|
+
expect(a_request(:get, /www.europeana.eu\/api\/v2\/search\.json\?query=test/)).to have_been_made.once
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
metadata
ADDED
@@ -0,0 +1,169 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: europeana
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Richard Doe
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-06-18 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activesupport
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '3.0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '3.0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: multi_json
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '1.0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '1.0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: bundler
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '1.3'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.3'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rake
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: rspec
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ~>
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '3.0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '3.0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: webmock
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ~>
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: 1.18.0
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 1.18.0
|
110
|
+
description: Search and retrieve records from the Europeana REST API
|
111
|
+
email:
|
112
|
+
- richard.doe@rwdit.net
|
113
|
+
executables: []
|
114
|
+
extensions: []
|
115
|
+
extra_rdoc_files: []
|
116
|
+
files:
|
117
|
+
- .gitignore
|
118
|
+
- Gemfile
|
119
|
+
- LICENSE.pdf
|
120
|
+
- README.md
|
121
|
+
- Rakefile
|
122
|
+
- europeana.gemspec
|
123
|
+
- lib/europeana.rb
|
124
|
+
- lib/europeana/errors.rb
|
125
|
+
- lib/europeana/record.rb
|
126
|
+
- lib/europeana/search.rb
|
127
|
+
- lib/europeana/version.rb
|
128
|
+
- spec/europeana/errors_spec.rb
|
129
|
+
- spec/europeana/record_spec.rb
|
130
|
+
- spec/europeana/search_spec.rb
|
131
|
+
- spec/europeana_spec.rb
|
132
|
+
- spec/spec_helper.rb
|
133
|
+
- spec/support/shared_examples/api_request.rb
|
134
|
+
- spec/support/shared_examples/record_request.rb
|
135
|
+
- spec/support/shared_examples/search_request.rb
|
136
|
+
homepage: https://github.com/europeana/europeana-client-ruby
|
137
|
+
licenses:
|
138
|
+
- EUPL 1.1
|
139
|
+
post_install_message:
|
140
|
+
rdoc_options: []
|
141
|
+
require_paths:
|
142
|
+
- lib
|
143
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
144
|
+
none: false
|
145
|
+
requirements:
|
146
|
+
- - ! '>='
|
147
|
+
- !ruby/object:Gem::Version
|
148
|
+
version: '0'
|
149
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
150
|
+
none: false
|
151
|
+
requirements:
|
152
|
+
- - ! '>='
|
153
|
+
- !ruby/object:Gem::Version
|
154
|
+
version: '0'
|
155
|
+
requirements: []
|
156
|
+
rubyforge_project:
|
157
|
+
rubygems_version: 1.8.25
|
158
|
+
signing_key:
|
159
|
+
specification_version: 3
|
160
|
+
summary: Ruby client library for the Europeana API
|
161
|
+
test_files:
|
162
|
+
- spec/europeana/errors_spec.rb
|
163
|
+
- spec/europeana/record_spec.rb
|
164
|
+
- spec/europeana/search_spec.rb
|
165
|
+
- spec/europeana_spec.rb
|
166
|
+
- spec/spec_helper.rb
|
167
|
+
- spec/support/shared_examples/api_request.rb
|
168
|
+
- spec/support/shared_examples/record_request.rb
|
169
|
+
- spec/support/shared_examples/search_request.rb
|