europeana-api 0.3.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 894ad987b215b9e7dfd6002f1e2f7225fcab25ae
4
+ data.tar.gz: 87e594f04c09dc273d7b285975ae682b4fbf7675
5
+ SHA512:
6
+ metadata.gz: bcd7ad50a881202448ef74db5ab0165b5147448ab6a1e2df915741dd53d27cc76e723c5270a22de4778b06641d21dba5f634553d4e16f8457fe4e3c0afe08d8c
7
+ data.tar.gz: c490cbfa7b307dd0a25ba8cd84d4226b2bc49b8efb461bec3c975e38b6822cdfa337df5fc88fbe56543aea7d5cbf28c7408d6594b5c6c6f9bb4625fd96c0dd1c
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in europeana.gemspec
4
+ gemspec
Binary file
@@ -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-api'
11
+
12
+ And then execute:
13
+
14
+ $ bundle
15
+
16
+ Or install it yourself as:
17
+
18
+ $ gem install europeana-api
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.api_key = "xyz"
33
+
34
+ ### Search
35
+
36
+ search = Europeana::API.search(:query => '"first world war"') # => { "success" => true, "items" => [ ... ], "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::API.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
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
@@ -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/api/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'europeana-api'
8
+ spec.version = Europeana::API::VERSION
9
+ spec.authors = ['Richard Doe']
10
+ spec.email = ['richard.doe@rwdit.net']
11
+ spec.description = 'Search and retrieve records from the Europeana REST API'
12
+ spec.summary = 'Ruby client library for the Europeana API'
13
+ spec.homepage = 'https://github.com/rwd/europeana-api-client-ruby'
14
+ spec.license = 'EUPL 1.1'
15
+
16
+ spec.files = `git ls-files`.split($RS)
17
+ spec.executables = spec.files.grep(/^bin\//) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(/^(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,95 @@
1
+ require 'europeana/api/version'
2
+ require 'uri'
3
+ require 'logger'
4
+ require 'active_support/core_ext/object'
5
+ require 'active_support/hash_with_indifferent_access'
6
+
7
+ ##
8
+ # Europeana REST API client
9
+ module Europeana
10
+ module API
11
+ API_VERSION = 'v2'
12
+ URL = "http://www.europeana.eu/api/#{API_VERSION}"
13
+
14
+ autoload :Errors, 'europeana/api/errors'
15
+ autoload :Record, 'europeana/api/record'
16
+ autoload :Request, 'europeana/api/request'
17
+ autoload :Search, 'europeana/api/search'
18
+
19
+ class << self
20
+ # The Europeana API key, required for authentication
21
+ attr_accessor :api_key
22
+
23
+ ##
24
+ # The maximum number of retries permitted
25
+ #
26
+ # Retries occur when a network request to the API fails. The default is 5
27
+ # retries before giving up.
28
+ #
29
+ # @return [Integer]
30
+ #
31
+ attr_accessor :max_retries
32
+
33
+ ##
34
+ # The number of seconds to wait between retries
35
+ #
36
+ # The default is 10 seconds.
37
+ #
38
+ # @return [Integer]
39
+ #
40
+ attr_accessor :retry_delay
41
+
42
+ ##
43
+ # Sets configuration values to their defaults
44
+ #
45
+ def defaults!
46
+ self.max_retries = 5
47
+ self.retry_delay = 10
48
+ end
49
+
50
+ ##
51
+ # Sends a Search request to the Europeana API
52
+ #
53
+ # Equivalent to:
54
+ # search = Europeana::Search.new(params)
55
+ # search.execute
56
+ #
57
+ # @param [Hash] params Query parameters
58
+ # @return [Hash] search response
59
+ # @see Europeana::Search#execute
60
+ #
61
+ def search(params = {})
62
+ Search.new(params).execute
63
+ end
64
+
65
+ ##
66
+ # Sends a Record request to the Europeana API
67
+ #
68
+ # Equivalent to:
69
+ # search = Europeana::Record.new(record_id, params)
70
+ # record.get
71
+ #
72
+ # @param [String] Record ID
73
+ # @param [Hash] params Query parameters
74
+ # @return [Hash] search response
75
+ # @see Europeana::Record#get
76
+ #
77
+ def record(record_id, params = {})
78
+ Record.new(record_id, params).get
79
+ end
80
+
81
+ def logger
82
+ unless @logger
83
+ if defined?(Rails) && Rails.logger
84
+ @logger = Rails.logger
85
+ else
86
+ @logger = Logger.new(STDOUT)
87
+ end
88
+ end
89
+ @logger
90
+ end
91
+ end
92
+
93
+ self.defaults!
94
+ end
95
+ end
@@ -0,0 +1,51 @@
1
+ module Europeana
2
+ module API
3
+ module Errors
4
+ ##
5
+ # Raised if API requests are attempted without the API key having been set.
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
+ class RequestError < StandardError
27
+ def initialize(msg = nil)
28
+ msg ||= <<-MSG
29
+ Request error.
30
+
31
+ There was a problem with your request to the Europeana API.
32
+ MSG
33
+ super(msg)
34
+ end
35
+ end
36
+
37
+ ##
38
+ # Raised if the API response is not valid JSON.
39
+ class ResponseError < StandardError
40
+ def initialize(msg = nil)
41
+ msg ||= <<-MSG
42
+ Response error.
43
+
44
+ Unable to parse the response from the Europeana API.
45
+ MSG
46
+ super(msg)
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,142 @@
1
+ module Europeana
2
+ module API
3
+ ##
4
+ # Interface to the Europeana API Record method
5
+ #
6
+ # @see http://labs.europeana.eu/api/record/
7
+ class Record
8
+ # Europeana ID of the record
9
+ attr_accessor :id
10
+
11
+ # Request parameters to send to the API
12
+ attr_accessor :params
13
+
14
+ ##
15
+ # @param [String] id Europeana ID of the record
16
+ # @param [Hash] params Request parameters
17
+ def initialize(id, params = {})
18
+ self.id = id
19
+ self.params = params
20
+ @hierarchy = HashWithIndifferentAccess.new
21
+ end
22
+
23
+ ##
24
+ # Returns query params with API key added
25
+ #
26
+ # @return [Hash]
27
+ def params_with_authentication
28
+ return params if params.key?(:wskey)
29
+ unless Europeana::API.api_key.present?
30
+ fail Errors::MissingAPIKeyError
31
+ end
32
+ params.merge(wskey: Europeana::API.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
+ unless id.is_a?(String) && id.match(%r{\A/[^/]+/[^/]+\B})
42
+ fail ArgumentError, "Invalid Europeana record ID: \"#{id}\""
43
+ end
44
+ @id = id
45
+ end
46
+
47
+ ##
48
+ # Sets request parameters after validating keys
49
+ #
50
+ # Valid parameter keys:
51
+ # * :callback
52
+ #
53
+ # For explanations of these request parameters, see: http://labs.europeana.eu/api/record/
54
+ #
55
+ # @param (see #initialize)
56
+ # @return [Hash] Request parameters
57
+ def params=(params = {})
58
+ params.assert_valid_keys(:callback, :wskey)
59
+ @params = params
60
+ end
61
+
62
+ ##
63
+ # Gets the URI for this Record request with parameters
64
+ #
65
+ # @return [URI]
66
+ def request_uri
67
+ uri = URI.parse(Europeana::API::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 [HashWithIndifferentAccess]
76
+ # @raise [Europeana::Errors::ResponseError] if API response could not be
77
+ # parsed as JSON
78
+ # @raise [Europeana::Errors::RequestError] if API response has
79
+ # `success:false`
80
+ # @raise [Europeana::Errors::RequestError] if API response has 404 status
81
+ # code
82
+ def get
83
+ request = Request.new(request_uri)
84
+ response = request.execute
85
+ body = JSON.parse(response.body)
86
+ fail Errors::RequestError, body['error'] unless body['success']
87
+ HashWithIndifferentAccess.new(body)
88
+ rescue JSON::ParserError
89
+ if response.code.to_i == 404
90
+ # Handle HTML 404 responses on malformed record ID, emulating API's
91
+ # JSON response.
92
+ raise Errors::RequestError, "Invalid record identifier: #{@id}"
93
+ else
94
+ raise Errors::ResponseError
95
+ end
96
+ end
97
+
98
+ ##
99
+ # Gets hierarchy data about this and related records from
100
+ # ancestor-self-siblings.json API method
101
+ #
102
+ # @note Proof of concept implementation for demo purposes.
103
+ # @todo Refactor if functionality to be retained.
104
+ def hierarchy(*args)
105
+ args = [:self] if args.blank?
106
+
107
+ data = {}
108
+ args.each do |method|
109
+ unless @hierarchy.key?(method)
110
+ @hierarchy[method] = hierarchical_data(method).select do |_k, v|
111
+ v.is_a?(Enumerable)
112
+ end
113
+ end
114
+ data.merge!(@hierarchy[method])
115
+ end
116
+ data
117
+ end
118
+
119
+ def hierarchical_data(method = :self)
120
+ request = Request.new(hierarchical_data_uri(method))
121
+ response = request.execute
122
+ body = JSON.parse(response.body)
123
+ fail Errors::RequestError, body['message'] unless body['success']
124
+ body
125
+ rescue JSON::ParserError
126
+ if response.code.to_i == 404
127
+ # Handle HTML 404 responses on malformed record ID, emulating API's
128
+ # JSON response.
129
+ raise Errors::RequestError, "Invalid record identifier: #{@id}"
130
+ else
131
+ raise Errors::ResponseError
132
+ end
133
+ end
134
+
135
+ def hierarchical_data_uri(method = :self)
136
+ uri = URI.parse(Europeana::API::URL + "/record#{@id}/#{method}.json")
137
+ uri.query = params_with_authentication.to_query
138
+ uri
139
+ end
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,49 @@
1
+ require 'active_support/benchmarkable'
2
+ require 'net/http'
3
+
4
+ module Europeana
5
+ module API
6
+ ##
7
+ # Europeana API request
8
+ class Request
9
+ include ActiveSupport::Benchmarkable
10
+
11
+ # Request URI
12
+ attr_reader :uri
13
+
14
+ # API response
15
+ attr_reader :response
16
+
17
+ # @param [URI]
18
+ def initialize(uri)
19
+ @uri = uri
20
+ end
21
+
22
+ # @return (see Net::HTTP#request)
23
+ def execute
24
+ logger.debug("#{self.class} API URL: #{uri}")
25
+
26
+ benchmark("#{self.class} API query", level: :debug) do
27
+ http = Net::HTTP.new(uri.host, uri.port)
28
+ request = Net::HTTP::Get.new(uri.request_uri)
29
+ retries = Europeana::API.max_retries
30
+
31
+ begin
32
+ @response = http.request(request)
33
+ rescue Timeout::Error, Errno::ECONNREFUSED, EOFError
34
+ retries -= 1
35
+ raise unless retries > 0
36
+ sleep Europeana::API.retry_delay
37
+ retry
38
+ end
39
+
40
+ @response
41
+ end
42
+ end
43
+
44
+ def logger
45
+ Europeana::API.logger
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,67 @@
1
+ module Europeana
2
+ module API
3
+ ##
4
+ # Interface to Europeana API's Search method
5
+ class Search
6
+ # Query params
7
+ attr_accessor :params
8
+
9
+ ##
10
+ # @param [Hash] params Europeana API request parameters for Search query
11
+ def initialize(params = {})
12
+ @params = HashWithIndifferentAccess.new(params)
13
+ end
14
+
15
+ ##
16
+ # Sends the Search request to the API
17
+ #
18
+ # @return [HashWithIndifferentAccess]
19
+ # @raise [Europeana::Errors::ResponseError] if API response could not be
20
+ # parsed as JSON
21
+ # @raise [Europeana::Errors::RequestError] if API response has
22
+ # `success:false`
23
+ def execute
24
+ request = Request.new(request_uri)
25
+ response = request.execute
26
+ body = JSON.parse(response.body)
27
+ fail Errors::RequestError, body['error'] unless body['success']
28
+ HashWithIndifferentAccess.new(body)
29
+ rescue JSON::ParserError
30
+ raise Errors::ResponseError
31
+ end
32
+
33
+ ##
34
+ # Returns query params with API key added
35
+ #
36
+ # @return [Hash]
37
+ def params_with_authentication
38
+ return params if params.key?(:wskey)
39
+ unless Europeana::API.api_key.present?
40
+ fail Errors::MissingAPIKeyError
41
+ end
42
+ params.merge(wskey: Europeana::API.api_key)
43
+ end
44
+
45
+ ##
46
+ # Gets the URI for this Search request with parameters
47
+ #
48
+ # @return [URI]
49
+ def request_uri
50
+ uri = URI.parse(Europeana::API::URL + '/search.json')
51
+ uri.query = request_uri_query
52
+ uri
53
+ end
54
+
55
+ def request_uri_query
56
+ uri_query = ''
57
+ params_with_authentication.each_pair do |name, value|
58
+ [value].flatten.each do |v|
59
+ uri_query << '&' unless uri_query.blank?
60
+ uri_query << CGI.escape(name.to_s) + '=' + CGI.escape(v.to_s)
61
+ end
62
+ end
63
+ uri_query
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,7 @@
1
+ module Europeana
2
+ ##
3
+ # Sets the *gem* version (not the *API* version)
4
+ module API
5
+ VERSION = '0.3.0'
6
+ end
7
+ 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 ".record" do
78
+ subject { Europeana.record(@record_id, @params) }
79
+ it_behaves_like "record request"
80
+ end
81
+ end
@@ -0,0 +1,10 @@
1
+ require 'europeana'
2
+ require 'webmock/rspec'
3
+
4
+ Dir["./spec/support/**/*.rb"].each { |f| require f }
5
+
6
+ RSpec.configure do |config|
7
+ config.expect_with :rspec do |c|
8
+ c.syntax = :expect
9
+ end
10
+ end
@@ -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,156 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: europeana-api
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.0
5
+ platform: ruby
6
+ authors:
7
+ - Richard Doe
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-03-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '3.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '3.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: multi_json
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.3'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: webmock
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 1.18.0
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 1.18.0
97
+ description: Search and retrieve records from the Europeana REST API
98
+ email:
99
+ - richard.doe@rwdit.net
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - ".gitignore"
105
+ - Gemfile
106
+ - LICENSE.pdf
107
+ - README.md
108
+ - Rakefile
109
+ - europeana-api.gemspec
110
+ - lib/europeana/api.rb
111
+ - lib/europeana/api/errors.rb
112
+ - lib/europeana/api/record.rb
113
+ - lib/europeana/api/request.rb
114
+ - lib/europeana/api/search.rb
115
+ - lib/europeana/api/version.rb
116
+ - spec/europeana/errors_spec.rb
117
+ - spec/europeana/record_spec.rb
118
+ - spec/europeana/search_spec.rb
119
+ - spec/europeana_spec.rb
120
+ - spec/spec_helper.rb
121
+ - spec/support/shared_examples/api_request.rb
122
+ - spec/support/shared_examples/record_request.rb
123
+ - spec/support/shared_examples/search_request.rb
124
+ homepage: https://github.com/rwd/europeana-api-client-ruby
125
+ licenses:
126
+ - EUPL 1.1
127
+ metadata: {}
128
+ post_install_message:
129
+ rdoc_options: []
130
+ require_paths:
131
+ - lib
132
+ required_ruby_version: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
137
+ required_rubygems_version: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - ">="
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ requirements: []
143
+ rubyforge_project:
144
+ rubygems_version: 2.4.6
145
+ signing_key:
146
+ specification_version: 4
147
+ summary: Ruby client library for the Europeana API
148
+ test_files:
149
+ - spec/europeana/errors_spec.rb
150
+ - spec/europeana/record_spec.rb
151
+ - spec/europeana/search_spec.rb
152
+ - spec/europeana_spec.rb
153
+ - spec/spec_helper.rb
154
+ - spec/support/shared_examples/api_request.rb
155
+ - spec/support/shared_examples/record_request.rb
156
+ - spec/support/shared_examples/search_request.rb