europeana-api 0.3.6 → 0.4.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1bc2819fe6fc5ae0932fc49cda0b1bff61d435c4
4
- data.tar.gz: b3d90815c7c71abcf4f7a6105e6e91652e395622
3
+ metadata.gz: 11327d8d43595f2888b4d3f501875fd45894abe5
4
+ data.tar.gz: 80e3e9ff21ab54e2bedcf70d8245fc7b84b30f50
5
5
  SHA512:
6
- metadata.gz: 0ad1cda878963ceb34f275bfd51aa04b17dfcf81892a3ddce8ff14e144f4e72dab2af5bf75e3d7344224e06e5113ba78bd4932b1753fba252c53ac24317aec84
7
- data.tar.gz: 1463a36d3b7104a3afcd88de68ba4dbd89655df9bf80a65f9e9e96b6e0f8f15801361e048d98ead124b3bb9e3a9135bdba40852f015c0abf3d7a67c452811f1c
6
+ metadata.gz: ec133494538ec61c5a45a01d9fb975f635b58b30136a5dd48c5f7c4efd5a3d5545ef36a238873b8ebb16b087628354e630c9903e1fe014cddd856412a1e3f35a
7
+ data.tar.gz: ca2870267f8f896def561a84ff9b087f3d73463f516c7c34b2080b5ec7da513a18804288c07bcfc6956ac10c9cc5e08df521f7888ca7cc7d417c3f4da841962a
data/.ruby-style.yml CHANGED
@@ -496,7 +496,7 @@ Metrics/CyclomaticComplexity:
496
496
  Metrics/LineLength:
497
497
  Description: Limit lines to 80 characters.
498
498
  StyleGuide: https://github.com/bbatsov/ruby-style-guide#80-character-limits
499
- Enabled: true
499
+ Enabled: false
500
500
  Max: 80
501
501
  AllowURI: true
502
502
  URISchemes:
data/.travis.yml CHANGED
@@ -1,6 +1,9 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.2.1
3
+ - 2.0.0
4
+ - 2.1.7
5
+ - 2.2.2
6
+ - 2.2.3
4
7
  notifications:
5
8
  email: false
6
9
  sudo: false
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Europeana
2
2
 
3
- [![Build Status](https://travis-ci.org/rwd/europeana-api-client-ruby.svg?branch=master)](https://travis-ci.org/rwd/europeana-api-client-ruby) [![Coverage Status](https://coveralls.io/repos/rwd/europeana-api-client-ruby/badge.svg?branch=master&service=github)](https://coveralls.io/github/rwd/europeana-api-client-ruby?branch=master) [![security](https://hakiri.io/github/rwd/europeana-api-client-ruby/master.svg)](https://hakiri.io/github/rwd/europeana-api-client-ruby/master)
3
+ [![Build Status](https://travis-ci.org/europeana/europeana-api-client-ruby.svg?branch=master)](https://travis-ci.org/europeana/europeana-api-client-ruby) [![Coverage Status](https://coveralls.io/repos/europeana/europeana-api-client-ruby/badge.svg?branch=master&service=github)](https://coveralls.io/github/europeana/europeana-api-client-ruby?branch=master) [![security](https://hakiri.io/github/europeana/europeana-api-client-ruby/master.svg)](https://hakiri.io/github/europeana/europeana-api-client-ruby/master) [![Dependency Status](https://gemnasium.com/europeana/europeana-api-client-ruby.svg)](https://gemnasium.com/europeana/europeana-api-client-ruby)
4
4
 
5
5
  Ruby client library for the search and retrieval of records from the [Europeana
6
6
  REST API](http://labs.europeana.eu/api/introduction/).
@@ -33,7 +33,7 @@ Or install it yourself as:
33
33
 
34
34
  Authentication is *required* for all requests to the Europeana API.
35
35
 
36
- Only Basic Authentication (by API key) is supported.
36
+ Only Basic Authentication (by API key) is supported.
37
37
 
38
38
  Sign up for an API key at: http://labs.europeana.eu/api/registration/
39
39
 
@@ -58,17 +58,9 @@ the search response.
58
58
  ### Record
59
59
 
60
60
  ```ruby
61
- record = Europeana::API.record('abc/1234') # => { "success" => true, "object" => { ... }, ... }
62
- record['object'] # => { "title" => "...", "proxies" => [ ... ], "aggregations" => [ ... ]
61
+ record = Europeana::API.record('/abc/1234') # => { "success" => true, "object" => { ... }, ... }
62
+ record['object'] # => { "title" => "...", "proxies" => [ ... ], "aggregations" => [ ... ], ... }
63
63
  ```
64
64
 
65
65
  See http://labs.europeana.eu/api/record/ for details of the data returned in
66
66
  the record response.
67
-
68
- ## Contributing
69
-
70
- 1. Fork it
71
- 2. Create your feature branch (`git checkout -b my-new-feature`)
72
- 3. Commit your changes (`git commit -am 'Add some feature'`)
73
- 4. Push to the branch (`git push origin my-new-feature`)
74
- 5. Create new Pull Request
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(/^(test|spec|features)\//)
19
19
  spec.require_paths = ['lib']
20
20
 
21
- spec.required_ruby_version = '>= 1.9.2'
21
+ spec.required_ruby_version = '>= 2.0.0'
22
22
 
23
23
  spec.add_dependency 'activesupport', '>= 3.0'
24
24
  spec.add_dependency 'multi_json', '~> 1.0'
data/lib/europeana/api.rb CHANGED
@@ -1,5 +1,9 @@
1
+ require 'active_support/cache'
1
2
  require 'active_support/core_ext/object'
3
+ require 'active_support/core_ext/hash/indifferent_access'
4
+ require 'active_support/core_ext/hash/slice'
2
5
  require 'active_support/hash_with_indifferent_access'
6
+ require 'active_support/inflector/methods'
3
7
  require 'europeana/api/version'
4
8
  require 'logger'
5
9
  require 'uri'
@@ -8,10 +12,11 @@ module Europeana
8
12
  ##
9
13
  # Europeana REST API client
10
14
  module API
11
- autoload :Errors, 'europeana/api/errors'
12
- autoload :Record, 'europeana/api/record'
13
- autoload :Request, 'europeana/api/request'
14
- autoload :Search, 'europeana/api/search'
15
+ autoload :Errors, 'europeana/api/errors'
16
+ autoload :Record, 'europeana/api/record'
17
+ autoload :Request, 'europeana/api/request'
18
+ autoload :Requestable, 'europeana/api/requestable'
19
+ autoload :Search, 'europeana/api/search'
15
20
 
16
21
  class << self
17
22
  ##
@@ -46,12 +51,18 @@ module Europeana
46
51
  # @return [Logger]
47
52
  attr_writer :logger
48
53
 
54
+ attr_accessor :cache_store
55
+
56
+ attr_accessor :cache_expires_in
57
+
49
58
  ##
50
59
  # Sets configuration values to their defaults
51
60
  def defaults!
52
61
  self.url = 'http://www.europeana.eu/api/v2'
53
62
  self.max_retries = 5
54
63
  self.retry_delay = 10
64
+ self.cache_store = ActiveSupport::Cache::NullStore.new
65
+ self.cache_expires_in = 24.hours
55
66
  end
56
67
 
57
68
  ##
@@ -5,31 +5,22 @@ module Europeana
5
5
  #
6
6
  # @see http://labs.europeana.eu/api/record/
7
7
  class Record
8
+ autoload :Hierarchy, 'europeana/api/record/hierarchy'
9
+
10
+ include Requestable
11
+
8
12
  # Europeana ID of the record
9
- attr_accessor :id
13
+ attr_reader :id
10
14
 
11
15
  # Request parameters to send to the API
12
- attr_accessor :params
16
+ attr_reader :params
13
17
 
14
18
  ##
15
19
  # @param [String] id Europeana ID of the record
16
20
  # @param [Hash] params Request parameters
17
21
  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) && params[:wskey].present?
29
- unless Europeana::API.api_key.present?
30
- fail Errors::MissingAPIKeyError
31
- end
32
- params.merge(wskey: Europeana::API.api_key)
22
+ @id = id
23
+ @params = params
33
24
  end
34
25
 
35
26
  ##
@@ -60,92 +51,47 @@ module Europeana
60
51
  end
61
52
 
62
53
  ##
63
- # Gets the URI for this Record request with parameters
54
+ # Gets the URL for this Record request
64
55
  #
65
56
  # @param [Hash{Symbol => Object}] options
66
57
  # @option options [Boolean] :ld (false)
67
58
  # Request JSON-LD
68
- # @return [URI]
69
- def request_uri(options = {})
70
- url = Europeana::API.url + "/record#{@id}.json"
71
- url << 'ld' if options[:ld]
72
- uri = URI.parse(url)
73
- uri.query = params_with_authentication.to_query
74
- uri
59
+ # @return [String]
60
+ def request_url(options = {})
61
+ options.assert_valid_keys(:ld)
62
+ (Europeana::API.url + "/record#{@id}.json").tap do |url|
63
+ url << 'ld' if options[:ld]
64
+ end
75
65
  end
76
66
 
67
+ alias_method :get, :execute_request
68
+
77
69
  ##
78
- # Sends a request for this record to the API
70
+ # Examines the `success` and `error` fields of the response for failure
79
71
  #
80
- # @param [Hash{Symbol => Object}] options
81
- # @option options [Boolean] :ld (false)
82
- # Request JSON-LD
83
- # @return [Hash]
84
- # @raise [Europeana::Errors::ResponseError] if API response could not be
85
- # parsed as JSON
86
72
  # @raise [Europeana::Errors::RequestError] if API response has
87
73
  # `success:false`
88
74
  # @raise [Europeana::Errors::RequestError] if API response has 404 status
89
75
  # code
90
- def get(options = {})
91
- request = Request.new(request_uri(options))
92
- response = request.execute
93
- body = JSON.parse(response.body)
94
- if (options[:ld] && !(200..299).include?(response.code.to_i)) || (!options[:ld] && !body['success'])
95
- fail Errors::RequestError, (body.key?('error') ? body['error'] : response.code)
96
- end
97
- body
98
- rescue JSON::ParserError
99
- if response.code.to_i == 404
100
- # Handle HTML 404 responses on malformed record ID, emulating API's
101
- # JSON response.
102
- raise Errors::RequestError, "Invalid record identifier: #{@id}"
103
- else
104
- raise Errors::ResponseError
105
- end
106
- end
107
-
108
- ##
109
- # Gets hierarchy data about this and related records from
110
- # ancestor-self-siblings.json API method
111
- #
112
- # @note Proof of concept implementation for demo purposes.
113
- # @todo Refactor if functionality to be retained.
114
- def hierarchy(*args)
115
- args = [:self] if args.blank?
116
-
117
- data = {}
118
- args.each do |method|
119
- unless @hierarchy.key?(method)
120
- @hierarchy[method] = hierarchical_data(method).select do |_k, v|
121
- v.is_a?(Enumerable)
122
- end
76
+ # @see Requestable#parse_response
77
+ def parse_response(response, options = {})
78
+ super.tap do |body|
79
+ if (options[:ld] && !(200..299).include?(response.code.to_i)) || (!options[:ld] && !body[:success])
80
+ fail Errors::RequestError, (body.key?(:error) ? body[:error] : response.code)
123
81
  end
124
- data.merge!(@hierarchy[method])
125
82
  end
126
- data
127
- end
128
-
129
- def hierarchical_data(method = :self)
130
- request = Request.new(hierarchical_data_uri(method))
131
- response = request.execute
132
- body = JSON.parse(response.body)
133
- fail Errors::RequestError, body['message'] unless body['success']
134
- body
135
83
  rescue JSON::ParserError
136
84
  if response.code.to_i == 404
137
85
  # Handle HTML 404 responses on malformed record ID, emulating API's
138
86
  # JSON response.
139
87
  raise Errors::RequestError, "Invalid record identifier: #{@id}"
140
88
  else
141
- raise Errors::ResponseError
89
+ raise
142
90
  end
143
91
  end
144
92
 
145
- def hierarchical_data_uri(method = :self)
146
- uri = URI.parse(Europeana::API.url + "/record#{@id}/#{method}.json")
147
- uri.query = params_with_authentication.to_query
148
- uri
93
+ def hierarchy
94
+ @hierarchy ||= Hierarchy.new(id)
149
95
  end
150
96
  end
151
97
  end
@@ -0,0 +1,48 @@
1
+ module Europeana
2
+ module API
3
+ class Record
4
+ ##
5
+ # Retrieve record hierarchies over the Europeana API
6
+ class Hierarchy
7
+ autoload :AncestorSelfSiblings, 'europeana/api/record/hierarchy/ancestor_self_siblings'
8
+ autoload :Base, 'europeana/api/record/hierarchy/base'
9
+ autoload :Children, 'europeana/api/record/hierarchy/children'
10
+ autoload :FollowingSiblings, 'europeana/api/record/hierarchy/following_siblings'
11
+ autoload :Parent, 'europeana/api/record/hierarchy/parent'
12
+ autoload :PrecedingSiblings, 'europeana/api/record/hierarchy/preceding_siblings'
13
+ autoload :Self, 'europeana/api/record/hierarchy/self'
14
+
15
+ def initialize(id)
16
+ @id = id
17
+ end
18
+
19
+ # bad idea having a method named self, but this is just a minimal
20
+ # helper class, so going with it for consistency with the API
21
+ def self(params = {})
22
+ Self.new(@id, params).execute_request
23
+ end
24
+
25
+ def parent(params = {})
26
+ Parent.new(@id, params).execute_request
27
+ end
28
+
29
+ def children(params = {})
30
+ Children.new(@id, params).execute_request
31
+ end
32
+
33
+ def preceding_siblings(params = {})
34
+ PrecedingSiblings.new(@id, params).execute_request
35
+ end
36
+ alias_method :preceeding_siblings, :preceding_siblings
37
+
38
+ def following_siblings(params = {})
39
+ FollowingSiblings.new(@id, params).execute_request
40
+ end
41
+
42
+ def ancestor_self_siblings(params = {})
43
+ AncestorSelfSiblings.new(@id, params).execute_request
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,12 @@
1
+ module Europeana
2
+ module API
3
+ class Record
4
+ class Hierarchy
5
+ ##
6
+ # Retrieve record full(ish) hierarchy data over the Europeana API
7
+ class AncestorSelfSiblings < Base
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,32 @@
1
+ module Europeana
2
+ module API
3
+ class Record
4
+ class Hierarchy
5
+ ##
6
+ # Base class for common heirarchy API behaviour
7
+ class Base
8
+ include Requestable
9
+
10
+ attr_accessor :params
11
+
12
+ def initialize(id, params = {})
13
+ @id = id
14
+ @params = params
15
+ end
16
+
17
+ def parse_response(response, options = {})
18
+ super.slice(:self, :children, :parent, 'preceeding-siblings', 'following-siblings', 'ancestors')
19
+ end
20
+
21
+ def request_url(_options = {})
22
+ Europeana::API.url + "/record#{@id}/#{api_method}.json"
23
+ end
24
+
25
+ def api_method
26
+ self.class.to_s.demodulize.underscore.dasherize
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,12 @@
1
+ module Europeana
2
+ module API
3
+ class Record
4
+ class Hierarchy
5
+ ##
6
+ # Retrieve record children hierarchy data over the Europeana API
7
+ class Children < Base
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ module Europeana
2
+ module API
3
+ class Record
4
+ class Hierarchy
5
+ ##
6
+ # Retrieve record following siblings hierarchy data over the Europeana API
7
+ class FollowingSiblings < Base
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ module Europeana
2
+ module API
3
+ class Record
4
+ class Hierarchy
5
+ ##
6
+ # Retrieve record parent hierarchy data over the Europeana API
7
+ class Parent < Base
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,15 @@
1
+ module Europeana
2
+ module API
3
+ class Record
4
+ class Hierarchy
5
+ ##
6
+ # Retrieve record preceding siblings hierarchy data over the Europeana API
7
+ class PrecedingSiblings < Base
8
+ def api_method
9
+ 'preceeding-siblings' # mis-spelt on the API
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,12 @@
1
+ module Europeana
2
+ module API
3
+ class Record
4
+ class Hierarchy
5
+ ##
6
+ # Retrieve record self hierarchy data over the Europeana API
7
+ class Self < Base
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,104 @@
1
+ module Europeana
2
+ module API
3
+ ##
4
+ # Mixin for classes that need to make Europeana API requests
5
+ #
6
+ # Class needs to implement {#request_url}
7
+ module Requestable
8
+ ##
9
+ # Request-specific params, to be overriden in including class
10
+ #
11
+ # @return [Hash]
12
+ def params
13
+ {}
14
+ end
15
+
16
+ ##
17
+ # Query params with API key added
18
+ #
19
+ # @return [Hash]
20
+ def params_with_authentication
21
+ return params if params.key?(:wskey) && params[:wskey].present?
22
+ unless Europeana::API.api_key.present?
23
+ fail Europeana::API::Errors::MissingAPIKeyError
24
+ end
25
+ params.merge(wskey: Europeana::API.api_key)
26
+ end
27
+
28
+ ##
29
+ # Execute the API request
30
+ #
31
+ # @param options [Hash] Options sent on to {#request_uri} and {#parse_response}
32
+ # @return (see #parse_response)
33
+ # @raise [Europeana::Errors::ResponseError] if API response could not be
34
+ # parsed as JSON
35
+ def execute_request(options = {})
36
+ uri = request_uri(options)
37
+ cache_response_body(uri) do
38
+ response = Request.new(uri).execute
39
+ parse_response(response, options)
40
+ end
41
+ rescue JSON::ParserError
42
+ raise Errors::ResponseError
43
+ end
44
+
45
+ def cache_key(uri)
46
+ "Europeana/API/#{uri}"
47
+ end
48
+
49
+ def cache_response_body(uri)
50
+ Europeana::API.cache_store.fetch(cache_key(uri), expires_in: Europeana::API.cache_expires_in) do
51
+ yield
52
+ end
53
+ end
54
+
55
+ ##
56
+ # Parses a JSON response from the API
57
+ #
58
+ # @param response (see Net::HTTP#request)
59
+ # @param options [Hash] Options used by including class's implementation
60
+ # of this method
61
+ # @return [HashWithIndifferentAccess] Parsed body of API response
62
+ def parse_response(response, _options = {})
63
+ JSON.parse(response.body).with_indifferent_access
64
+ end
65
+
66
+ ##
67
+ # URI query param string
68
+ #
69
+ # @return [String]
70
+ def request_uri_query
71
+ ''.tap do |uri_query|
72
+ params_with_authentication.each_pair do |name, value|
73
+ [value].flatten.each do |v|
74
+ uri_query << '&' unless uri_query.blank?
75
+ uri_query << CGI.escape(name.to_s) + '=' + CGI.escape(v.to_s)
76
+ end
77
+ end
78
+ end
79
+ end
80
+
81
+ ##
82
+ # Gets the URI for this request, with any query parameters
83
+ #
84
+ # @param [Hash{Symbol => Object}] options passed to {#request_url}
85
+ # @return [String]
86
+ def request_uri(options = {})
87
+ URI.parse(request_url(options)).tap do |uri|
88
+ uri.query = request_uri_query
89
+ end
90
+ end
91
+
92
+ ##
93
+ # URL for the request, without query params
94
+ #
95
+ # To be implemented by the including class
96
+ #
97
+ # @param options [Hash] Options used by implementation
98
+ # @return [String] Request URL
99
+ def request_url(_options = {})
100
+ fail NotImplementedError, "Requestable class #{self.class} does not implement #request_url"
101
+ end
102
+ end
103
+ end
104
+ end
@@ -1,5 +1,3 @@
1
- require 'active_support/core_ext/hash'
2
-
3
1
  module Europeana
4
2
  module API
5
3
  ##
@@ -7,6 +5,8 @@ module Europeana
7
5
  class Search
8
6
  autoload :Fields, 'europeana/api/search/fields'
9
7
 
8
+ include Requestable
9
+
10
10
  # Query params
11
11
  attr_accessor :params
12
12
 
@@ -17,6 +17,7 @@ module Europeana
17
17
  # @param [String] text Text to escape
18
18
  # @return [String] Escaped text
19
19
  def escape(text)
20
+ fail ArgumentError, "Expected String, got #{text.class}" unless text.is_a?(String)
20
21
  specials = %w<\\ + - & | ! ( ) { } [ ] ^ " ~ * ? : / >
21
22
  specials.each_with_object(text.dup) do |char, unescaped|
22
23
  unescaped.gsub!(char, '\\\\' + char) # prepends *one* backslash
@@ -31,56 +32,27 @@ module Europeana
31
32
  end
32
33
 
33
34
  ##
34
- # Sends the Search request to the API
35
+ # Base URL for a Search request
35
36
  #
36
- # @return [HashWithIndifferentAccess]
37
- # @raise [Europeana::Errors::ResponseError] if API response could not be
38
- # parsed as JSON
39
- # @raise [Europeana::Errors::RequestError] if API response has
40
- # `success:false`
41
- def execute
42
- request = Request.new(request_uri)
43
- response = request.execute
44
- body = JSON.parse(response.body)
45
- unless body['success']
46
- fail Errors::RequestError, (body.key?('error') ? body['error'] : response.code)
47
- end
48
- HashWithIndifferentAccess.new(body)
49
- rescue JSON::ParserError
50
- raise Errors::ResponseError
37
+ # @return [URI]
38
+ def request_url(_options = {})
39
+ Europeana::API.url + '/search.json'
51
40
  end
52
41
 
53
- ##
54
- # Returns query params with API key added
55
- #
56
- # @return [Hash]
57
- def params_with_authentication
58
- return params if params.key?(:wskey) && params[:wskey].present?
59
- unless Europeana::API.api_key.present?
60
- fail Errors::MissingAPIKeyError
61
- end
62
- params.merge(wskey: Europeana::API.api_key)
63
- end
42
+ alias_method :execute, :execute_request
64
43
 
65
44
  ##
66
- # Gets the URI for this Search request with parameters
45
+ # Examines the `success` and `error` fields of the response for failure
67
46
  #
68
- # @return [URI]
69
- def request_uri
70
- uri = URI.parse(Europeana::API.url + '/search.json')
71
- uri.query = request_uri_query
72
- uri
73
- end
74
-
75
- def request_uri_query
76
- uri_query = ''
77
- params_with_authentication.each_pair do |name, value|
78
- [value].flatten.each do |v|
79
- uri_query << '&' unless uri_query.blank?
80
- uri_query << CGI.escape(name.to_s) + '=' + CGI.escape(v.to_s)
47
+ # @raise [Europeana::Errors::RequestError] if API response has
48
+ # `success:false`
49
+ # @see Requestable#parse_response
50
+ def parse_response(response, _options = {})
51
+ super.tap do |body|
52
+ unless body[:success]
53
+ fail Errors::RequestError, (body.key?(:error) ? body[:error] : response.code)
81
54
  end
82
55
  end
83
- uri_query
84
56
  end
85
57
  end
86
58
  end
@@ -2,6 +2,6 @@ module Europeana
2
2
  ##
3
3
  # Sets the *gem* version (not the *API* version)
4
4
  module API
5
- VERSION = '0.3.6'
5
+ VERSION = '0.4.1'
6
6
  end
7
7
  end
@@ -0,0 +1,15 @@
1
+ RSpec.describe Europeana::API::Record::Hierarchy do
2
+ let(:record_id) { '/abc/1234' }
3
+ let(:params) { { callback: 'doSomething();' } }
4
+
5
+ subject { described_class.new(record_id) }
6
+
7
+ %w(self parent children).each do |relation|
8
+ describe "##{relation}" do
9
+ it "should retrieve #{relation} hierarchy data from the API" do
10
+ subject.send(relation)
11
+ expect(a_request(:get, %r{www.europeana.eu/api/v2/record#{record_id}/#{relation}.json})).to have_been_made.once
12
+ end
13
+ end
14
+ end
15
+ end
@@ -1,133 +1,133 @@
1
- require 'spec_helper'
1
+ RSpec.describe Europeana::API::Record do
2
+ let(:api_key) { 'xyz' }
3
+ let(:record_id) { '/abc/1234' }
4
+ let(:params) { { callback: 'doSomething();' } }
2
5
 
3
- module Europeana
4
- module API
5
- describe Record do
6
- let(:api_key) { 'xyz' }
7
- let(:record_id) { '/abc/1234' }
8
- let(:params) { { callback: 'doSomething();' } }
6
+ before do
7
+ Europeana::API.api_key = api_key
8
+ end
9
9
 
10
- before do
11
- Europeana::API.api_key = api_key
10
+ describe '#new' do
11
+ context 'without record ID' do
12
+ it 'raises error' do
13
+ expect { subject }.to raise_error(ArgumentError)
12
14
  end
15
+ end
13
16
 
14
- describe "#new" do
15
- context "without record ID" do
16
- it "raises error" do
17
- expect { subject }.to raise_error(ArgumentError)
18
- end
19
- end
20
-
21
- context "with record ID" do
22
- context "without params" do
23
- subject { described_class.new(record_id) }
24
-
25
- it "should not raise error" do
26
- expect { subject }.to_not raise_error
27
- end
17
+ context 'with record ID' do
18
+ context 'without params' do
19
+ subject { described_class.new(record_id) }
28
20
 
29
- it "sets id attribute" do
30
- expect(subject.instance_variable_get(:@id)).to eq(record_id)
31
- end
32
- end
21
+ it 'should not raise error' do
22
+ expect { subject }.to_not raise_error
23
+ end
33
24
 
34
- context "with params" do
35
- subject { described_class.new(record_id, params) }
25
+ it 'sets id attribute' do
26
+ expect(subject.instance_variable_get(:@id)).to eq(record_id)
27
+ end
28
+ end
36
29
 
37
- it "should not raise error" do
38
- expect { subject }.to_not raise_error
39
- end
30
+ context 'with params' do
31
+ subject { described_class.new(record_id, params) }
40
32
 
41
- it "sets params attribute" do
42
- expect(subject.instance_variable_get(:@params)).to eq(params)
43
- end
44
- end
33
+ it 'should not raise error' do
34
+ expect { subject }.to_not raise_error
45
35
  end
46
- end
47
36
 
48
- describe "#id" do
49
- subject { described_class.new(record_id) }
50
- it "gets id attribute" do
51
- expect(subject.id).to eq(subject.instance_variable_get(:@id))
37
+ it 'sets params attribute' do
38
+ expect(subject.instance_variable_get(:@params)).to eq(params)
52
39
  end
53
40
  end
41
+ end
42
+ end
54
43
 
55
- describe "#id=" do
56
- subject { described_class.new(record_id) }
44
+ describe '#id' do
45
+ subject { described_class.new(record_id) }
46
+ it 'gets id attribute' do
47
+ expect(subject.id).to eq(subject.instance_variable_get(:@id))
48
+ end
49
+ end
57
50
 
58
- context "with valid ID" do
59
- it "sets id attribute" do
60
- subject.id = "/xyz/5678"
61
- expect(subject.instance_variable_get(:@id)).to eq("/xyz/5678")
62
- end
63
- end
51
+ describe '#id=' do
52
+ subject { described_class.new(record_id) }
64
53
 
65
- context "invalid ID" do
66
- it "raises error" do
67
- expect { subject.id = "invalid" }.to raise_error('Invalid Europeana record ID: "invalid"')
68
- end
69
- end
54
+ context 'with valid ID' do
55
+ it 'sets id attribute' do
56
+ subject.id = '/xyz/5678'
57
+ expect(subject.instance_variable_get(:@id)).to eq('/xyz/5678')
70
58
  end
59
+ end
71
60
 
72
- describe "#params" do
73
- subject { described_class.new(record_id, params) }
74
- it "gets params attribute" do
75
- expect(subject.params).to eq(subject.instance_variable_get(:@params))
76
- end
61
+ context 'invalid ID' do
62
+ it 'raises error' do
63
+ expect { subject.id = 'invalid' }.to raise_error('Invalid Europeana record ID: "invalid"')
77
64
  end
65
+ end
66
+ end
78
67
 
79
- describe "#params=" do
80
- subject { described_class.new(record_id, {}) }
68
+ describe '#params' do
69
+ subject { described_class.new(record_id, params) }
70
+ it 'gets params attribute' do
71
+ expect(subject.params).to eq(subject.instance_variable_get(:@params))
72
+ end
73
+ end
81
74
 
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
75
+ describe '#params=' do
76
+ subject { described_class.new(record_id, {}) }
88
77
 
89
- it "validates param names" do
90
- expect { subject.params = { :invalid => "parameter" } }.to raise_error(/Unknown key: :?invalid/)
91
- end
78
+ context 'valid params' do
79
+ it 'sets params attribute' do
80
+ subject.params = params
81
+ expect(subject.instance_variable_get(:@params)).to eq(params)
92
82
  end
83
+ end
93
84
 
94
- describe "#params_with_authentication" do
95
- subject { described_class.new(record_id, params) }
85
+ it 'validates param names' do
86
+ expect { subject.params = { invalid: 'parameter' } }.to raise_error(/Unknown key: :?invalid/)
87
+ end
88
+ end
96
89
 
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
90
+ describe '#params_with_authentication' do
91
+ subject { described_class.new(record_id, params) }
102
92
 
103
- context "without API key" do
104
- it "raises an error" do
105
- Europeana::API.api_key = nil
106
- expect { subject.params_with_authentication }.to raise_error(Europeana::API::Errors::MissingAPIKeyError)
107
- end
108
- end
93
+ context 'with API key' do
94
+ it 'adds API key to params' do
95
+ expect(subject.params_with_authentication).to eq(params.merge(wskey: api_key))
109
96
  end
97
+ end
110
98
 
111
- describe "#request_uri" do
112
- subject { described_class.new(record_id, params) }
99
+ context 'without API key' do
100
+ it 'raises an error' do
101
+ Europeana::API.api_key = nil
102
+ expect { subject.params_with_authentication }.to raise_error(Europeana::API::Errors::MissingAPIKeyError)
103
+ end
104
+ end
105
+ end
113
106
 
114
- it "returns a URI" do
115
- expect(subject.request_uri).to be_a(URI)
116
- end
107
+ describe '#request_uri' do
108
+ subject { described_class.new(record_id, params) }
117
109
 
118
- it "includes the record ID" do
119
- expect(subject.request_uri.to_s).to include(record_id)
120
- end
110
+ it 'returns a URI' do
111
+ expect(subject.request_uri).to be_a(URI)
112
+ end
121
113
 
122
- it "includes the query params" do
123
- expect(subject.request_uri.to_s).to include(params.to_query)
124
- end
125
- end
114
+ it 'includes the record ID' do
115
+ expect(subject.request_uri.to_s).to include(record_id)
116
+ end
126
117
 
127
- describe "#get" do
128
- subject { described_class.new(record_id, params).get }
129
- it_behaves_like "record request"
130
- end
118
+ it 'includes the query params' do
119
+ expect(subject.request_uri.to_s).to include(params.to_query)
131
120
  end
132
121
  end
122
+
123
+ describe '#get' do
124
+ subject { described_class.new(record_id, params).get }
125
+ it_behaves_like 'record request'
126
+ end
127
+
128
+ describe '#hierarchy' do
129
+ let(:record) { described_class.new(record_id, params) }
130
+ subject { record.hierarchy }
131
+ it { is_expected.to be_a(Europeana::API::Record::Hierarchy) }
132
+ end
133
133
  end
data/spec/spec_helper.rb CHANGED
@@ -2,7 +2,7 @@ require 'coveralls'
2
2
  require 'europeana/api'
3
3
  require 'webmock/rspec'
4
4
 
5
- Dir["./spec/support/**/*.rb"].each { |f| require f }
5
+ Dir['./spec/support/**/*.rb'].each { |f| require f }
6
6
 
7
7
  Coveralls.wear! unless Coveralls.will_run?.nil?
8
8
 
@@ -1,31 +1,26 @@
1
- shared_examples "record request" do
1
+ shared_examples 'record request' do
2
+ let(:api_record_endpoint) { %r{www.europeana.eu/api/v2/record#{record_id}\.json} }
3
+ let(:api_key) { 'xyz' }
4
+ let(:record_id) { '/abc/1234' }
5
+ let(:params) { { callback: 'doSomething();' } }
6
+
2
7
  before(:each) do
3
- stub_request(:get, /www.europeana.eu\/api\/v2\/record#{record_id}\.json/).
4
- to_return(body: '{"success":true}')
8
+ stub_request(:get, api_record_endpoint).to_return(body: '{"success":true}')
9
+ Europeana::API.api_key = api_key
5
10
  end
6
11
 
7
- it_behaves_like "API request"
8
-
9
- context "with API key" do
10
- before(:each) do
11
- Europeana::API.api_key = api_key
12
- end
13
-
14
- let(:api_key) { 'xyz' }
15
- let(:record_id) { '/abc/1234' }
16
- let(:params) { { callback: 'doSomething();' } }
12
+ it_behaves_like 'API request'
17
13
 
18
- it "sends a Record request to the API" do
19
- subject
20
- expect(a_request(:get, /www.europeana.eu\/api\/v2\/record#{record_id}\.json/)).to have_been_made.once
21
- end
14
+ it 'sends a Record request to the API' do
15
+ subject
16
+ expect(a_request(:get, api_record_endpoint)).to have_been_made.once
17
+ end
22
18
 
23
- context "when record ID is invalid" do
24
- it "raises RequestError from HTML 404 response" do
25
- stub_request(:get, /www.europeana.eu\/api\/v2\/record#{record_id}\.json/).
26
- to_return(body: '<html></html>', headers: { 'Content-Type' => 'text/html' }, status: 404)
27
- expect { subject }.to raise_error(Europeana::API::Errors::RequestError, "Invalid record identifier: #{record_id}")
28
- end
19
+ context 'when record ID is invalid' do
20
+ it 'raises RequestError from HTML 404 response' do
21
+ stub_request(:get, api_record_endpoint).
22
+ to_return(body: '<html></html>', headers: { 'Content-Type' => 'text/html' }, status: 404)
23
+ expect { subject }.to raise_error(Europeana::API::Errors::RequestError, "Invalid record identifier: #{record_id}")
29
24
  end
30
25
  end
31
26
  end
@@ -0,0 +1,14 @@
1
+ RSpec.configure do |config|
2
+ config.before do
3
+ Europeana::API.api_key = 'xyz'
4
+
5
+ stub_request(:get, %r{www.europeana.eu/api/v2/record/[^/]+/[^/]+/self\.json}).
6
+ to_return(body: lambda { |_| '{"success":true, "self":{"id":"' + record_id + '", "childrenCount":0, "hasChildren":false}}' })
7
+
8
+ stub_request(:get, %r{www.europeana.eu/api/v2/record/[^/]+/[^/]+/parent\.json}).
9
+ to_return(body: lambda { |_| '{"success":true, "self":{"id":"' + record_id + '", "childrenCount":5, "hasChildren":false}, "parent":{}}' })
10
+
11
+ stub_request(:get, %r{www.europeana.eu/api/v2/record/[^/]+/[^/]+/children\.json}).
12
+ to_return(body: lambda { |_| '{"success":true, "self":{"id":"' + record_id + '", "childrenCount":5, "hasChildren":false}, "children":[]}' })
13
+ end
14
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: europeana-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.6
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Richard Doe
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-09-23 00:00:00.000000000 Z
11
+ date: 2015-11-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -115,11 +115,21 @@ files:
115
115
  - lib/europeana/api.rb
116
116
  - lib/europeana/api/errors.rb
117
117
  - lib/europeana/api/record.rb
118
+ - lib/europeana/api/record/hierarchy.rb
119
+ - lib/europeana/api/record/hierarchy/ancestor_self_siblings.rb
120
+ - lib/europeana/api/record/hierarchy/base.rb
121
+ - lib/europeana/api/record/hierarchy/children.rb
122
+ - lib/europeana/api/record/hierarchy/following_siblings.rb
123
+ - lib/europeana/api/record/hierarchy/parent.rb
124
+ - lib/europeana/api/record/hierarchy/preceding_siblings.rb
125
+ - lib/europeana/api/record/hierarchy/self.rb
118
126
  - lib/europeana/api/request.rb
127
+ - lib/europeana/api/requestable.rb
119
128
  - lib/europeana/api/search.rb
120
129
  - lib/europeana/api/search/fields.rb
121
130
  - lib/europeana/api/version.rb
122
131
  - spec/europeana/api/errors_spec.rb
132
+ - spec/europeana/api/record/hierarchy_spec.rb
123
133
  - spec/europeana/api/record_spec.rb
124
134
  - spec/europeana/api/search_spec.rb
125
135
  - spec/europeana/api_spec.rb
@@ -127,6 +137,7 @@ files:
127
137
  - spec/support/shared_examples/api_request.rb
128
138
  - spec/support/shared_examples/record_request.rb
129
139
  - spec/support/shared_examples/search_request.rb
140
+ - spec/support/webmock.rb
130
141
  homepage: https://github.com/europeana/europeana-api-client-ruby
131
142
  licenses:
132
143
  - EUPL V.1.1
@@ -139,7 +150,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
139
150
  requirements:
140
151
  - - ">="
141
152
  - !ruby/object:Gem::Version
142
- version: 1.9.2
153
+ version: 2.0.0
143
154
  required_rubygems_version: !ruby/object:Gem::Requirement
144
155
  requirements:
145
156
  - - ">="
@@ -153,6 +164,7 @@ specification_version: 4
153
164
  summary: Ruby client library for the Europeana API
154
165
  test_files:
155
166
  - spec/europeana/api/errors_spec.rb
167
+ - spec/europeana/api/record/hierarchy_spec.rb
156
168
  - spec/europeana/api/record_spec.rb
157
169
  - spec/europeana/api/search_spec.rb
158
170
  - spec/europeana/api_spec.rb
@@ -160,3 +172,4 @@ test_files:
160
172
  - spec/support/shared_examples/api_request.rb
161
173
  - spec/support/shared_examples/record_request.rb
162
174
  - spec/support/shared_examples/search_request.rb
175
+ - spec/support/webmock.rb