europeana-api 0.3.0

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