ezid-client 1.3.0 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 141f157b6169fdedba53b58d11e0b9c1b26c7662
4
- data.tar.gz: ef0923245729d7f20e079f3581d7647bc7cb5581
3
+ metadata.gz: f2baebf2aca4cada19d44f70e2e6614ad9e206ea
4
+ data.tar.gz: 1cbc73e6739a91a88d2cd3a7f5698d8dab1bfa3a
5
5
  SHA512:
6
- metadata.gz: 16b22cbb1ba43ab241036710cfb044f66b365dd434a783a31a1370743e063517a530df12b2f72c24c0f3575dabdb8045e49fa673fc01306621d46fe2a8a88683
7
- data.tar.gz: f329532cc4d162575b0c3c14a76d8b7ca253963486686e73565ec4f31debd1c498f5804034f2713badac901b0875d7a27eba322a488bd6ef48f073b01246ce70
6
+ metadata.gz: 042582d5276928c9444bf60eb1d1ed851795d072145c2e33e13d8a08d25be121bb797992ed941a2e1eba5cae1a9f980d26c24196f4ffa59edbf9a3d1d5a46161
7
+ data.tar.gz: f6be1c6c06c59f8aec88b78664927aa0fbd8c92d090f920ad5c4c9edf99202c397f6a8444b2210da12c1f5c1ebc7240401286dc09fb447b7ef9f9ee65cccc414
data/README.md CHANGED
@@ -27,17 +27,17 @@ Or install it yourself as:
27
27
 
28
28
  [Mint an identifier on a shoulder](http://ezid.cdlib.org/doc/apidoc.html#operation-mint-identifier)
29
29
 
30
+ *Added in v1.4.0:* `Ezid::Identifier.mint` class method.
31
+
30
32
  ```
31
- >> identifier = Ezid::Identifier.create(shoulder: "ark:/99999/fk4")
32
- I, [2014-12-04T15:06:02.428445 #86655] INFO -- : EZID MintIdentifier -- success: ark:/99999/fk4rx9d523
33
- I, [2014-12-04T15:06:03.249793 #86655] INFO -- : EZID GetIdentifierMetadata -- success: ark:/99999/fk4rx9d523
34
- => #<Ezid::Identifier id="ark:/99999/fk4rx9d523" status="public" target="http://ezid.cdlib.org/id/ark:/99999/fk4rx9d523" created="2014-12-04 20:06:02 UTC">
35
- >> identifier.id
36
- => "ark:/99999/fk4rx9d523"
33
+ >> identifier = Ezid::Identifier.mint("ark:/99999/fk4")
34
+ I, [2016-03-01T22:20:08.505323 #35148] INFO -- : EZID MintIdentifier -- success: ark:/99999/fk4tq65d6k
35
+ => #<Ezid::Identifier id=ark:/99999/fk4tq65d6k>
37
36
  >> identifier.status
37
+ I, [2016-03-01T22:20:22.323650 #35148] INFO -- : EZID GetIdentifierMetadata -- success: ark:/99999/fk4tq65d6k
38
38
  => "public"
39
39
  >> identifier.target
40
- => "http://ezid.cdlib.org/id/ark:/99999/fk4rx9d523"
40
+ => "http://ezid.cdlib.org/id/ark:/99999/fk4tq65d6k"
41
41
  ```
42
42
 
43
43
  A default shoulder can be configured:
@@ -59,19 +59,19 @@ end
59
59
  New identifiers will then be minted on the default shoulder when a shoulder is not specified:
60
60
 
61
61
  ```
62
- >> identifier = Ezid::Identifier.create
62
+ >> identifier = Ezid::Identifier.mint
63
63
  I, [2014-12-09T11:22:34.499860 #32279] INFO -- : EZID MintIdentifier -- success: ark:/99999/fk43f4wd4v
64
- I, [2014-12-09T11:22:35.317181 #32279] INFO -- : EZID GetIdentifierMetadata -- success: ark:/99999/fk43f4wd4v
65
- => #<Ezid::Identifier id="ark:/99999/fk43f4wd4v" status="public" target="http://ezid.cdlib.org/id/ark:/99999/fk43f4wd4v" created="2014-12-09 16:22:35 UTC">
64
+ => #<Ezid::Identifier id="ark:/99999/fk43f4wd4v">
66
65
  ```
67
66
 
68
67
  [Create a specific identifier](http://ezid.cdlib.org/doc/apidoc.html#operation-create-identifier)
69
68
 
69
+ *Changed in v1.4.0:* `Ezid::Identifier.create` now expects the first argument to be the identifier (String) to create; the second optional argument is a hash of metadata elements. Passing the identifier in an `:id` hash option is deprecated and will be removed in v2.0. The `:shoulder` hash option is likewise deprecated; use `Ezid::Identifier.mint(shoulder, metadata)` instead.
70
+
70
71
  ```
71
- >> identifier = Ezid::Identifier.create(id: "ark:/99999/fk4rx9d523/12345")
72
+ >> identifier = Ezid::Identifier.create("ark:/99999/fk4rx9d523/12345")
72
73
  I, [2014-12-09T11:21:42.077297 #32279] INFO -- : EZID CreateIdentifier -- success: ark:/99999/fk4rx9d523/12345
73
- I, [2014-12-09T11:21:42.808534 #32279] INFO -- : EZID GetIdentifierMetadata -- success: ark:/99999/fk4rx9d523/12345
74
- => #<Ezid::Identifier id="ark:/99999/fk4rx9d523/12345" status="public" target="http://ezid.cdlib.org/id/ark:/99999/fk4rx9d523/12345" created="2014-12-09 16:21:42 UTC">
74
+ => #<Ezid::Identifier id="ark:/99999/fk4rx9d523/12345">
75
75
  ```
76
76
 
77
77
  **Retrieve** (Get Metadata)
@@ -91,30 +91,34 @@ I, [2014-12-04T15:07:00.648676 #86655] INFO -- : EZID GetIdentifierMetadata --
91
91
  => "http://example.com"
92
92
  >> identifier.save
93
93
  I, [2014-12-09T11:24:26.321801 #32279] INFO -- : EZID ModifyIdentifier -- success: ark:/99999/fk43f4wd4v
94
- I, [2014-12-09T11:24:27.039288 #32279] INFO -- : EZID GetIdentifierMetadata -- success: ark:/99999/fk43f4wd4v
95
- => #<Ezid::Identifier id="ark:/99999/fk43f4wd4v" status="public" target="http://example.com" created="2014-12-09 16:22:35 UTC">
94
+ => #<Ezid::Identifier id="ark:/99999/fk43f4wd4v">
96
95
  >> identifier.target
96
+ I, [2014-12-09T11:24:27.039288 #32279] INFO -- : EZID GetIdentifierMetadata -- success: ark:/99999/fk43f4wd4v
97
97
  => "http://example.com"
98
98
  ```
99
99
 
100
+ *Added in v1.4.0:* `Ezid::Identifier.modify(id, metadata)` class method. In support of more efficient updating of known identifiers, this method skips the GetIdentifierMetadata request used by `.find`. The operation will raise the `Ezid::IdentifierNotFoundError` if the EZID identifier does not exist.
101
+
100
102
  **Delete**
101
103
 
102
104
  *Identifier status must be "reserved" to delete.* http://ezid.cdlib.org/doc/apidoc.html#operation-delete-identifier
103
105
 
104
106
  ```
105
- >> identifier = Ezid::Identifier.create(shoulder: "ark:/99999/fk4", status: "reserved")
106
- I, [2014-12-04T15:12:39.976930 #86734] INFO -- : EZID MintIdentifier -- success: ark:/99999/fk4n58pc0r
107
- I, [2014-12-04T15:12:40.693256 #86734] INFO -- : EZID GetIdentifierMetadata -- success: ark:/99999/fk4n58pc0r
108
- => #<Ezid::Identifier id="ark:/99999/fk4n58pc0r" status="reserved" target="http://ezid.cdlib.org/id/ark:/99999/fk4n58pc0r" created="2014-12-04 20:12:39 UTC">
107
+ >> identifier = Ezid::Identifier.mint("ark:/99999/fk4", status: "reserved")
108
+ I, [2016-03-01T22:26:08.645858 #36701] INFO -- : EZID MintIdentifier -- success: ark:/99999/fk4pz5fm1b
109
+ => #<Ezid::Identifier id=ark:/99999/fk4pz5fm1b>
109
110
  >> identifier.delete
110
- I, [2014-12-04T15:12:48.853964 #86734] INFO -- : EZID DeleteIdentifier -- success: ark:/99999/fk4n58pc0r
111
- => #<Ezid::Identifier id="ark:/99999/fk4n58pc0r" DELETED>
111
+ I, [2016-03-01T22:26:14.829731 #36701] INFO -- : EZID GetIdentifierMetadata -- success: ark:/99999/fk4pz5fm1b
112
+ I, [2016-03-01T22:26:15.711390 #36701] INFO -- : EZID DeleteIdentifier -- success: ark:/99999/fk4pz5fm1b
113
+ => #<Ezid::Identifier id=ark:/99999/fk4pz5fm1b [DELETED]>
112
114
  ```
113
115
 
114
116
  ## Batch Download
115
117
 
116
118
  See http://ezid.cdlib.org/doc/apidoc.html#parameters. Repeated values should be given as an array value for the parameter key.
117
119
 
120
+ *Added in v1.3.0:* `Ezid::BatchDownload` class.
121
+
118
122
  ```
119
123
  >> batch = Ezid::BatchDownload.new(:csv)
120
124
  => #<Ezid::BatchDownload format=:csv>
@@ -161,33 +165,6 @@ Notes:
161
165
 
162
166
  Accessors are also implemented for the `crossref`, `datacite`, and `erc` elements as described in the EZID API documentation.
163
167
 
164
- **Setting default metadata values**
165
-
166
- Default metadata values can be set:
167
-
168
- ```ruby
169
- Ezid::Client.configure do |config|
170
- # set multiple defaults with a hash
171
- config.identifier.defaults = {status: "reserved", profile: "dc"}
172
- # or set individual elements
173
- config.identifier.defaults[:status] = "reserved"
174
- config.identifier.defaults[:profile] = "dc"
175
- end
176
- ```
177
-
178
- Then new identifiers will receive the defaults:
179
-
180
- ```
181
- >> identifier = Ezid::Identifier.create(shoulder: "ark:/99999/fk4")
182
- I, [2014-12-09T11:38:37.335136 #32279] INFO -- : EZID MintIdentifier -- success: ark:/99999/fk4zs2w500
183
- I, [2014-12-09T11:38:38.153546 #32279] INFO -- : EZID GetIdentifierMetadata -- success: ark:/99999/fk4zs2w500
184
- => #<Ezid::Identifier id="ark:/99999/fk4zs2w500" status="reserved" target="http://ezid.cdlib.org/id/ark:/99999/fk4zs2w500" created="2014-12-09 16:38:38 UTC">
185
- >> identifier.profile
186
- => "dc"
187
- >> identifier.status
188
- => "reserved"
189
- ```
190
-
191
168
  ## Authentication
192
169
 
193
170
  Credentials can be provided in any -- or a combination -- of these ways:
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.3.0
1
+ 1.4.0
data/ezid-client.gemspec CHANGED
@@ -24,4 +24,5 @@ Gem::Specification.new do |spec|
24
24
  spec.add_development_dependency "bundler", "~> 1.7"
25
25
  spec.add_development_dependency "rake"
26
26
  spec.add_development_dependency "rspec", "~> 3.1"
27
+ spec.add_development_dependency "rspec-its"
27
28
  end
@@ -1,7 +1,6 @@
1
1
  require "hashie"
2
2
  require "net/http"
3
3
  require "uri"
4
- require_relative "reserved_metadata"
5
4
 
6
5
  module Ezid
7
6
  class BatchDownloadError < Error; end
data/lib/ezid/client.rb CHANGED
@@ -6,7 +6,6 @@ require_relative "configuration"
6
6
  require_relative "session"
7
7
  require_relative "metadata"
8
8
  require_relative "identifier"
9
- require_relative "proxy_identifier"
10
9
  require_relative "batch_download"
11
10
 
12
11
  Dir[File.expand_path("../responses/*.rb", __FILE__)].each { |m| require m }
data/lib/ezid/error.rb CHANGED
@@ -1,3 +1,11 @@
1
1
  module Ezid
2
2
  class Error < ::RuntimeError; end
3
+
4
+ # The requested identifier was not found
5
+ class IdentifierNotFoundError < Error; end
6
+
7
+ # The requested action is not allowed
8
+ class NotAllowedError < Error; end
9
+
10
+ class DeletionError < Error; end
3
11
  end
@@ -6,53 +6,111 @@ module Ezid
6
6
  #
7
7
  class Identifier
8
8
 
9
- attr_reader :client
10
- attr_accessor :id, :shoulder, :metadata, :state
11
-
12
- private :state, :state=, :id=
13
-
14
- # Attributes to display on inspect
15
- INSPECT_ATTRS = %w( id status target created ).freeze
9
+ attr_accessor :id, :shoulder, :persisted, :deleted
10
+ private :persisted=, :persisted, :deleted=, :deleted
16
11
 
17
12
  class << self
18
13
  attr_accessor :defaults
19
14
 
20
15
  # Creates or mints an identifier (depending on arguments)
21
16
  # @see #save
17
+ # @overload create(id, metadata=nil)
18
+ # Creates an identifier
19
+ # @param id [String] the identifier to create
20
+ # @param metadata [Hash] the metadata to set on the identifier
21
+ # @overload create(metadata=nil)
22
+ # Mints an identifier
23
+ # @deprecated Use {.mint} instead
24
+ # @param metadata [Hash] the metadata to set on the identifier
25
+ # @return [Ezid::Identifier] the new identifier
26
+ # @raise [Ezid::Error]
27
+ def create(*args)
28
+ raise ArgumentError, "`mint` receives 0-2 arguments." if args.size > 2
29
+ if args.first.is_a?(Hash)
30
+ warn "[DEPRECATION] Sending a hash as the first argument to `create` is deprecated and will raise an exception in 2.0. Use `create(id, metadata)` or `mint(metadata)` instead. (called from #{caller.first})"
31
+ metadata = args.first
32
+ id = metadata.delete(:id)
33
+ else
34
+ id, metadata = args
35
+ end
36
+ if id.nil?
37
+ warn "[DEPRECATION] Calling `create` without an id will raise an exception in 2.0. Use `mint` instead. (called from #{caller.first})"
38
+ shoulder = metadata.delete(:shoulder)
39
+ mint(shoulder, metadata)
40
+ else
41
+ new(id, metadata) { |i| i.save }
42
+ end
43
+ end
44
+
45
+ # Mints a new identifier
46
+ # @overload mint(shoulder, metadata=nil)
47
+ # @param shoulder [String] the EZID shoulder on which to mint
48
+ # @param metadata [Hash] the metadata to set on the identifier
49
+ # @overload mint(metadata=nil)
50
+ # @param metadata [Hash] the metadata to set on the identifier
22
51
  # @return [Ezid::Identifier] the new identifier
23
52
  # @raise [Ezid::Error]
24
- def create(attrs = {})
25
- identifier = new(attrs)
26
- identifier.save
53
+ def mint(*args)
54
+ raise ArgumentError, "`mint` receives 0-2 arguments." if args.size > 2
55
+ metadata = args.last.is_a?(Hash) ? args.pop : nil
56
+ new(metadata) do |i|
57
+ i.shoulder = args.first
58
+ i.save
59
+ end
60
+ end
61
+
62
+ # Modifies the metadata of an existing identifier.
63
+ # @param id [String] the EZID identifier
64
+ # @param metadata [Hash] the metadata to update on the identifier
65
+ # @return [Ezid::Identifier] the identifier
66
+ # @raise [Ezid::IdentifierNotFoundError]
67
+ def modify(id, metadata)
68
+ i = allocate
69
+ i.id = id
70
+ i.update_metadata(metadata)
71
+ i.modify!
27
72
  end
28
73
 
29
74
  # Retrieves an identifier
75
+ # @param id [String] the EZID identifier to find
30
76
  # @return [Ezid::Identifier] the identifier
31
- # @raise [Ezid::Error] if the identifier does not exist in EZID
77
+ # @raise [Ezid::IdentifierNotFoundError] if the identifier does not exist in EZID
32
78
  def find(id)
33
- identifier = new(id: id)
34
- identifier.load_metadata
79
+ i = allocate
80
+ i.id = id
81
+ i.load_metadata
35
82
  end
36
83
  end
37
84
 
38
85
  self.defaults = {}
39
86
 
40
- def initialize(args={})
41
- @client = args.delete(:client) || Client.new
42
- @id = args.delete(:id)
43
- @shoulder = args.delete(:shoulder)
44
- @state = :new
45
- self.metadata = Metadata.new args.delete(:metadata)
46
- update_metadata self.class.defaults.merge(args) # deprecate?
87
+ def initialize(*args)
88
+ raise ArgumentError, "`new` receives 0-2 arguments." if args.size > 2
89
+ data = args.last.is_a?(Hash) ? args.pop : nil
90
+ @id = args.first
91
+ apply_default_metadata
92
+ if data
93
+ if shoulder = data.delete(:shoulder)
94
+ warn "[DEPRECATION] The `:shoulder` hash option is deprecated and will raise an exception in 2.0. Use `Ezid::Identifier.mint(shoulder, metadata)` to mint an identifier. (called by #{caller.first})"
95
+ @shoulder = shoulder
96
+ end
97
+ if anvl = data.delete(:metadata)
98
+ update_metadata(anvl)
99
+ end
100
+ update_metadata(data)
101
+ end
102
+ yield self if block_given?
47
103
  end
48
104
 
49
105
  def inspect
50
- attrs = if deleted?
51
- "id=\"#{id}\" DELETED"
52
- else
53
- INSPECT_ATTRS.map { |attr| "#{attr}=#{send(attr).inspect}" }.join(", ")
54
- end
55
- "#<#{self.class.name} #{attrs}>"
106
+ id_val = if id.nil?
107
+ "NEW"
108
+ elsif deleted?
109
+ "#{id} [DELETED]"
110
+ else
111
+ id
112
+ end
113
+ "#<#{self.class.name} id=#{id_val}>"
56
114
  end
57
115
 
58
116
  def to_s
@@ -60,11 +118,16 @@ module Ezid
60
118
  end
61
119
 
62
120
  # Returns the identifier metadata
63
- # @param load [Boolean] - flag to load the metadata from EZID if stale (default: `true`)
64
121
  # @return [Ezid::Metadata] the metadata
65
- def metadata(load = true)
66
- load_metadata if load && stale?
67
- @metadata
122
+ def metadata(_=nil)
123
+ if !_.nil?
124
+ warn "[DEPRECATION] The parameter of `metadata` is deprecated and will be removed in 2.0. (called from #{caller.first})"
125
+ end
126
+ @metadata ||= Metadata.new
127
+ end
128
+
129
+ def remote_metadata
130
+ @remote_metadata ||= Metadata.new
68
131
  end
69
132
 
70
133
  # Persist the identifer and/or metadata to EZID.
@@ -77,27 +140,41 @@ module Ezid
77
140
  def save
78
141
  raise Error, "Cannot save a deleted identifier." if deleted?
79
142
  persist
80
- reset
143
+ reset_metadata
144
+ self
145
+ end
146
+
147
+ # Force a modification of the EZID identifier -- i.e.,
148
+ # assumes previously persisted without confirmation.
149
+ # @return [Ezid::Identifier] the identifier
150
+ # @raise [Ezid::Error] if `id` is nil
151
+ # @raise [Ezid::IdentifierNotFoundError] if EZID identifier does not exist.
152
+ def modify!
153
+ raise Error, "Cannot modify an identifier without and id." if id.nil?
154
+ modify
155
+ persists!
156
+ reset_metadata
157
+ self
81
158
  end
82
159
 
83
160
  # Updates the metadata
84
161
  # @param attrs [Hash] the metadata
85
162
  # @return [Ezid::Identifier] the identifier
86
163
  def update_metadata(attrs={})
87
- attrs.each { |k, v| send("#{k}=", v) }
164
+ metadata.update(attrs)
88
165
  self
89
166
  end
90
167
 
91
168
  # Is the identifier persisted?
92
169
  # @return [Boolean]
93
170
  def persisted?
94
- state == :persisted
171
+ !!persisted
95
172
  end
96
173
 
97
174
  # Has the identifier been deleted?
98
175
  # @return [Boolean]
99
176
  def deleted?
100
- state == :deleted
177
+ !!deleted
101
178
  end
102
179
 
103
180
  # Updates the metadata and saves the identifier
@@ -111,24 +188,26 @@ module Ezid
111
188
 
112
189
  # @deprecated Use {#load_metadata} instead.
113
190
  def reload
114
- warn "[DEPRECATION] `reload` is deprecated and will be removed in version 2.0. Use `load_metadata` instead."
191
+ warn "[DEPRECATION] `reload` is deprecated and will be removed in version 2.0. Use `load_metadata` instead. (called from #{caller.first})"
115
192
  load_metadata
116
193
  end
117
194
 
118
- # Loads the metadata from EZID (local changes will be lost!)
195
+ # Loads the metadata from EZID
119
196
  # @return [Ezid::Identifier] the identifier
120
197
  # @raise [Ezid::Error]
121
198
  def load_metadata
122
199
  response = client.get_identifier_metadata(id)
123
- self.metadata = Metadata.new(response.metadata)
124
- self.state = :persisted
200
+ # self.remote_metadata = Metadata.new(response.metadata)
201
+ remote_metadata.replace(response.metadata)
202
+ persists!
125
203
  self
126
204
  end
127
205
 
128
206
  # Empties the (local) metadata (changes will be lost!)
129
207
  # @return [Ezid::Identifier] the identifier
130
208
  def reset
131
- clear_metadata
209
+ warn "[DEPRECATION] `reset` is deprecated and will be removed in 2.0. Use `reset_metadata` instead. (called from #{caller.first})"
210
+ reset_metadata
132
211
  self
133
212
  end
134
213
 
@@ -139,8 +218,10 @@ module Ezid
139
218
  def delete
140
219
  raise Error, "Only persisted, reserved identifiers may be deleted: #{inspect}." unless deletable?
141
220
  client.delete_identifier(id)
142
- self.state = :deleted
143
- reset
221
+ reset_metadata
222
+ self.deleted = true
223
+ self.persisted = false
224
+ self
144
225
  end
145
226
 
146
227
  # Is the identifier reserved?
@@ -190,22 +271,32 @@ module Ezid
190
271
  self.status = Status::PUBLIC
191
272
  end
192
273
 
274
+ def client
275
+ @client ||= Client.new
276
+ end
277
+
278
+ def reset_metadata
279
+ metadata.clear unless metadata.empty?
280
+ remote_metadata.clear unless remote_metadata.empty?
281
+ end
282
+
193
283
  protected
194
284
 
195
- def method_missing(method, *args)
196
- metadata.send(method, *args)
285
+ def method_missing(*args)
286
+ local_or_remote_metadata(*args)
197
287
  rescue NoMethodError
198
288
  super
199
289
  end
200
290
 
201
291
  private
202
292
 
203
- def stale?
204
- persisted? && metadata(false).empty?
205
- end
206
-
207
- def clear_metadata
208
- metadata(false).clear
293
+ def local_or_remote_metadata(*args)
294
+ value = metadata.send(*args)
295
+ if value.nil? && persisted?
296
+ load_metadata if remote_metadata.empty?
297
+ value = remote_metadata.send(*args)
298
+ end
299
+ value
209
300
  end
210
301
 
211
302
  def modify
@@ -227,7 +318,15 @@ module Ezid
227
318
 
228
319
  def persist
229
320
  persisted? ? modify : create_or_mint
230
- self.state = :persisted
321
+ persists!
322
+ end
323
+
324
+ def persists!
325
+ self.persisted = true
326
+ end
327
+
328
+ def apply_default_metadata
329
+ update_metadata(self.class.defaults)
231
330
  end
232
331
 
233
332
  end