hydra-remote_identifier 0.0.3 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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:
|