hydra-remote_identifier 0.0.3 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +7 -0
- data/README.md +14 -7
- data/hydra-remote_identifier.gemspec +1 -2
- data/lib/hydra/remote_identifier.rb +19 -35
- data/lib/hydra/remote_identifier/configuration.rb +46 -0
- data/lib/hydra/remote_identifier/mapper.rb +12 -12
- data/lib/hydra/remote_identifier/registration.rb +21 -5
- data/lib/hydra/remote_identifier/remote_services.rb +1 -5
- data/lib/hydra/remote_identifier/remote_services/doi.rb +51 -0
- data/lib/hydra/remote_identifier/version.rb +1 -1
- data/spec/fixtures/cassettes/doi-create.yml +47 -0
- data/spec/fixtures/cassettes/doi-integration.yml +47 -0
- data/spec/lib/hydra/remote_identifier/configuration_spec.rb +48 -0
- data/spec/lib/hydra/remote_identifier/mapper_spec.rb +106 -0
- data/spec/lib/hydra/remote_identifier/registration_spec.rb +4 -7
- data/spec/lib/hydra/remote_identifier/remote_service_spec.rb +6 -5
- data/spec/lib/hydra/remote_identifier/remote_services/doi_spec.rb +38 -0
- data/spec/lib/hydra/remote_identifier_spec.rb +43 -44
- data/spec/spec_helper.rb +15 -0
- metadata +34 -58
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c555e2e358d784219f8aeae86457d9a456410470
|
4
|
+
data.tar.gz: 1e6e8f346332a2692a6c04001837cb18ca3ef6db
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8ce31c0525b6c307bcebc30f9a227a87d047ad76da1a872c3a5454b900d2081f5aeedd67a0126bed876cba6337d0ec1efee78086f487c5a9377198b7fd68bd54
|
7
|
+
data.tar.gz: 8379665c7d8f1a022a3e09bf3f7ef4ed4fa126caebda959325f2585c437e3e4eb68ddb4c149e004f8c7b813997f404ee670ee56fa120d4e1b9b41e4f8bfc0c79
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -19,11 +19,18 @@ Or install it yourself as:
|
|
19
19
|
|
20
20
|
## Usage
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
Hydra::RemoteIdentifier.
|
26
|
-
|
27
|
-
|
28
|
-
|
22
|
+
Configure your remote identifiers with credentials and what have you:
|
23
|
+
|
24
|
+
doi_credentials = Psych.load('/path/to/doi_credentials.yml')
|
25
|
+
Hydra::RemoteIdentifier.configure do |config|
|
26
|
+
config.configure_remote_service(:doi, doi_credentials) do |doi|
|
27
|
+
doi.register(target_class) do |map|
|
28
|
+
map.target :url
|
29
|
+
map.creator :creator
|
30
|
+
map.title :title
|
31
|
+
map.publisher :publisher
|
32
|
+
map.publicationyear :publicationyear
|
33
|
+
map.set_identifier(:set_identifier=)
|
34
|
+
end
|
35
|
+
end
|
29
36
|
end
|
@@ -19,10 +19,9 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
21
|
spec.add_dependency 'activesupport', '>= 3.2.13', '< 5.0'
|
22
|
+
spec.add_dependency 'rest-client', '~> 1.6.7'
|
22
23
|
|
23
24
|
spec.add_development_dependency "bundler", "~> 1.3"
|
24
25
|
spec.add_development_dependency "rake"
|
25
26
|
spec.add_development_dependency 'rspec'
|
26
|
-
spec.add_development_dependency 'yard'
|
27
|
-
spec.add_development_dependency 'redcarpet'
|
28
27
|
end
|
@@ -1,50 +1,34 @@
|
|
1
1
|
require "hydra/remote_identifier/version"
|
2
|
+
require 'hydra/remote_identifier/configuration'
|
2
3
|
require 'hydra/remote_identifier/registration'
|
3
4
|
require 'hydra/remote_identifier/remote_service'
|
4
|
-
require 'hydra/remote_identifier/remote_services'
|
5
5
|
|
6
6
|
module Hydra::RemoteIdentifier
|
7
7
|
|
8
8
|
class << self
|
9
9
|
|
10
|
-
#
|
11
|
-
#
|
12
|
-
# :target_classes
|
10
|
+
# Used for configuring available RemoteService and any additional
|
11
|
+
# initialization requirements for those RemoteServices (i.e. credentials)
|
13
12
|
#
|
14
13
|
# @example
|
15
|
-
# Hydra::RemoteIdentifier.
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
14
|
+
# Hydra::RemoteIdentifier.configure do |config|
|
15
|
+
# config.configure_remote_service(:doi, doi_credentials) do |doi|
|
16
|
+
# doi.register(target_class) do |map|
|
17
|
+
# map.target :url
|
18
|
+
# map.creator :creator
|
19
|
+
# map.title :title
|
20
|
+
# map.publisher :publisher
|
21
|
+
# map.publicationyear :publicationyear
|
22
|
+
# map.set_identifier(:set_identifier=)
|
23
|
+
# end
|
24
|
+
# end
|
19
25
|
# end
|
20
26
|
#
|
21
|
-
# @
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
# :remote_service as well as what the callback for what the
|
27
|
-
# :remote_resource should do (see Mapper::Wrapper)
|
28
|
-
def register(remote_service_name, *target_classes, &map)
|
29
|
-
Array(target_classes).flatten.compact.each do |target_class|
|
30
|
-
Registration.new(remote_service(remote_service_name), target_class, &map)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
|
35
|
-
# Given a string retrieve an instance of the corresponding RemoteService.
|
36
|
-
# @param string [#to_s]
|
37
|
-
# @return [RemoteService]
|
38
|
-
def remote_service(string)
|
39
|
-
namespace_for_lookup = RemoteServices
|
40
|
-
remote_service_class_name = string.to_s.gsub(/(?:^|_)([a-z])/) { $1.upcase }
|
41
|
-
if namespace_for_lookup.const_defined?(remote_service_class_name)
|
42
|
-
namespace_for_lookup.const_get(remote_service_class_name).new
|
43
|
-
else
|
44
|
-
raise NotImplementedError.new(
|
45
|
-
"Unable to find #{self} remote_service '#{string}'. Consider creating #{namespace_for_lookup}::#{remote_service_class_name}"
|
46
|
-
)
|
47
|
-
end
|
27
|
+
# @yieldparam config [Configuration]
|
28
|
+
attr_accessor :configuration
|
29
|
+
def configure
|
30
|
+
self.configuration ||= Configuration.new
|
31
|
+
yield(configuration)
|
48
32
|
end
|
49
33
|
|
50
34
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require File.expand_path('../remote_services', __FILE__)
|
2
|
+
|
3
|
+
module Hydra::RemoteIdentifier
|
4
|
+
|
5
|
+
# Configuration is responsible for exposing the available RemoteServices
|
6
|
+
# and configuring those RemoteServices.
|
7
|
+
class Configuration
|
8
|
+
|
9
|
+
def initialize(options = {})
|
10
|
+
@remote_service_namespace_container = options.fetch(:remote_service_namespace_container, Hydra::RemoteIdentifier::RemoteServices)
|
11
|
+
@remote_services = {}
|
12
|
+
end
|
13
|
+
attr_reader :remote_service_namespace_container
|
14
|
+
private :remote_service_namespace_container
|
15
|
+
attr_reader :remote_services
|
16
|
+
|
17
|
+
def find_remote_service(service_name)
|
18
|
+
remote_services.fetch(service_name, remote_service_class_lookup(service_name).new)
|
19
|
+
end
|
20
|
+
|
21
|
+
def remote_service(service_name, *args, &block)
|
22
|
+
remote_service_class_lookup(service_name).configure(*args, &block)
|
23
|
+
end
|
24
|
+
|
25
|
+
def configure_remote_service(service_name, *args, &block)
|
26
|
+
remote_service = remote_service_class_lookup(service_name).new(*args)
|
27
|
+
remote_services[service_name]
|
28
|
+
yield(Registration.new(remote_service))
|
29
|
+
remote_service
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def remote_service_class_lookup(string)
|
35
|
+
remote_service_class_name = string.to_s.gsub(/(?:^|_)([a-z])/) { $1.upcase }
|
36
|
+
if remote_service_namespace_container.const_defined?(remote_service_class_name)
|
37
|
+
remote_service_namespace_container.const_get(remote_service_class_name)
|
38
|
+
else
|
39
|
+
raise NotImplementedError.new(
|
40
|
+
"Unable to find #{self} remote_service '#{string}'. Consider creating #{remote_service_namespace_container}::#{remote_service_class_name}"
|
41
|
+
)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
@@ -2,10 +2,19 @@ require File.expand_path('../exceptions', __FILE__)
|
|
2
2
|
|
3
3
|
module Hydra::RemoteIdentifier
|
4
4
|
|
5
|
-
#
|
6
|
-
#
|
5
|
+
# The Mapper is responsible for transforming a target, via a Map, into an
|
6
|
+
# acceptable format for a Minter
|
7
7
|
class Mapper
|
8
8
|
|
9
|
+
attr_reader :map
|
10
|
+
def initialize(service_class, map_builder = Map, &mapping_block)
|
11
|
+
@map = map_builder.new(service_class, &mapping_block)
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(target, wrapper_builder = Wrapper)
|
15
|
+
wrapper_builder.new(map, target)
|
16
|
+
end
|
17
|
+
|
9
18
|
# The Wrapper provides the getting and setting behavior for a target based on a Map
|
10
19
|
class Wrapper
|
11
20
|
attr_reader :map, :target
|
@@ -33,7 +42,7 @@ module Hydra::RemoteIdentifier
|
|
33
42
|
target.send(setter, value)
|
34
43
|
elsif setter.is_a?(Hash)
|
35
44
|
datastream = setter.fetch(:at)
|
36
|
-
field = setter.fetch(:in
|
45
|
+
field = setter.fetch(:in)
|
37
46
|
target.datastreams["#{datastream}"].send("#{field}=", value)
|
38
47
|
end
|
39
48
|
end
|
@@ -83,15 +92,6 @@ module Hydra::RemoteIdentifier
|
|
83
92
|
end
|
84
93
|
end
|
85
94
|
|
86
|
-
attr_reader :map
|
87
|
-
def initialize(service_class, map_builder = Map, &mapping_block)
|
88
|
-
@map = map_builder.new(service_class, &mapping_block)
|
89
|
-
end
|
90
|
-
|
91
|
-
def call(target, wrapper_builder = Wrapper)
|
92
|
-
wrapper_builder.new(map, target)
|
93
|
-
end
|
94
|
-
|
95
95
|
end
|
96
96
|
|
97
97
|
end
|
@@ -3,16 +3,32 @@ require File.expand_path('../minting_coordinator', __FILE__)
|
|
3
3
|
|
4
4
|
module Hydra::RemoteIdentifier
|
5
5
|
|
6
|
-
# The Registration is responsible for connecting a RemoteService
|
6
|
+
# The Registration is responsible for connecting a RemoteService and a Target
|
7
7
|
# to a particular Map
|
8
8
|
class Registration
|
9
|
-
|
9
|
+
attr_reader :remote_service, :minting_coordinator
|
10
|
+
def initialize(remote_service, minting_coordinator = MintingCoordinator, &map)
|
11
|
+
@remote_service = remote_service
|
12
|
+
@minting_coordinator = minting_coordinator
|
13
|
+
end
|
14
|
+
|
15
|
+
def register(*target_classes, &map)
|
10
16
|
if map.nil?
|
11
|
-
raise RuntimeError, "You attempted to register the remote service #{
|
17
|
+
raise RuntimeError, "You attempted to register the remote service #{remote_service} for #{target_classes} without a map"
|
18
|
+
end
|
19
|
+
Array(target_classes).flatten.compact.each {|target_class|
|
20
|
+
register_target(target_class, &map)
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def register_target(target_class, &map)
|
27
|
+
unless target_class.respond_to?(:registered_remote_identifier_minters)
|
28
|
+
target_class.class_attribute :registered_remote_identifier_minters
|
12
29
|
end
|
13
|
-
target_class.class_attribute :registered_remote_identifier_minters unless target_class.respond_to?(:registered_remote_identifier_minters)
|
14
30
|
target_class.registered_remote_identifier_minters ||= []
|
15
|
-
target_class.registered_remote_identifier_minters += [minting_coordinator.new(
|
31
|
+
target_class.registered_remote_identifier_minters += [minting_coordinator.new(remote_service, &map)]
|
16
32
|
end
|
17
33
|
end
|
18
34
|
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'rest_client'
|
3
|
+
require 'hydra/remote_identifier/remote_service'
|
4
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
5
|
+
|
6
|
+
module Hydra::RemoteIdentifier
|
7
|
+
module RemoteServices
|
8
|
+
class Doi < Hydra::RemoteIdentifier::RemoteService
|
9
|
+
|
10
|
+
attr_reader :uri
|
11
|
+
def initialize(configuration = {})
|
12
|
+
username = configuration.fetch(:username)
|
13
|
+
password = configuration.fetch(:password)
|
14
|
+
shoulder = configuration.fetch(:shoulder)
|
15
|
+
url = configuration.fetch(:url)
|
16
|
+
|
17
|
+
# This is specific for the creation of DOIs
|
18
|
+
@uri = URI.parse(File.join(url, 'shoulder', shoulder))
|
19
|
+
@uri.user = username
|
20
|
+
@uri.password = password
|
21
|
+
end
|
22
|
+
|
23
|
+
REQUIRED_ATTRIBUTES = ['target', 'creator', 'title', 'publisher', 'publicationyear' ].freeze
|
24
|
+
def valid_attribute?(attribute_name)
|
25
|
+
REQUIRED_ATTRIBUTES.include?(attribute_name.to_s)
|
26
|
+
end
|
27
|
+
|
28
|
+
def call(payload)
|
29
|
+
request(data_for_create(payload.with_indifferent_access))
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def request(data)
|
35
|
+
response = RestClient.post(uri.to_s, data, content_type: 'text/plain')
|
36
|
+
matched_data = /\Asuccess:(.*)(?<doi>doi:[^\|]*)(.*)\Z/.match(response.body)
|
37
|
+
matched_data[:doi].strip
|
38
|
+
end
|
39
|
+
|
40
|
+
def data_for_create(payload)
|
41
|
+
[
|
42
|
+
"_target: #{payload.fetch(:target)}",
|
43
|
+
"datacite.creator: #{payload.fetch(:creator)}",
|
44
|
+
"datacite.title: #{payload.fetch(:title)}",
|
45
|
+
"datacite.publisher: #{payload.fetch(:publisher)}",
|
46
|
+
"datacite.publicationyear: #{payload.fetch(:publicationyear)}"
|
47
|
+
].join("\n")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: post
|
5
|
+
uri: https://apitest:apitest@n2t.net/ezid/shoulder/doi:10.5072/FK2
|
6
|
+
body:
|
7
|
+
encoding: UTF-8
|
8
|
+
string: |-
|
9
|
+
_target: http://google.com
|
10
|
+
datacite.creator: Jeremy Friesen
|
11
|
+
datacite.title: My Article
|
12
|
+
datacite.publisher: Me Myself and I
|
13
|
+
datacite.publicationyear: 2013
|
14
|
+
headers:
|
15
|
+
Accept:
|
16
|
+
- '*/*; q=0.5, application/xml'
|
17
|
+
Accept-Encoding:
|
18
|
+
- gzip, deflate
|
19
|
+
Content-Type:
|
20
|
+
- text/plain
|
21
|
+
Content-Length:
|
22
|
+
- '153'
|
23
|
+
User-Agent:
|
24
|
+
- Ruby
|
25
|
+
response:
|
26
|
+
status:
|
27
|
+
code: 201
|
28
|
+
message: CREATED
|
29
|
+
headers:
|
30
|
+
Date:
|
31
|
+
- Thu, 03 Oct 2013 17:50:51 GMT
|
32
|
+
Server:
|
33
|
+
- Apache/2.2.17 (Unix) DAV/2 mod_wsgi/3.3 Python/2.7 mod_ssl/2.2.17 OpenSSL/0.9.8o
|
34
|
+
Vary:
|
35
|
+
- Cookie
|
36
|
+
Set-Cookie:
|
37
|
+
- sessionid=649cfcff023c40d4c8f1420673837ae6; Path=/ezid/
|
38
|
+
Content-Length:
|
39
|
+
- '53'
|
40
|
+
Content-Type:
|
41
|
+
- text/plain; charset=UTF-8
|
42
|
+
body:
|
43
|
+
encoding: UTF-8
|
44
|
+
string: 'success: doi:10.5072/FK23J3QV8 | ark:/b5072/fk23j3qv8'
|
45
|
+
http_version:
|
46
|
+
recorded_at: Thu, 03 Oct 2013 17:50:54 GMT
|
47
|
+
recorded_with: VCR 2.6.0
|
@@ -0,0 +1,47 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: post
|
5
|
+
uri: https://apitest:apitest@n2t.net/ezid/shoulder/doi:10.5072/FK2
|
6
|
+
body:
|
7
|
+
encoding: UTF-8
|
8
|
+
string: |-
|
9
|
+
_target: http://google.com
|
10
|
+
datacite.creator: my creator
|
11
|
+
datacite.title: my title
|
12
|
+
datacite.publisher: my publisher
|
13
|
+
datacite.publicationyear: 2013
|
14
|
+
headers:
|
15
|
+
Accept:
|
16
|
+
- '*/*; q=0.5, application/xml'
|
17
|
+
Accept-Encoding:
|
18
|
+
- gzip, deflate
|
19
|
+
Content-Type:
|
20
|
+
- text/plain
|
21
|
+
Content-Length:
|
22
|
+
- '144'
|
23
|
+
User-Agent:
|
24
|
+
- Ruby
|
25
|
+
response:
|
26
|
+
status:
|
27
|
+
code: 201
|
28
|
+
message: CREATED
|
29
|
+
headers:
|
30
|
+
Date:
|
31
|
+
- Thu, 03 Oct 2013 19:10:22 GMT
|
32
|
+
Server:
|
33
|
+
- Apache/2.2.17 (Unix) DAV/2 mod_wsgi/3.3 Python/2.7 mod_ssl/2.2.17 OpenSSL/0.9.8o
|
34
|
+
Vary:
|
35
|
+
- Cookie
|
36
|
+
Set-Cookie:
|
37
|
+
- sessionid=995dadb966d7013e9251daf61b6122ba; Path=/ezid/
|
38
|
+
Content-Length:
|
39
|
+
- '53'
|
40
|
+
Content-Type:
|
41
|
+
- text/plain; charset=UTF-8
|
42
|
+
body:
|
43
|
+
encoding: UTF-8
|
44
|
+
string: 'success: doi:10.5072/FK2FT8XZZ | ark:/b5072/fk2ft8xzz'
|
45
|
+
http_version:
|
46
|
+
recorded_at: Thu, 03 Oct 2013 19:10:25 GMT
|
47
|
+
recorded_with: VCR 2.6.0
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require File.expand_path('../../../../../lib/hydra/remote_identifier/configuration', __FILE__)
|
2
|
+
|
3
|
+
module Hydra::RemoteIdentifier
|
4
|
+
|
5
|
+
describe Configuration do
|
6
|
+
around do |example|
|
7
|
+
module RemoteServices
|
8
|
+
class MyRemoteService
|
9
|
+
class << self
|
10
|
+
attr_reader :options
|
11
|
+
def configure(*args, &block)
|
12
|
+
@options = [args, block]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
example.run
|
18
|
+
RemoteServices.send(:remove_const, :MyRemoteService)
|
19
|
+
end
|
20
|
+
|
21
|
+
subject { Configuration.new }
|
22
|
+
|
23
|
+
context 'with a missing service' do
|
24
|
+
specify do
|
25
|
+
expect { subject.remote_service(:obviously_missing_service) }.to raise_error(NotImplementedError)
|
26
|
+
end
|
27
|
+
specify do
|
28
|
+
expect {
|
29
|
+
subject.find_remote_service(:obviously_missing_service)
|
30
|
+
}.to raise_error(NotImplementedError)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'with an existing service' do
|
35
|
+
let(:block) { lambda {} }
|
36
|
+
specify do
|
37
|
+
expect {
|
38
|
+
subject.remote_service(:my_remote_service, :arg, &block)
|
39
|
+
}.to change(RemoteServices::MyRemoteService, :options).from(nil).to([[:arg], block])
|
40
|
+
end
|
41
|
+
specify do
|
42
|
+
expect(subject.find_remote_service(:my_remote_service)).to be_an_instance_of(RemoteServices::MyRemoteService)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
@@ -47,5 +47,111 @@ module Hydra::RemoteIdentifier
|
|
47
47
|
}.to raise_error(InvalidServiceMapping)
|
48
48
|
end
|
49
49
|
end
|
50
|
+
|
51
|
+
describe Mapper::Wrapper do
|
52
|
+
subject { Mapper::Wrapper.new(map, target) }
|
53
|
+
|
54
|
+
context 'extract_payload' do
|
55
|
+
let(:target) { double(foo: :foo_value) }
|
56
|
+
describe 'with implicit getter' do
|
57
|
+
let(:map) { double(_getters: { bar: :foo } ) }
|
58
|
+
its(:extract_payload) { should == {bar: :foo_value} }
|
59
|
+
end
|
60
|
+
|
61
|
+
describe 'with lambda getter' do
|
62
|
+
let(:map) { double(_getters: { bar: lambda {|o| o.foo } } ) }
|
63
|
+
its(:extract_payload) { should == {bar: :foo_value} }
|
64
|
+
end
|
65
|
+
|
66
|
+
describe 'with implicit datastream getter' do
|
67
|
+
let(:target) {
|
68
|
+
double(datastreams: {'datastream' => double(foo: :foo_value)})
|
69
|
+
}
|
70
|
+
let(:map) {
|
71
|
+
double(_getters: { foo: { at: 'datastream' } } )
|
72
|
+
}
|
73
|
+
its(:extract_payload) { should == {foo: :foo_value} }
|
74
|
+
end
|
75
|
+
|
76
|
+
describe 'with explicit datastream getter' do
|
77
|
+
let(:target) {
|
78
|
+
double(datastreams: {'datastream' => double(blorg: :foo_value)})
|
79
|
+
}
|
80
|
+
let(:map) {
|
81
|
+
double(_getters: { foo: { at: 'datastream', in: :blorg } } )
|
82
|
+
}
|
83
|
+
its(:extract_payload) { should == {foo: :foo_value} }
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
context '#extract_payload' do
|
89
|
+
|
90
|
+
let(:target) { double(foo: :foo_value) }
|
91
|
+
describe 'with implicit getter' do
|
92
|
+
let(:map) { double(_getters: { bar: :foo } ) }
|
93
|
+
its(:extract_payload) { should == {bar: :foo_value} }
|
94
|
+
end
|
95
|
+
|
96
|
+
describe 'with lambda getter' do
|
97
|
+
let(:map) { double(_getters: { bar: lambda {|o| o.foo } } ) }
|
98
|
+
its(:extract_payload) { should == {bar: :foo_value} }
|
99
|
+
end
|
100
|
+
|
101
|
+
describe 'with implicit datastream getter' do
|
102
|
+
let(:target) {
|
103
|
+
double(datastreams: {'datastream' => double(foo: :foo_value)})
|
104
|
+
}
|
105
|
+
let(:map) {
|
106
|
+
double(_getters: { foo: { at: 'datastream' } } )
|
107
|
+
}
|
108
|
+
its(:extract_payload) { should == {foo: :foo_value} }
|
109
|
+
end
|
110
|
+
|
111
|
+
describe 'with explicit datastream getter' do
|
112
|
+
let(:target) {
|
113
|
+
double(datastreams: {'datastream' => double(blorg: :foo_value)})
|
114
|
+
}
|
115
|
+
let(:map) {
|
116
|
+
double(_getters: { foo: { at: 'datastream', in: :blorg } } )
|
117
|
+
}
|
118
|
+
its(:extract_payload) { should == {foo: :foo_value} }
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
context '#set_identifier' do
|
124
|
+
let(:target) { double }
|
125
|
+
describe 'with implicit setter' do
|
126
|
+
let(:map) { double(_setter: :bar) }
|
127
|
+
specify {
|
128
|
+
target.should_receive(:bar).with(:expected_identifier)
|
129
|
+
subject.set_identifier(:expected_identifier)
|
130
|
+
}
|
131
|
+
end
|
132
|
+
|
133
|
+
describe 'with lambda setter' do
|
134
|
+
let(:map) { double(_setter: lambda {|o, v| o.foo = v } ) }
|
135
|
+
specify {
|
136
|
+
target.should_receive(:foo=).with(:expected_identifier)
|
137
|
+
subject.set_identifier(:expected_identifier)
|
138
|
+
}
|
139
|
+
end
|
140
|
+
|
141
|
+
describe 'with explicit datastream getter' do
|
142
|
+
let(:target) { double(datastreams: datastreams ) }
|
143
|
+
let(:datastreams) { {'properties' => double } }
|
144
|
+
let(:map) {
|
145
|
+
double(_setter: { at: 'properties', in: :identifier } )
|
146
|
+
}
|
147
|
+
specify {
|
148
|
+
datastreams['properties'].should_receive(:identifier=).with(:expected_identifier)
|
149
|
+
subject.set_identifier(:expected_identifier)
|
150
|
+
}
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
50
156
|
end
|
51
157
|
end
|
@@ -5,21 +5,18 @@ module Hydra::RemoteIdentifier
|
|
5
5
|
let(:minting_coordinator) { double(new: :minting_coordinator) }
|
6
6
|
let(:target_class) { Class.new }
|
7
7
|
let(:map) { lambda {|m| m.title :title } }
|
8
|
+
subject { Registration.new(:my_remote_service, minting_coordinator) }
|
8
9
|
it 'requires a map' do
|
9
|
-
expect {
|
10
|
+
expect { subject.register(target_class) }.to raise_error(RuntimeError)
|
10
11
|
end
|
11
12
|
it 'adds a .registered_remote_identifier_minters method' do
|
12
13
|
expect {
|
13
|
-
|
14
|
+
subject.register(target_class, &map)
|
14
15
|
}.to change{ target_class.respond_to?(:registered_remote_identifier_minters) }.from(false).to(true)
|
15
16
|
end
|
16
17
|
it 'adds a .registered_remote_identifier_minters method' do
|
17
|
-
|
18
|
+
subject.register(target_class, &map)
|
18
19
|
expect(target_class.registered_remote_identifier_minters).to eq [:minting_coordinator]
|
19
20
|
end
|
20
|
-
|
21
|
-
it 'should yield a map' do
|
22
|
-
Registration.new(:my_remote_service, target_class, minting_coordinator, &map)
|
23
|
-
end
|
24
21
|
end
|
25
22
|
end
|
@@ -3,12 +3,13 @@ require File.expand_path('../../../../../lib/hydra/remote_identifier/remote_serv
|
|
3
3
|
module Hydra::RemoteIdentifier
|
4
4
|
|
5
5
|
describe RemoteService do
|
6
|
-
let(:payload) { 'abc' }
|
7
|
-
subject { RemoteService.new }
|
8
|
-
|
9
|
-
it { expect { subject.call(payload) }.to raise_error NotImplementedError }
|
10
|
-
it { expect { subject.valid_attribute?(:attribute_name) }.to raise_error NotImplementedError }
|
11
6
|
|
7
|
+
describe 'instance methods' do
|
8
|
+
let(:payload) { 'abc' }
|
9
|
+
subject { RemoteService.new }
|
10
|
+
it { expect { subject.call(payload) }.to raise_error NotImplementedError }
|
11
|
+
it { expect { subject.valid_attribute?(:attribute_name) }.to raise_error NotImplementedError }
|
12
|
+
end
|
12
13
|
end
|
13
14
|
|
14
15
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'hydra/remote_identifier/remote_services/doi'
|
3
|
+
|
4
|
+
module Hydra::RemoteIdentifier
|
5
|
+
module RemoteServices
|
6
|
+
|
7
|
+
describe Doi do
|
8
|
+
let(:configuration) {
|
9
|
+
{
|
10
|
+
username: 'apitest',
|
11
|
+
password: 'apitest',
|
12
|
+
shoulder: 'doi:10.5072/FK2',
|
13
|
+
url: "https://n2t.net/ezid/"
|
14
|
+
}
|
15
|
+
}
|
16
|
+
let(:payload) {
|
17
|
+
{
|
18
|
+
target: 'http://google.com',
|
19
|
+
creator: 'Jeremy Friesen',
|
20
|
+
title: 'My Article',
|
21
|
+
publisher: 'Me Myself and I',
|
22
|
+
publicationyear: "2013"
|
23
|
+
}
|
24
|
+
}
|
25
|
+
let(:expected_doi) {
|
26
|
+
# From the doi-create cassette
|
27
|
+
'doi:10.5072/FK23J3QV8'
|
28
|
+
}
|
29
|
+
subject { RemoteServices::Doi.new(configuration) }
|
30
|
+
|
31
|
+
context '.call' do
|
32
|
+
it 'should post to remote service', VCR::SpecSupport.merge(cassette_name: 'doi-create') do
|
33
|
+
expect(subject.call(payload)).to eq(expected_doi)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -1,61 +1,60 @@
|
|
1
1
|
require File.expand_path('../../../../lib/hydra/remote_identifier', __FILE__)
|
2
2
|
module Hydra::RemoteIdentifier
|
3
3
|
|
4
|
-
describe '
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
example.run
|
17
|
-
RemoteServices.send(:remove_const, :MyRemoteService)
|
18
|
-
end
|
4
|
+
describe '.configure' do
|
5
|
+
|
6
|
+
let(:target_class) {
|
7
|
+
Class.new {
|
8
|
+
def url; 'http://google.com'; end
|
9
|
+
def creator; 'my creator'; end
|
10
|
+
def title; 'my title'; end
|
11
|
+
def publisher; 'my publisher'; end
|
12
|
+
def publicationyear; '2013'; end
|
13
|
+
attr_accessor :set_identifier
|
14
|
+
}
|
15
|
+
}
|
19
16
|
|
20
|
-
|
17
|
+
let(:target) { target_class.new }
|
21
18
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
def update_identifier(value); @identifier = value; end
|
27
|
-
}
|
28
|
-
}
|
29
|
-
let(:target) { target_class.new }
|
19
|
+
let(:expected_doi) {
|
20
|
+
# From the doi-create cassette
|
21
|
+
'doi:10.5072/FK2FT8XZZ'
|
22
|
+
}
|
30
23
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
24
|
+
let(:doi_options) {
|
25
|
+
{
|
26
|
+
username: 'apitest',
|
27
|
+
password: 'apitest',
|
28
|
+
shoulder: 'doi:10.5072/FK2',
|
29
|
+
url: "https://n2t.net/ezid/"
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
describe '.register API' do
|
34
|
+
|
35
|
+
before(:each) do
|
36
|
+
Hydra::RemoteIdentifier.configure do |config|
|
37
|
+
config.configure_remote_service(:doi, doi_options) do |doi|
|
38
|
+
doi.register(target_class) do |map|
|
39
|
+
map.target :url
|
40
|
+
map.creator :creator
|
41
|
+
map.title :title
|
42
|
+
map.publisher :publisher
|
43
|
+
map.publicationyear :publicationyear
|
44
|
+
map.set_identifier(:set_identifier=)
|
45
|
+
end
|
46
|
+
end
|
35
47
|
end
|
48
|
+
end
|
36
49
|
|
50
|
+
it 'works!', VCR::SpecSupport.merge(record: :new_episodes, cassette_name: 'doi-integration') do
|
37
51
|
expect {
|
38
52
|
target_class.registered_remote_identifier_minters.each do |minter|
|
39
53
|
minter.call(target)
|
40
54
|
end
|
41
|
-
}.to change(target, :
|
42
|
-
|
55
|
+
}.to change(target, :set_identifier).from(nil).to(expected_doi)
|
43
56
|
end
|
44
|
-
end
|
45
57
|
|
46
|
-
describe '.remote_service' do
|
47
|
-
context 'with valid remote service' do
|
48
|
-
subject { Hydra::RemoteIdentifier.remote_service(:my_remote_service) }
|
49
|
-
it 'should return an instance of that service' do
|
50
|
-
expect(subject).to be_instance_of RemoteServices::MyRemoteService
|
51
|
-
end
|
52
|
-
end
|
53
|
-
context 'with invalid remote service' do
|
54
|
-
subject { Hydra::RemoteIdentifier.remote_service(:undefined_service) }
|
55
|
-
it 'should raise a NotImplementedError' do
|
56
|
-
expect { subject }.to raise_error NotImplementedError
|
57
|
-
end
|
58
|
-
end
|
59
58
|
end
|
60
59
|
|
61
60
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,6 +1,21 @@
|
|
1
1
|
GEM_ROOT = File.expand_path("../../", __FILE__)
|
2
2
|
$:.unshift File.join(GEM_ROOT, "lib")
|
3
3
|
|
4
|
+
require 'vcr'
|
5
|
+
|
6
|
+
module VCR::SpecSupport
|
7
|
+
module_function
|
8
|
+
def merge(options = {})
|
9
|
+
{vcr: {record: :new_episodes}.merge(options)}
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
VCR.configure do |config|
|
14
|
+
config.cassette_library_dir = 'spec/fixtures/cassettes'
|
15
|
+
config.hook_into :webmock
|
16
|
+
config.configure_rspec_metadata!
|
17
|
+
end
|
18
|
+
|
4
19
|
# This file was generated by the `rspec --init` command. Conventionally, all
|
5
20
|
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
6
21
|
# Require this file using `require "spec_helper"` to ensure that it is only
|
metadata
CHANGED
@@ -1,22 +1,20 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hydra-remote_identifier
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
5
|
-
prerelease:
|
4
|
+
version: 0.2.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Jeremy Friesen
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2013-10-
|
11
|
+
date: 2013-10-03 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: activesupport
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - '>='
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: 3.2.13
|
22
20
|
- - <
|
@@ -25,92 +23,67 @@ dependencies:
|
|
25
23
|
type: :runtime
|
26
24
|
prerelease: false
|
27
25
|
version_requirements: !ruby/object:Gem::Requirement
|
28
|
-
none: false
|
29
26
|
requirements:
|
30
|
-
- -
|
27
|
+
- - '>='
|
31
28
|
- !ruby/object:Gem::Version
|
32
29
|
version: 3.2.13
|
33
30
|
- - <
|
34
31
|
- !ruby/object:Gem::Version
|
35
32
|
version: '5.0'
|
36
33
|
- !ruby/object:Gem::Dependency
|
37
|
-
name:
|
34
|
+
name: rest-client
|
38
35
|
requirement: !ruby/object:Gem::Requirement
|
39
|
-
none: false
|
40
36
|
requirements:
|
41
37
|
- - ~>
|
42
38
|
- !ruby/object:Gem::Version
|
43
|
-
version:
|
44
|
-
type: :
|
39
|
+
version: 1.6.7
|
40
|
+
type: :runtime
|
45
41
|
prerelease: false
|
46
42
|
version_requirements: !ruby/object:Gem::Requirement
|
47
|
-
none: false
|
48
43
|
requirements:
|
49
44
|
- - ~>
|
50
45
|
- !ruby/object:Gem::Version
|
51
|
-
version:
|
46
|
+
version: 1.6.7
|
52
47
|
- !ruby/object:Gem::Dependency
|
53
|
-
name:
|
54
|
-
requirement: !ruby/object:Gem::Requirement
|
55
|
-
none: false
|
56
|
-
requirements:
|
57
|
-
- - ! '>='
|
58
|
-
- !ruby/object:Gem::Version
|
59
|
-
version: '0'
|
60
|
-
type: :development
|
61
|
-
prerelease: false
|
62
|
-
version_requirements: !ruby/object:Gem::Requirement
|
63
|
-
none: false
|
64
|
-
requirements:
|
65
|
-
- - ! '>='
|
66
|
-
- !ruby/object:Gem::Version
|
67
|
-
version: '0'
|
68
|
-
- !ruby/object:Gem::Dependency
|
69
|
-
name: rspec
|
48
|
+
name: bundler
|
70
49
|
requirement: !ruby/object:Gem::Requirement
|
71
|
-
none: false
|
72
50
|
requirements:
|
73
|
-
- -
|
51
|
+
- - ~>
|
74
52
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
53
|
+
version: '1.3'
|
76
54
|
type: :development
|
77
55
|
prerelease: false
|
78
56
|
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
none: false
|
80
57
|
requirements:
|
81
|
-
- -
|
58
|
+
- - ~>
|
82
59
|
- !ruby/object:Gem::Version
|
83
|
-
version: '
|
60
|
+
version: '1.3'
|
84
61
|
- !ruby/object:Gem::Dependency
|
85
|
-
name:
|
62
|
+
name: rake
|
86
63
|
requirement: !ruby/object:Gem::Requirement
|
87
|
-
none: false
|
88
64
|
requirements:
|
89
|
-
- -
|
65
|
+
- - '>='
|
90
66
|
- !ruby/object:Gem::Version
|
91
67
|
version: '0'
|
92
68
|
type: :development
|
93
69
|
prerelease: false
|
94
70
|
version_requirements: !ruby/object:Gem::Requirement
|
95
|
-
none: false
|
96
71
|
requirements:
|
97
|
-
- -
|
72
|
+
- - '>='
|
98
73
|
- !ruby/object:Gem::Version
|
99
74
|
version: '0'
|
100
75
|
- !ruby/object:Gem::Dependency
|
101
|
-
name:
|
76
|
+
name: rspec
|
102
77
|
requirement: !ruby/object:Gem::Requirement
|
103
|
-
none: false
|
104
78
|
requirements:
|
105
|
-
- -
|
79
|
+
- - '>='
|
106
80
|
- !ruby/object:Gem::Version
|
107
81
|
version: '0'
|
108
82
|
type: :development
|
109
83
|
prerelease: false
|
110
84
|
version_requirements: !ruby/object:Gem::Requirement
|
111
|
-
none: false
|
112
85
|
requirements:
|
113
|
-
- -
|
86
|
+
- - '>='
|
114
87
|
- !ruby/object:Gem::Version
|
115
88
|
version: '0'
|
116
89
|
description: Handles the registration and minting of remote identifiers (i.e. DOI,
|
@@ -131,6 +104,7 @@ files:
|
|
131
104
|
- Rakefile
|
132
105
|
- hydra-remote_identifier.gemspec
|
133
106
|
- lib/hydra/remote_identifier.rb
|
107
|
+
- lib/hydra/remote_identifier/configuration.rb
|
134
108
|
- lib/hydra/remote_identifier/exceptions.rb
|
135
109
|
- lib/hydra/remote_identifier/mapper.rb
|
136
110
|
- lib/hydra/remote_identifier/minter.rb
|
@@ -138,52 +112,54 @@ files:
|
|
138
112
|
- lib/hydra/remote_identifier/registration.rb
|
139
113
|
- lib/hydra/remote_identifier/remote_service.rb
|
140
114
|
- lib/hydra/remote_identifier/remote_services.rb
|
115
|
+
- lib/hydra/remote_identifier/remote_services/doi.rb
|
141
116
|
- lib/hydra/remote_identifier/version.rb
|
117
|
+
- spec/fixtures/cassettes/doi-create.yml
|
118
|
+
- spec/fixtures/cassettes/doi-integration.yml
|
119
|
+
- spec/lib/hydra/remote_identifier/configuration_spec.rb
|
142
120
|
- spec/lib/hydra/remote_identifier/mapper_spec.rb
|
143
121
|
- spec/lib/hydra/remote_identifier/minter_spec.rb
|
144
122
|
- spec/lib/hydra/remote_identifier/minting_coordinator_spec.rb
|
145
123
|
- spec/lib/hydra/remote_identifier/registration_spec.rb
|
146
124
|
- spec/lib/hydra/remote_identifier/remote_service_spec.rb
|
125
|
+
- spec/lib/hydra/remote_identifier/remote_services/doi_spec.rb
|
147
126
|
- spec/lib/hydra/remote_identifier_spec.rb
|
148
127
|
- spec/spec_helper.rb
|
149
128
|
homepage: https://github.com/jeremyf/hydra-remote_identifier
|
150
129
|
licenses:
|
151
130
|
- APACHE2
|
131
|
+
metadata: {}
|
152
132
|
post_install_message:
|
153
133
|
rdoc_options: []
|
154
134
|
require_paths:
|
155
135
|
- lib
|
156
136
|
required_ruby_version: !ruby/object:Gem::Requirement
|
157
|
-
none: false
|
158
137
|
requirements:
|
159
|
-
- -
|
138
|
+
- - '>='
|
160
139
|
- !ruby/object:Gem::Version
|
161
140
|
version: '0'
|
162
|
-
segments:
|
163
|
-
- 0
|
164
|
-
hash: 1218886598798334275
|
165
141
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
166
|
-
none: false
|
167
142
|
requirements:
|
168
|
-
- -
|
143
|
+
- - '>='
|
169
144
|
- !ruby/object:Gem::Version
|
170
145
|
version: '0'
|
171
|
-
segments:
|
172
|
-
- 0
|
173
|
-
hash: 1218886598798334275
|
174
146
|
requirements: []
|
175
147
|
rubyforge_project:
|
176
|
-
rubygems_version:
|
148
|
+
rubygems_version: 2.0.3
|
177
149
|
signing_key:
|
178
|
-
specification_version:
|
150
|
+
specification_version: 4
|
179
151
|
summary: Handles the registration and minting of remote identifiers (i.e. DOI, ARK,
|
180
152
|
ORCID)
|
181
153
|
test_files:
|
154
|
+
- spec/fixtures/cassettes/doi-create.yml
|
155
|
+
- spec/fixtures/cassettes/doi-integration.yml
|
156
|
+
- spec/lib/hydra/remote_identifier/configuration_spec.rb
|
182
157
|
- spec/lib/hydra/remote_identifier/mapper_spec.rb
|
183
158
|
- spec/lib/hydra/remote_identifier/minter_spec.rb
|
184
159
|
- spec/lib/hydra/remote_identifier/minting_coordinator_spec.rb
|
185
160
|
- spec/lib/hydra/remote_identifier/registration_spec.rb
|
186
161
|
- spec/lib/hydra/remote_identifier/remote_service_spec.rb
|
162
|
+
- spec/lib/hydra/remote_identifier/remote_services/doi_spec.rb
|
187
163
|
- spec/lib/hydra/remote_identifier_spec.rb
|
188
164
|
- spec/spec_helper.rb
|
189
165
|
has_rdoc:
|