ezid-client 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c103eaae29bd61679e4e349a5a14ab7964edd291
4
+ data.tar.gz: 047f1df3708982722bcbad3fac050183cf6285a6
5
+ SHA512:
6
+ metadata.gz: 53b9aa4362dbeea70ad165b6977756b63ac0ca6ad970fae98caa11ba135e83603f102b23de54b27577a38293f3701bf89712bdc60e7fd19409de0dc1f9a2ea73
7
+ data.tar.gz: ac9b5fa24406b489ce716d6683d2d68c2d6c7e01d59da813e1848385f811ce3d9f4158e6e3b8649935c216624fb273742097bf639d181af7c8a5c04a828cff61
@@ -0,0 +1,21 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/cassettes
15
+ spec/reports
16
+ tmp
17
+ *.bundle
18
+ *.so
19
+ *.o
20
+ *.a
21
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in ezid-client.gemspec
4
+ gemspec
@@ -0,0 +1,27 @@
1
+ Copyright (c) Duke University Libraries.
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without modification,
5
+ are permitted provided that the following conditions are met:
6
+
7
+ 1. Redistributions of source code must retain the above copyright notice,
8
+ this list of conditions and the following disclaimer.
9
+
10
+ 2. Redistributions in binary form must reproduce the above copyright notice,
11
+ this list of conditions and the following disclaimer in the documentation
12
+ and/or other materials provided with the distribution.
13
+
14
+ 3. Neither the name of Duke University nor the names of its contributors may
15
+ be used to endorse or promote products derived from this software without
16
+ specific prior written permission.
17
+
18
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
22
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,71 @@
1
+ # Ezid::Client
2
+
3
+ EZID API Version 2 bindings. See http://ezid.cdlib.org/doc/apidoc.html.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'ezid-client'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install ezid-client
18
+
19
+ ## Usage
20
+
21
+ Create a client
22
+
23
+ ```ruby
24
+ >> client = Ezid::Client.new(user: "apitest", password: "********")
25
+ => #<Ezid::Client:0x007f857c23ca40 @user="apitest", @password="********", @session=#<Ezid::Session:0x007f857c2515a8 @cookie="sessionid=quyclw5bbnwsay0qh05isalt86xj5o1l">>
26
+ ```
27
+
28
+ Mint an identifier
29
+
30
+ ```ruby
31
+ >> response = client.mint_identifier("ark:/99999/fk4")
32
+ => #<Ezid::Response:0x007f857c488010 @http_response=#<Net::HTTPCreated 201 CREATED readbody=true>, @metadata=#<Ezid::Metadata:0x007f857c488448 @elements={}>, @result="success", @message="ark:/99999/fk4988cc8j">
33
+ >> response.identifier
34
+ => "ark:/99999/fk4988cc8j"
35
+ ```
36
+
37
+ Modify identifier metadata
38
+
39
+ ```ruby
40
+ >> metadata = Ezid::Metadata.new("dc.type" => "Image")
41
+ => #<Ezid::Metadata:0x007f857c251c88 @elements={"dc.type"=>"Image"}>
42
+ >> response = client.modify_identifier("ark:/99999/fk4988cc8j", metadata)
43
+ => #<Ezid::Response:0x007f857c53ab20 @http_response=#<Net::HTTPOK 200 OK readbody=true>, @metadata=#<Ezid::Metadata:0x007f857c53aa30 @elements={}>, @result="success", @message="ark:/99999/fk4988cc8j">
44
+ ```
45
+
46
+ Get identifier metadata
47
+
48
+ ```
49
+ >> response = client.get_identifier_metadata("ark:/99999/fk4988cc8j")
50
+ => #<Ezid::Response:0x007f857c50a060 @http_response=#<Net::HTTPOK 200 OK readbody=true>, @metadata=#<Ezid::Metadata:0x007f857c509f48 @elements={"_updated"=>"1416436386", "_target"=>"http://ezid.cdlib.org/id/ark:/99999/fk4988cc8j", "_profile"=>"erc", "dc.type"=>"Image", "_ownergroup"=>"apitest", "_owner"=>"apitest", "_export"=>"yes", "_created"=>"1416436287", "_status"=>"public"}>, @result="success", @message="ark:/99999/fk4988cc8j">
51
+ >> response.metadata["dc.type"]
52
+ => "Image"
53
+ >> puts response.metadata
54
+ _updated: 1416436386
55
+ _target: http://ezid.cdlib.org/id/ark:/99999/fk4988cc8j
56
+ _profile: erc
57
+ dc.type: Image
58
+ _ownergroup: apitest
59
+ _owner: apitest
60
+ _export: yes
61
+ _created: 1416436287
62
+ _status: public
63
+ ```
64
+
65
+ ## Contributing
66
+
67
+ 1. Fork it ( https://github.com/[my-github-username]/ezid-client/fork )
68
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
69
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
70
+ 4. Push to the branch (`git push origin my-new-feature`)
71
+ 5. Create a new Pull Request
@@ -0,0 +1,14 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ desc "Run all specs in spec directory"
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ namespace :test do
8
+ desc "Clean up test artifacts (e.g., VCR cassettes)"
9
+ task :clean do
10
+ FileUtils.rm_rf File.join(__dir__, "spec", "cassettes")
11
+ end
12
+ end
13
+
14
+ task default: :spec
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "ezid-client"
7
+ spec.version = File.read(File.expand_path("../VERSION", __FILE__)).chomp
8
+ spec.authors = ["dchandekstark"]
9
+ spec.email = ["dchandekstark@gmail.com"]
10
+ spec.summary = "Ruby client for EZID API Version 2"
11
+ spec.description = "Ruby client for EZID API Version 2 (http://ezid.cdlib.org/doc/apidoc.html)"
12
+ spec.homepage = "https://github.com/duke-libraries/ezid-client"
13
+ spec.license = "BSD-3-Clause"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_development_dependency "bundler", "~> 1.6"
21
+ spec.add_development_dependency "rake"
22
+ spec.add_development_dependency "rspec", "~> 3.0"
23
+ spec.add_development_dependency "vcr"
24
+ spec.add_development_dependency "webmock"
25
+ end
@@ -0,0 +1 @@
1
+ require "ezid/client"
@@ -0,0 +1,52 @@
1
+ module Ezid
2
+ #
3
+ # EZID API Version 2 bindings
4
+ #
5
+ module Api
6
+
7
+ VERSION = "2"
8
+
9
+ # EZID server subsystems
10
+ DATACITE_SUBSYSTEM = "datacite"
11
+ NOID_SUBSYSTEM = "noid"
12
+ LDAP_SUBSYSTEM = "ldap"
13
+ ALL_SUBSYSTEMS = "*"
14
+
15
+ class << self
16
+
17
+ def login
18
+ [:Get, "/login"]
19
+ end
20
+
21
+ def logout
22
+ [:Get, "/logout"]
23
+ end
24
+
25
+ def mint_identifier(shoulder)
26
+ [:Post, "/shoulder/#{shoulder}"]
27
+ end
28
+
29
+ def create_identifier(identifier)
30
+ [:Put, "/id/#{identifier}"]
31
+ end
32
+
33
+ def modify_identifier(identifier)
34
+ [:Post, "/id/#{identifier}"]
35
+ end
36
+
37
+ def get_identifier_metadata(identifier)
38
+ [:Get, "/id/#{identifier}"]
39
+ end
40
+
41
+ def delete_identifier(identifier)
42
+ [:Delete, "/id/#{identifier}"]
43
+ end
44
+
45
+ def server_status(subsystems)
46
+ [:Get, "/status", "subsystems=#{subsystems.join(',')}"]
47
+ end
48
+
49
+ end
50
+
51
+ end
52
+ end
@@ -0,0 +1,184 @@
1
+ require_relative "identifier"
2
+ require_relative "request"
3
+ require_relative "session"
4
+ require_relative "configuration"
5
+ require_relative "error"
6
+
7
+ module Ezid
8
+ class Client
9
+
10
+ class << self
11
+ def config
12
+ @config ||= Configuration.new
13
+ end
14
+
15
+ def configure
16
+ yield config
17
+ end
18
+
19
+ def create_identifier(*args)
20
+ Client.new.create_identifier(*args)
21
+ end
22
+
23
+ def mint_identifier(*args)
24
+ Client.new.mint_identifier(*args)
25
+ end
26
+
27
+ def get_identifier_metadata(*args)
28
+ Client.new.get_identifier_metadata(*args)
29
+ end
30
+
31
+ def login
32
+ Client.new.login
33
+ end
34
+ end
35
+
36
+ attr_reader :session, :user, :password
37
+
38
+ def initialize(opts = {})
39
+ @session = Session.new
40
+ @user = opts[:user] || config.user
41
+ @password = opts[:password] || config.password
42
+ if block_given?
43
+ login
44
+ yield self
45
+ logout
46
+ end
47
+ end
48
+
49
+ def inspect
50
+ out = super
51
+ out.sub!(/@password="[^\"]+"/, "@password=\"********\"")
52
+ out.sub!(/@session=#<[^>]+>/, logged_in? ? "LOGGED_IN" : "")
53
+ out
54
+ end
55
+
56
+ def config
57
+ self.class.config
58
+ end
59
+
60
+ def logger
61
+ config.logger
62
+ end
63
+
64
+ def login
65
+ if logged_in?
66
+ logger.info("Already logged in, skipping login request.")
67
+ else
68
+ do_login
69
+ end
70
+ end
71
+
72
+ def logout
73
+ if logged_in?
74
+ do_logout
75
+ else
76
+ logger.info("Not logged in, skipping logout request.")
77
+ end
78
+ end
79
+
80
+ def logged_in?
81
+ session.open?
82
+ end
83
+
84
+ def create_identifier(identifier, metadata=nil)
85
+ request = Request.build(:create_identifier, identifier)
86
+ add_authentication(request)
87
+ add_metadata(request, metadata)
88
+ execute(request)
89
+ end
90
+
91
+ def mint_identifier(shoulder, metadata=nil)
92
+ request = Request.build(:mint_identifier, shoulder)
93
+ add_authentication(request)
94
+ add_metadata(request, metadata)
95
+ execute(request)
96
+ end
97
+
98
+ def modify_identifier(identifier, metadata)
99
+ raise ArgumentError, "Metadata is required" if metadata.nil? || metadata.empty?
100
+ request = Request.build(:modify_identifier, identifier)
101
+ add_authentication(request)
102
+ add_metadata(request, metadata)
103
+ execute(request)
104
+ end
105
+
106
+ def get_identifier_metadata(identifier)
107
+ request = Request.build(:get_identifier_metadata, identifier)
108
+ add_authentication(request)
109
+ execute(request)
110
+ end
111
+
112
+ def delete_identifier(identifier)
113
+ request = Request.build(:delete_identifier, identifier)
114
+ add_authentication(request)
115
+ execute(request)
116
+ end
117
+
118
+ def server_status(*subsystems)
119
+ request = Request.build(:server_status, subsystems)
120
+ execute(request)
121
+ end
122
+
123
+ private
124
+
125
+ # Executes the request
126
+ def execute(request)
127
+ response = request.execute
128
+ handle_response(response)
129
+ end
130
+
131
+ # Handles the response
132
+ def handle_response(response)
133
+ raise Error, response.message if response.error?
134
+ response
135
+ ensure
136
+ log_response(response)
137
+ end
138
+
139
+ # Logs a message for the response
140
+ def log_response(response)
141
+ logger.log(log_level(response), log_message(response))
142
+ end
143
+
144
+ # Returns the log level to use for the response
145
+ def log_level(response)
146
+ response.error? ? Logger::ERROR : Logger::INFO
147
+ end
148
+
149
+ # Returns the message to log for the response
150
+ def log_message(response)
151
+ response.status_line
152
+ end
153
+
154
+ # Adds metadata to the request
155
+ def add_metadata(request, metadata)
156
+ request.body = metadata.to_anvl unless metadata.nil? || metadata.empty?
157
+ end
158
+
159
+ # Adds authentication to the request
160
+ def add_authentication(request)
161
+ if session.open?
162
+ request["Cookie"] = session.cookie
163
+ else
164
+ request.basic_auth(user, password)
165
+ end
166
+ end
167
+
168
+ def do_login
169
+ request = Request.build(:login)
170
+ add_authentication(request)
171
+ response = execute(request)
172
+ session.open(response)
173
+ self
174
+ end
175
+
176
+ def do_logout
177
+ request = Request.build(:logout)
178
+ execute(request)
179
+ session.close
180
+ self
181
+ end
182
+
183
+ end
184
+ end
@@ -0,0 +1,22 @@
1
+ require "logger"
2
+
3
+ module Ezid
4
+ class Configuration
5
+
6
+ attr_writer :user, :password, :logger
7
+ attr_accessor :metadata_profile, :default_status
8
+
9
+ def user
10
+ @user ||= ENV["EZID_USER"]
11
+ end
12
+
13
+ def password
14
+ @password ||= ENV["EZID_PASSWORD"]
15
+ end
16
+
17
+ def logger
18
+ @logger ||= Logger.new(STDERR)
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,3 @@
1
+ module Ezid
2
+ class Error < ::RuntimeError; end
3
+ end
@@ -0,0 +1,56 @@
1
+ require_relative "metadata"
2
+
3
+ module Ezid
4
+ class Identifier
5
+
6
+ class << self
7
+ def create(id, metadata=nil)
8
+ response = Client.create_identifier(id, metadata)
9
+ Identifier.new(response.identifier)
10
+ end
11
+
12
+ def mint(metadata=nil)
13
+ response = Client.mint_identifier(metadata)
14
+ identifier = Identifier.new(response.identifier)
15
+ end
16
+
17
+ def find(id)
18
+ response = Client.get_identifier_metadata(id)
19
+ Identifier.new(response.identifier, response.metadata)
20
+ end
21
+ end
22
+
23
+ attr_reader :id
24
+
25
+ def initialize(id, metadata=nil)
26
+ @id = id
27
+ @metadata = Metadata.new(metadata)
28
+ end
29
+
30
+ def metadata
31
+ reload if @metadata.empty?
32
+ @metadata
33
+ end
34
+
35
+ def reload
36
+ response = client.get_identifier_metadata(id)
37
+ @metadata.update(response.metadata)
38
+ self
39
+ end
40
+
41
+ def client
42
+ @client ||= Client.new
43
+ end
44
+
45
+ def save
46
+ response = client.modify_identifier(id, metadata)
47
+ response.success?
48
+ end
49
+
50
+ def delete
51
+ response = client.delete_identifier(id)
52
+ response.success?
53
+ end
54
+
55
+ end
56
+ end
@@ -0,0 +1,79 @@
1
+ require "forwardable"
2
+
3
+ module Ezid
4
+ class Metadata
5
+ extend Forwardable
6
+
7
+ attr_reader :elements
8
+ def_delegators :elements, :[], :[]=, :empty?, :to_h, :to_a
9
+
10
+ ERC_PROFILE = "erc"
11
+ DC_PROFILE = "dc"
12
+ DATACITE_PROFILE = "datacite"
13
+ CROSSREF_PROFILE = "crossref"
14
+
15
+ STATUS_PUBLIC = "public"
16
+ STATUS_RESERVED = "reserved"
17
+ STATUS_UNAVAILABLE = "unavailable"
18
+
19
+ # Internal metadata elements
20
+ INTERNAL_READONLY_ELEMENTS = %w( _owner _ownergroup _created _updated _shadows _shadowedby _datacenter ).freeze
21
+ INTERNAL_READWRITE_ELEMENTS = %w( _coowners _target _profile _status _export _crossref ).freeze
22
+ INTERNAL_ELEMENTS = (INTERNAL_READONLY_ELEMENTS + INTERNAL_READWRITE_ELEMENTS).freeze
23
+
24
+ ANVL_SEPARATOR = ": ".freeze
25
+
26
+ # Creates a reader method for each internal metadata element
27
+ INTERNAL_ELEMENTS.each do |element|
28
+ reader = element.sub("_", "").to_sym
29
+ define_method(reader) do
30
+ self[element]
31
+ end
32
+ end
33
+
34
+ # Creates a writer method for each writable internal metadata element
35
+ INTERNAL_READWRITE_ELEMENTS.each do |element|
36
+ writer = "#{element.sub('_', '')}=".to_sym
37
+ define_method(writer) do |value|
38
+ self[element] = value
39
+ end
40
+ end
41
+
42
+ # @param data [Hash, String, Ezid::Metadata] EZID metadata
43
+ def initialize(data={})
44
+ @elements = coerce(data)
45
+ end
46
+
47
+ # @todo escape \n, \r and %
48
+ # @todo force UTF-8
49
+ # @see http://ezid.cdlib.org/doc/apidoc.html#request-response-bodies
50
+ def to_anvl
51
+ to_a.map { |pair| pair.join(ANVL_SEPARATOR) }.join("\n")
52
+ end
53
+
54
+ def to_s
55
+ to_anvl
56
+ end
57
+
58
+ # Add metadata
59
+ def update(data)
60
+ elements.update(coerce(data))
61
+ end
62
+
63
+ private
64
+
65
+ # Coerce data into a Hash of elements
66
+ # @todo unescape
67
+ # @see {#to_anvl}
68
+ def coerce(data)
69
+ begin
70
+ data.to_h
71
+ rescue NoMethodError
72
+ # This does not account for comments and continuation lines
73
+ # http://ezid.cdlib.org/doc/apidoc.html#request-response-bodies
74
+ data.split(/\r?\n/).map { |line| line.split(ANVL_SEPARATOR, 2) }.to_h
75
+ end
76
+ end
77
+
78
+ end
79
+ end
@@ -0,0 +1,34 @@
1
+ require "uri"
2
+ require "net/http"
3
+ require "delegate"
4
+
5
+ require_relative "api"
6
+ require_relative "response"
7
+
8
+ module Ezid
9
+ #
10
+ # A request to the EZID service.
11
+ #
12
+ class Request < SimpleDelegator
13
+
14
+ EZID_HOST = "ezid.cdlib.org"
15
+ CHARSET = "UTF-8"
16
+ CONTENT_TYPE = "text/plain"
17
+
18
+ def self.build(op, *args)
19
+ http_method, path, query = Api.send(op, *args)
20
+ uri = URI::HTTPS.build(host: EZID_HOST, path: path, query: query)
21
+ http_request = Net::HTTP.const_get(http_method).new(uri)
22
+ Request.new(http_request)
23
+ end
24
+
25
+ def execute
26
+ http_response = Net::HTTP.start(uri.host, use_ssl: true) do |http|
27
+ set_content_type(CONTENT_TYPE, charset: CHARSET)
28
+ http.request(__getobj__)
29
+ end
30
+ Response.build(http_response)
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,59 @@
1
+ require "delegate"
2
+
3
+ module Ezid
4
+ # A response from the EZID service.
5
+ class Response < SimpleDelegator
6
+
7
+ SUCCESS = "success"
8
+ ERROR = "error"
9
+
10
+ def self.build(http_response)
11
+ Response.new(http_response)
12
+ end
13
+
14
+ def status
15
+ @status ||= status_line.split(/: /)
16
+ end
17
+
18
+ def status_line
19
+ content.first
20
+ end
21
+
22
+ def content
23
+ @content ||= body.split(/\r?\n/, 2)
24
+ end
25
+
26
+ def metadata
27
+ content.last if success? && identifier_uri?
28
+ end
29
+
30
+ def identifier
31
+ message.split(/\s/).first if success? && identifier_uri?
32
+ end
33
+
34
+ def identifier_uri?
35
+ uri.path =~ /^\/(id|shoulder)\//
36
+ end
37
+
38
+ def outcome
39
+ status.first
40
+ end
41
+
42
+ def message
43
+ status.last
44
+ end
45
+
46
+ def cookie
47
+ self["Set-Cookie"].split(";").first rescue nil
48
+ end
49
+
50
+ def error?
51
+ outcome == ERROR
52
+ end
53
+
54
+ def success?
55
+ outcome == SUCCESS
56
+ end
57
+
58
+ end
59
+ end
@@ -0,0 +1,37 @@
1
+ require "uri"
2
+ require "net/http"
3
+
4
+ require_relative "request"
5
+
6
+ module Ezid
7
+ class Session
8
+
9
+ attr_reader :cookie
10
+
11
+ def initialize(response=nil)
12
+ open(response) if response
13
+ end
14
+
15
+ def inspect
16
+ super.sub(/@cookie="[^\"]+"/, "OPEN")
17
+ end
18
+
19
+ def open(response)
20
+ # XXX raise exception if no cookie?
21
+ @cookie = response.cookie if response.cookie
22
+ end
23
+
24
+ def close
25
+ @cookie = nil
26
+ end
27
+
28
+ def closed?
29
+ cookie.nil?
30
+ end
31
+
32
+ def open?
33
+ !closed?
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,17 @@
1
+ module Ezid
2
+ module TestHelper
3
+
4
+ TEST_USER = "apitest"
5
+ ARK_SHOULDER = "ark:/99999/fk4"
6
+ DOI_SHOULDER = "doi:10.5072/FK2"
7
+
8
+ def doi_metadata
9
+ Metadata.new("datacite.title" => "Test",
10
+ "datacite.creator" => "Duke",
11
+ "datacite.publisher" => "Duke",
12
+ "datacite.publicationyear" => "2014",
13
+ "datacite.resourcetype" => "Other")
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,80 @@
1
+ module Ezid
2
+ RSpec.describe Client do
3
+ describe "initialization" do
4
+ describe "without a block" do
5
+ subject { described_class.new(user: TEST_USER) }
6
+ it "should not be logged in" do
7
+ expect(subject).not_to be_logged_in
8
+ end
9
+ end
10
+ describe "with a block", :vcr do
11
+ it "should be logged in" do
12
+ described_class.new(user: TEST_USER) do |client|
13
+ expect(client).to be_logged_in
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ describe "authentication", :vcr do
20
+ subject { described_class.new(user: TEST_USER) }
21
+ describe "logging in" do
22
+ before { subject.login }
23
+ it "should be logged in" do
24
+ expect(subject).to be_logged_in
25
+ end
26
+ end
27
+ describe "logging out" do
28
+ before { subject.login; subject.logout }
29
+ it "should not be logged in" do
30
+ expect(subject).not_to be_logged_in
31
+ end
32
+ end
33
+ end
34
+ describe "creating an identifier" do
35
+ # TODO
36
+ end
37
+ describe "minting an identifier", :vcr do
38
+ let(:client) { described_class.new(user: TEST_USER) }
39
+ describe "which is an ARK" do
40
+ subject { client.mint_identifier(ARK_SHOULDER) }
41
+ it "should be a success" do
42
+ expect(subject).to be_success
43
+ expect(subject.message).to match(/#{ARK_SHOULDER}/)
44
+ end
45
+ end
46
+ describe "which is a DOI" do
47
+ subject { client.mint_identifier(DOI_SHOULDER, doi_metadata) }
48
+ it "should be a sucess" do
49
+ expect(subject).to be_success
50
+ expect(subject.message).to match(/#{DOI_SHOULDER}/)
51
+ expect(subject.message).to match(/\| ark:/)
52
+ end
53
+ end
54
+ end
55
+ describe "getting identifier metadata", :vcr do
56
+ let(:client) { described_class.new(user: TEST_USER) }
57
+ let(:metadata) { Metadata.new("dc.title" => "Test") }
58
+ let(:identifier) { client.mint_identifier(ARK_SHOULDER, metadata).message }
59
+ subject { Metadata.new(client.get_identifier_metadata(identifier).content.last) }
60
+ it "should return the metadata" do
61
+ expect(subject["dc.title"]).to eq("Test")
62
+ end
63
+ end
64
+ describe "modifying an identifier" do
65
+ # TODO
66
+ end
67
+ describe "deleting an identifier" do
68
+ # TODO
69
+ end
70
+ describe "server status", :vcr do
71
+ let(:client) { described_class.new(user: TEST_USER) }
72
+ subject { client.server_status("*") }
73
+ it "should report the status of EZID and subsystems" do
74
+ expect(subject).to be_success
75
+ expect(subject.message).to eq "EZID is up"
76
+ end
77
+ end
78
+ end
79
+ end
80
+
@@ -0,0 +1,102 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # The generated `.rspec` file contains `--require spec_helper` which will cause this
4
+ # file to always be loaded, without a need to explicitly require it in any files.
5
+ #
6
+ # Given that it is always loaded, you are encouraged to keep this file as
7
+ # light-weight as possible. Requiring heavyweight dependencies from this file
8
+ # will add to the boot time of your test suite on EVERY test run, even for an
9
+ # individual file that may not need all of that loaded. Instead, consider making
10
+ # a separate helper file that requires the additional dependencies and performs
11
+ # the additional setup, and require it from the spec files that actually need it.
12
+ #
13
+ # The `.rspec` file also contains a few flags that are not defaults but that
14
+ # users commonly want.
15
+ #
16
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
17
+
18
+ require "ezid-client"
19
+ require "ezid/test_helper"
20
+
21
+ include Ezid::TestHelper
22
+
23
+ require "vcr"
24
+
25
+ VCR.configure do |c|
26
+ c.cassette_library_dir = 'spec/cassettes'
27
+ c.hook_into :webmock
28
+ c.configure_rspec_metadata!
29
+ c.allow_http_connections_when_no_cassette = true
30
+ end
31
+
32
+ RSpec.configure do |config|
33
+
34
+ # rspec-expectations config goes here. You can use an alternate
35
+ # assertion/expectation library such as wrong or the stdlib/minitest
36
+ # assertions if you prefer.
37
+ config.expect_with :rspec do |expectations|
38
+ # This option will default to `true` in RSpec 4. It makes the `description`
39
+ # and `failure_message` of custom matchers include text for helper methods
40
+ # defined using `chain`, e.g.:
41
+ # be_bigger_than(2).and_smaller_than(4).description
42
+ # # => "be bigger than 2 and smaller than 4"
43
+ # ...rather than:
44
+ # # => "be bigger than 2"
45
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
46
+ end
47
+
48
+ # rspec-mocks config goes here. You can use an alternate test double
49
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
50
+ config.mock_with :rspec do |mocks|
51
+ # Prevents you from mocking or stubbing a method that does not exist on
52
+ # a real object. This is generally recommended, and will default to
53
+ # `true` in RSpec 4.
54
+ mocks.verify_partial_doubles = true
55
+ end
56
+
57
+ # These two settings work together to allow you to limit a spec run
58
+ # to individual examples or groups you care about by tagging them with
59
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
60
+ # get run.
61
+ config.filter_run :focus
62
+ config.run_all_when_everything_filtered = true
63
+
64
+ # Limits the available syntax to the non-monkey patched syntax that is recommended.
65
+ # For more details, see:
66
+ # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
67
+ # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
68
+ # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
69
+ config.disable_monkey_patching!
70
+
71
+ # This setting enables warnings. It's recommended, but in some cases may
72
+ # be too noisy due to issues in dependencies.
73
+ config.warnings = true
74
+
75
+ # Many RSpec users commonly either run the entire suite or an individual
76
+ # file, and it's useful to allow more verbose output when running an
77
+ # individual spec file.
78
+ if config.files_to_run.one?
79
+ # Use the documentation formatter for detailed output,
80
+ # unless a formatter has already been configured
81
+ # (e.g. via a command-line flag).
82
+ config.default_formatter = 'doc'
83
+ end
84
+
85
+ # Print the 10 slowest examples and example groups at the
86
+ # end of the spec run, to help surface which specs are running
87
+ # particularly slow.
88
+ config.profile_examples = 10
89
+
90
+ # Run specs in random order to surface order dependencies. If you find an
91
+ # order dependency and want to debug it, you can fix the order by providing
92
+ # the seed, which is printed after each run.
93
+ # --seed 1234
94
+ config.order = :random
95
+
96
+ # Seed global randomization in this process using the `--seed` CLI option.
97
+ # Setting this allows you to use `--seed` to deterministically reproduce
98
+ # test failures related to randomization by passing the same `--seed` value
99
+ # as the one that triggered the failure.
100
+ Kernel.srand config.seed
101
+
102
+ end
metadata ADDED
@@ -0,0 +1,137 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ezid-client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - dchandekstark
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-11-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: vcr
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: webmock
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Ruby client for EZID API Version 2 (http://ezid.cdlib.org/doc/apidoc.html)
84
+ email:
85
+ - dchandekstark@gmail.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - ".rspec"
92
+ - Gemfile
93
+ - LICENSE.txt
94
+ - README.md
95
+ - Rakefile
96
+ - VERSION
97
+ - ezid-client.gemspec
98
+ - lib/ezid-client.rb
99
+ - lib/ezid/api.rb
100
+ - lib/ezid/client.rb
101
+ - lib/ezid/configuration.rb
102
+ - lib/ezid/error.rb
103
+ - lib/ezid/identifier.rb
104
+ - lib/ezid/metadata.rb
105
+ - lib/ezid/request.rb
106
+ - lib/ezid/response.rb
107
+ - lib/ezid/session.rb
108
+ - lib/ezid/test_helper.rb
109
+ - spec/lib/ezid/client_spec.rb
110
+ - spec/spec_helper.rb
111
+ homepage: https://github.com/duke-libraries/ezid-client
112
+ licenses:
113
+ - BSD-3-Clause
114
+ metadata: {}
115
+ post_install_message:
116
+ rdoc_options: []
117
+ require_paths:
118
+ - lib
119
+ required_ruby_version: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ required_rubygems_version: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - ">="
127
+ - !ruby/object:Gem::Version
128
+ version: '0'
129
+ requirements: []
130
+ rubyforge_project:
131
+ rubygems_version: 2.2.2
132
+ signing_key:
133
+ specification_version: 4
134
+ summary: Ruby client for EZID API Version 2
135
+ test_files:
136
+ - spec/lib/ezid/client_spec.rb
137
+ - spec/spec_helper.rb