europeana-api 0.3.6 → 0.4.1

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