ddr-models 2.6.0.rc1 → 2.6.0.rc2

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: edadac3d26e329ebd8cd6ce67e3d92c10e2233da
4
- data.tar.gz: 70aefbe23b138eedb961dd6cc24886a3ad4691ed
3
+ metadata.gz: 2a6aaa85c1cec8d9127e06e4db353d27bff2242f
4
+ data.tar.gz: d00f7e80d79c688e814ea6f3db6f07acf011cf09
5
5
  SHA512:
6
- metadata.gz: 73f1a830f3a2763d9a867505260286d5c50836d530551d758b92351339af451c67eb4572f5924501017d271bedbef692a1ff9981469f589c4fe796e187e05bbe
7
- data.tar.gz: 1a2541c01cdf459f64ec0b9ee291479f77446b845da398c13038d721c48c69d9a3641a25f83a56ea7f673d555e096f99ff2c1a670705d298dc773b444389c51e
6
+ metadata.gz: 7a9dbb8d4bc4b4e4ecba17969d8a1dea7f10fc23da40e9002f8abfb86cce07005f461f100ebf3fd9dc70ef1485f40124b028b2df39361ba60d1cb091d481880f
7
+ data.tar.gz: 28eba8f8e3b45a2b19155e138a7886e97e6884b2296c4d344a9c11d1e1c2e1a01e07f9ab6bae1f2c1353b2073e6953a3fff270ff17505b842d52264a04a83af6
@@ -13,10 +13,16 @@ ActiveSupport::Notifications.subscribe(Ddr::Notifications::CREATION, Ddr::Events
13
13
 
14
14
  # Update
15
15
  ActiveSupport::Notifications.subscribe(Ddr::Notifications::UPDATE, Ddr::Events::UpdateEvent)
16
+ ActiveSupport::Notifications.subscribe("assign.permanent_id", Ddr::Events::UpdateEvent)
16
17
 
17
18
  # Deletion
18
19
  ActiveSupport::Notifications.subscribe(Ddr::Notifications::DELETION, Ddr::Events::DeletionEvent)
19
20
  ActiveSupport::Notifications.subscribe(/destroy\.\w+/, Ddr::Events::DeletionEvent)
21
+ ActiveSupport::Notifications.subscribe(/destroy\.\w+/, Ddr::Models::PermanentId)
20
22
 
21
23
  # Deaccession
22
24
  ActiveSupport::Notifications.subscribe(/deaccession\.\w+/, Ddr::Events::DeaccessionEvent)
25
+ ActiveSupport::Notifications.subscribe(/deaccession\.\w+/, Ddr::Models::PermanentId)
26
+
27
+ # Workflow
28
+ ActiveSupport::Notifications.subscribe(/workflow/, Ddr::Models::PermanentId)
data/lib/ddr/models.rb CHANGED
@@ -63,6 +63,7 @@ module Ddr
63
63
  autoload :HasThumbnail
64
64
  autoload :Indexing
65
65
  autoload :NotFoundError, 'ddr/models/error'
66
+ autoload :PermanentId
66
67
  autoload :SolrDocument
67
68
  autoload :StructDiv
68
69
  autoload :Structure
@@ -119,6 +120,14 @@ module Ddr
119
120
  false
120
121
  end
121
122
 
123
+ mattr_accessor :auto_assign_permanent_id do
124
+ false
125
+ end
126
+
127
+ mattr_accessor :auto_update_permanent_id do
128
+ false
129
+ end
130
+
122
131
  # Yields an object with module configuration accessors
123
132
  def self.configure
124
133
  yield self
@@ -24,7 +24,7 @@ module Ddr
24
24
 
25
25
  around_save :notify_save
26
26
  around_save :notify_workflow_change, if: [:workflow_state_changed?, :persisted?]
27
- after_create :notify_create
27
+ after_create :assign_permanent_id, if: :assign_permanent_id?
28
28
  around_deaccession :notify_deaccession
29
29
  around_destroy :notify_destroy
30
30
 
@@ -136,11 +136,6 @@ module Ddr
136
136
  end
137
137
  end
138
138
 
139
- def notify_create
140
- ActiveSupport::Notifications.instrument("create.#{self.class.to_s.underscore}",
141
- pid: pid)
142
- end
143
-
144
139
  def notify_deaccession
145
140
  ActiveSupport::Notifications.instrument("deaccession.#{self.class.to_s.underscore}",
146
141
  pid: pid,
@@ -157,6 +152,14 @@ module Ddr
157
152
  end
158
153
  end
159
154
 
155
+ def assign_permanent_id?
156
+ permanent_id.nil? && Ddr::Models.auto_assign_permanent_id
157
+ end
158
+
159
+ def assign_permanent_id
160
+ PermanentId.assign!(self)
161
+ end
162
+
160
163
  end
161
164
  end
162
165
  end
@@ -0,0 +1,263 @@
1
+ require 'ezid-client'
2
+
3
+ module Ddr::Models
4
+ class PermanentId
5
+
6
+ class Error < Ddr::Models::Error; end
7
+ class AssignmentFailed < Error; end
8
+ class RepoObjectNotPersisted < Error; end
9
+ class AlreadyAssigned < AssignmentFailed; end
10
+ class IdentifierNotAssigned < Error; end
11
+ class IdentifierNotFound < Error; end
12
+
13
+ PERMANENT_URL_BASE = "https://idn.duke.edu/".freeze
14
+ DEFAULT_STATUS = Ezid::Status::RESERVED
15
+ DEFAULT_EXPORT = "no".freeze
16
+ DEFAULT_PROFILE = "dc".freeze
17
+ DEFAULT_TARGET = "https://repository.duke.edu/id/%s"
18
+ FCREPO3_PID = "fcrepo3.pid".freeze
19
+ DELETED = "deleted".freeze
20
+ DEACCESSIONED = "deaccessioned".freeze
21
+
22
+ class_attribute :identifier_class, :identifier_repo_id_field
23
+
24
+ self.identifier_class = Ezid::Identifier
25
+ self.identifier_class.defaults = {
26
+ profile: DEFAULT_PROFILE,
27
+ export: DEFAULT_EXPORT,
28
+ status: DEFAULT_STATUS,
29
+ }
30
+
31
+ self.identifier_repo_id_field = FCREPO3_PID
32
+
33
+ # ActiveSupport::Notifications event handler
34
+ def self.call(*args)
35
+ event = ActiveSupport::Notifications::Event.new(*args)
36
+ repo_id, identifier_id, reason = event.payload.values_at(:pid, :permanent_id, :reason)
37
+ case event.name
38
+ when /workflow/
39
+ update!(repo_id) if auto_update?
40
+ when /^deaccession/
41
+ if auto_update? && identifier_id
42
+ deaccession!(repo_id, identifier_id, reason)
43
+ end
44
+ when /^destroy/
45
+ if auto_update? && identifier_id
46
+ delete!(repo_id, identifier_id, reason)
47
+ end
48
+ end
49
+ end
50
+
51
+ def self.auto_update?
52
+ Ddr::Models.auto_update_permanent_id
53
+ end
54
+
55
+ def self.deaccession!(repo_object_or_id, identifier_or_id, reason = nil)
56
+ new(repo_object_or_id, identifier_or_id).deaccession!(reason)
57
+ end
58
+
59
+ def self.delete!(repo_object_or_id, identifier_or_id, reason = nil)
60
+ new(repo_object_or_id, identifier_or_id).delete!(reason)
61
+ end
62
+
63
+ def self.update!(repo_object_or_id)
64
+ perm_id = new(repo_object_or_id)
65
+ perm_id.update! if perm_id.assigned?
66
+ end
67
+
68
+ def self.assign!(repo_object_or_id, identifier_or_id = nil)
69
+ new(repo_object_or_id, identifier_or_id).assign!
70
+ end
71
+
72
+ def self.assigned(repo_object_or_id)
73
+ perm_id = new(repo_object_or_id)
74
+ perm_id.assigned? ? perm_id : nil
75
+ end
76
+
77
+ def initialize(repo_object_or_id, identifier_or_id = nil)
78
+ case repo_object_or_id
79
+ when ActiveFedora::Base
80
+ raise RepoObjectNotPersisted, "Repository object must be persisted." if repo_object_or_id.new_record?
81
+ @repo_object = repo_object_or_id
82
+ when String, nil
83
+ @repo_id = repo_object_or_id
84
+ else
85
+ raise TypeError, "#{repo_object_or_id.class} is not expected as the first argument."
86
+ end
87
+
88
+ case identifier_or_id
89
+ when identifier_class
90
+ @identifier = identifier_or_id
91
+ when String, nil
92
+ @identifier_id = identifier_or_id
93
+ else
94
+ raise TypeError, "#{identifier_or_id.class} is not expected as the second argument."
95
+ end
96
+ end
97
+
98
+ def repo_object
99
+ @repo_object ||= ActiveFedora::Base.find(repo_id)
100
+ end
101
+
102
+ def repo_id
103
+ @repo_id ||= @repo_object && @repo_object.id
104
+ end
105
+
106
+ def assign!(id = nil)
107
+ ActiveSupport::Notifications.instrument("assign.permanent_id", pid: repo_object.id) do |payload|
108
+ assign(id)
109
+ software = [ "ddr-models #{Ddr::Models::VERSION}", Ezid::Client.version ].join("; ")
110
+ detail = <<-EOS
111
+ Permanent ID: #{repo_object.permanent_id}
112
+ Permanent URL: #{repo_object.permanent_url}
113
+
114
+ EZID Metadata:
115
+ #{identifier.metadata}
116
+ EOS
117
+ payload.merge!(summary: "Permanent ID assignment",
118
+ detail: detail,
119
+ software: software,
120
+ permanent_id: identifier.id)
121
+ end
122
+ end
123
+
124
+ def assigned?
125
+ repo_object.permanent_id
126
+ end
127
+
128
+ def update!
129
+ ActiveSupport::Notifications.instrument("update.permanent_id", pid: repo_object.id) do |payload|
130
+ update
131
+ payload.merge!(permanent_id: identifier.id)
132
+ end
133
+ end
134
+
135
+ def deaccession!(reason = nil)
136
+ delete_or_make_unavailable(reason || DEACCESSIONED)
137
+ end
138
+
139
+ def delete!(reason = nil)
140
+ delete_or_make_unavailable(reason || DELETED)
141
+ end
142
+
143
+ def identifier
144
+ if @identifier.nil?
145
+ if identifier_id
146
+ @identifier = find_identifier(identifier_id)
147
+ elsif assigned?
148
+ @identifier = find_identifier(repo_object.permanent_id)
149
+ end
150
+ end
151
+ @identifier
152
+ end
153
+
154
+ def identifier_id
155
+ @identifier_id ||= @identifier && @identifier.id
156
+ end
157
+
158
+ def set_permanent_url
159
+ repo_object.permanent_url = PERMANENT_URL_BASE + identifier.id
160
+ end
161
+
162
+ def set_metadata!
163
+ set_metadata
164
+ save
165
+ self
166
+ end
167
+
168
+ def set_metadata
169
+ set_target
170
+ set_status
171
+ set_identifier_repo_id
172
+ end
173
+
174
+ def set_target
175
+ self.target = DEFAULT_TARGET % id
176
+ end
177
+
178
+ def set_identifier_repo_id
179
+ self.identifier_repo_id = repo_object.id
180
+ end
181
+
182
+ def identifier_repo_id=(val)
183
+ if identifier_repo_id
184
+ raise Error, "Identifier repository id already set to \"#{identifier_repo_id}\"; cannot change."
185
+ end
186
+ self[identifier_repo_id_field] = val
187
+ end
188
+
189
+ def identifier_repo_id
190
+ self[identifier_repo_id_field]
191
+ end
192
+
193
+ def set_status!
194
+ save if set_status
195
+ end
196
+
197
+ def set_status
198
+ if repo_object.published? && !public?
199
+ public!
200
+ elsif repo_object.unpublished? && public?
201
+ unavailable!("not published")
202
+ end
203
+ end
204
+
205
+ protected
206
+
207
+ def method_missing(name, *args, &block)
208
+ identifier.send(name, *args, &block)
209
+ end
210
+
211
+ private
212
+
213
+ def find_identifier(ark)
214
+ identifier_class.find(ark)
215
+ rescue Ezid::IdentifierNotFoundError => e
216
+ raise IdentifierNotFound, e.message
217
+ end
218
+
219
+ def mint_identifier(*args)
220
+ identifier_class.mint(*args)
221
+ end
222
+
223
+ def update
224
+ if !assigned?
225
+ raise IdentifierNotAssigned,
226
+ "Cannot update identifier for repository object \"#{repo_object.id}\"; not assigned."
227
+ end
228
+ set_status!
229
+ end
230
+
231
+ def assign(id = nil)
232
+ if assigned?
233
+ raise AlreadyAssigned,
234
+ "Repository object \"#{repo_object.id}\" has already been assigned permanent id \"#{repo_object.permanent_id}\"."
235
+ end
236
+ @identifier = case id
237
+ when identifier_class
238
+ id
239
+ when String
240
+ find_identifier(id)
241
+ when nil
242
+ mint_identifier
243
+ end
244
+ repo_object.reload
245
+ repo_object.permanent_id = identifier.id
246
+ repo_object.permanent_url = PERMANENT_URL_BASE + identifier.id
247
+ repo_object.save(validate: false)
248
+ set_metadata!
249
+ end
250
+
251
+ def delete_or_make_unavailable(reason)
252
+ if repo_id && identifier_repo_id && ( identifier_repo_id != repo_id )
253
+ raise Error, "Identifier \"#{identifier_id}\" is assigned to a different repository object \"#{repo_id}\"."
254
+ end
255
+ if reserved?
256
+ delete
257
+ else
258
+ unavailable!(reason) && save
259
+ end
260
+ end
261
+
262
+ end
263
+ end
@@ -1,5 +1,5 @@
1
1
  module Ddr
2
2
  module Models
3
- VERSION = "2.6.0.rc1"
3
+ VERSION = "2.6.0.rc2"
4
4
  end
5
5
  end
@@ -0,0 +1,440 @@
1
+ module Ddr::Models
2
+ RSpec.describe PermanentId do
3
+
4
+ describe "auto assigment" do
5
+ let(:obj) { FactoryGirl.create(:item) }
6
+ describe "when enabled" do
7
+ let!(:id) { described_class.identifier_class.new("foo") }
8
+ before do
9
+ allow(id).to receive(:save) { nil }
10
+ allow(described_class.identifier_class).to receive(:mint) { id }
11
+ allow(described_class.identifier_class).to receive(:find).with("foo") { id }
12
+ allow(Ddr::Models).to receive(:auto_assign_permanent_id) { true }
13
+ end
14
+ after do
15
+ obj.permanent_id = nil
16
+ obj.save!
17
+ end
18
+ it "assigns a permanent id to the object" do
19
+ obj.reload
20
+ expect(obj.permanent_id).to eq("foo")
21
+ expect(obj.permanent_url).to eq("https://idn.duke.edu/foo")
22
+ end
23
+ end
24
+ describe "when disabled" do
25
+ before do
26
+ allow(Ddr::Models).to receive(:auto_assign_permanent_id) { false }
27
+ end
28
+ it "does not assign a permanent id to the object" do
29
+ expect(obj.reload.permanent_id).to be_nil
30
+ end
31
+ end
32
+ end
33
+
34
+ describe "assignment" do
35
+ let(:obj) { FactoryGirl.create(:item) }
36
+ let!(:id) { described_class.identifier_class.new("foo") }
37
+ before do
38
+ allow(id).to receive(:save) { nil }
39
+ allow(described_class.identifier_class).to receive(:mint) { id }
40
+ allow(described_class.identifier_class).to receive(:find).with("foo") { id }
41
+ end
42
+ after do
43
+ obj.permanent_id = nil
44
+ obj.save!
45
+ end
46
+ it "creates an update event" do
47
+ expect { described_class.assign!(obj) }.to change(Ddr::Events::UpdateEvent, :count).to(1)
48
+ end
49
+ end
50
+
51
+ describe "auto updating" do
52
+ let(:obj) { Item.create(pid: "test:1") }
53
+ let!(:id) { described_class.identifier_class.new("foo") }
54
+ before do
55
+ allow(described_class.identifier_class).to receive(:find).with("foo") { id }
56
+ end
57
+ describe "when enabled" do
58
+ before do
59
+ allow(Ddr::Models).to receive(:auto_update_permanent_id) { true }
60
+ end
61
+ describe "when the object workflow state changes" do
62
+ describe "and the object has a permanent id" do
63
+ before do
64
+ allow(id).to receive(:save) { nil }
65
+ obj.permanent_id = "foo"
66
+ end
67
+ after do
68
+ obj.permanent_id = nil
69
+ obj.save!
70
+ end
71
+ it "updates the permanent id" do
72
+ expect { obj.publish! }.to change(id, :status).to("public")
73
+ end
74
+ end
75
+ describe "and the object does not have a permanent id" do
76
+ it "does not update the permanent id" do
77
+ expect { obj.publish! }.not_to change(id, :status)
78
+ end
79
+ end
80
+ end
81
+ describe "when the object workflow state does not change" do
82
+ it "does not update the permanent id" do
83
+ expect { obj.save! }.not_to change(id, :status)
84
+ end
85
+ end
86
+ end
87
+ describe "when disabled" do
88
+ before do
89
+ allow(Ddr::Models).to receive(:auto_update_permanent_id) { false }
90
+ end
91
+ describe "when the object workflow state changes" do
92
+ describe "and the object has a permanent id" do
93
+ before do
94
+ allow(id).to receive(:save) { nil }
95
+ obj.permanent_id = "foo"
96
+ end
97
+ after do
98
+ obj.permanent_id = nil
99
+ obj.save!
100
+ end
101
+ it "does not update the permanent id" do
102
+ expect { obj.publish! }.not_to change(id, :status)
103
+ end
104
+ end
105
+ describe "and the object does not have a permanent id" do
106
+ it "does not update the permanent id" do
107
+ expect { obj.publish! }.not_to change(id, :status)
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
113
+
114
+ describe "auto deleting / marking unavailable" do
115
+ describe "when enabled" do
116
+ before do
117
+ allow(Ddr::Models).to receive(:auto_update_permanent_id) { true }
118
+ end
119
+ describe "when an object has a permanent id" do
120
+ let(:obj) { Item.create(pid: "test:1", permanent_id: "foo") }
121
+ let!(:id) { described_class.identifier_class.new("foo") }
122
+ before do
123
+ allow(id).to receive(:save) { nil }
124
+ allow(described_class.identifier_class).to receive(:find).with("foo") { id }
125
+ end
126
+ describe "and it's deacessioned" do
127
+ specify {
128
+ expect(described_class).to receive(:deaccession!).with("test:1", "foo", nil) { nil }
129
+ obj.deaccession
130
+ }
131
+ end
132
+ describe "and it's deleted" do
133
+ specify {
134
+ expect(described_class).not_to receive(:delete!)
135
+ expect(described_class).not_to receive(:deaccession!)
136
+ obj.send(:delete)
137
+ }
138
+ end
139
+ describe "and it's destroyed" do
140
+ specify {
141
+ expect(described_class).to receive(:delete!).with("test:1", "foo", nil) { nil }
142
+ obj.destroy
143
+ }
144
+ end
145
+ end
146
+ describe "when an object does not have a permanent id" do
147
+ let(:obj) { FactoryGirl.create(:item) }
148
+ describe "and it's deacessioned" do
149
+ specify {
150
+ expect(described_class).not_to receive(:deaccession!)
151
+ obj.deaccession
152
+ }
153
+ end
154
+ describe "and it's deleted" do
155
+ specify {
156
+ expect(described_class).not_to receive(:deaccession!)
157
+ expect(described_class).not_to receive(:delete!)
158
+ obj.send(:delete)
159
+ }
160
+ end
161
+ describe "and it's destroyed" do
162
+ specify {
163
+ expect(described_class).not_to receive(:delete!)
164
+ obj.destroy
165
+ }
166
+ end
167
+ end
168
+ end
169
+ describe "when disabled" do
170
+ before do
171
+ allow(Ddr::Models).to receive(:auto_update_permanent_id) { false }
172
+ end
173
+ describe "when an object has a permanent id" do
174
+ let(:obj) { Item.create(pid: "test:1", permanent_id: "foo") }
175
+ let!(:id) { described_class.identifier_class.new("foo") }
176
+ before do
177
+ allow(id).to receive(:save) { nil }
178
+ allow(described_class.identifier_class).to receive(:find).with("foo") { id }
179
+ end
180
+ describe "and it's deacessioned" do
181
+ specify {
182
+ expect(described_class).not_to receive(:deaccession!)
183
+ obj.deaccession
184
+ }
185
+ end
186
+ describe "and it's destroyed" do
187
+ specify {
188
+ expect(described_class).not_to receive(:delete!)
189
+ obj.destroy
190
+ }
191
+ end
192
+ end
193
+ end
194
+ end
195
+
196
+ describe "constructor" do
197
+ describe "when the object is new" do
198
+ let(:obj) { FactoryGirl.build(:item) }
199
+ it "raises an error" do
200
+ expect { described_class.new(obj) }.to raise_error(PermanentId::RepoObjectNotPersisted)
201
+ end
202
+ end
203
+ describe "when passed a repo object id" do
204
+ let(:obj) { FactoryGirl.create(:item) }
205
+ subject { described_class.new(obj.id) }
206
+ its(:repo_id) { is_expected.to eq(obj.id) }
207
+ end
208
+ end
209
+
210
+ describe "instance methods" do
211
+ let(:obj) { FactoryGirl.create(:item) }
212
+ subject { described_class.new(obj) }
213
+
214
+ describe "#assign!" do
215
+ describe "when the object already has a permanent identifier" do
216
+ before { obj.permanent_id = "foo" }
217
+ it "raises an error" do
218
+ expect { subject.assign! }.to raise_error(PermanentId::AlreadyAssigned)
219
+ expect { subject.assign!("bar") }.to raise_error(PermanentId::AlreadyAssigned)
220
+ end
221
+ end
222
+ describe "when the object does not have a permanent identifier" do
223
+ let(:obj) { FactoryGirl.create(:item) }
224
+ let!(:id) { described_class.identifier_class.new("foo") }
225
+ before do
226
+ allow(described_class.identifier_class).to receive(:find).with("foo") { id }
227
+ allow(id).to receive(:save) { nil }
228
+ allow(obj).to receive(:save) { true }
229
+ end
230
+ describe "when passed an ARK" do
231
+ before do
232
+ subject.assign!("foo")
233
+ end
234
+ it "assigns the ARK" do
235
+ expect(obj.permanent_id).to eq("foo")
236
+ end
237
+ it "sets the target on the identifier" do
238
+ expect(id.target).to eq("https://repository.duke.edu/id/foo")
239
+ end
240
+ it "sets the status on the identifier" do
241
+ expect(id.status).to eq("reserved")
242
+ end
243
+ it "sets the repository id on the identifier" do
244
+ expect(id["fcrepo3.pid"]).to eq(obj.id)
245
+ end
246
+ end
247
+ describe "when not passed an ARK" do
248
+ before do
249
+ subject.assign!("foo")
250
+ allow(described_class.identifier_class).to receive(:mint) { id }
251
+ end
252
+ it "mints and assigns an ARK" do
253
+ expect(obj.permanent_id).to eq("foo")
254
+ end
255
+ it "sets the target on the identifier" do
256
+ expect(id.target).to eq("https://repository.duke.edu/id/foo")
257
+ end
258
+ it "sets the status on the identifier" do
259
+ expect(id.status).to eq("reserved")
260
+ end
261
+ it "sets the repository id on the identifier" do
262
+ expect(id["fcrepo3.pid"]).to eq(obj.id)
263
+ end
264
+ end
265
+ end
266
+ end
267
+
268
+ describe "#update!" do
269
+ describe "when the object has not been assigned a permanent id" do
270
+ it "raises an error" do
271
+ expect { subject.update! }.to raise_error(PermanentId::IdentifierNotAssigned)
272
+ end
273
+ end
274
+ describe "when the object has been assigned a permanent id" do
275
+ let!(:id) { described_class.identifier_class.new("foo") }
276
+ before do
277
+ allow(described_class.identifier_class).to receive(:find).with("foo") { id }
278
+ obj.permanent_id = "foo"
279
+ end
280
+ it "sets the status on the permanent id" do
281
+ expect(subject).to receive(:set_status!) { nil }
282
+ subject.update!
283
+ end
284
+ end
285
+ end
286
+
287
+ describe "#deaccession!" do
288
+ let!(:id) { described_class.identifier_class.new("foo") }
289
+ subject { described_class.new("test:1", "foo") }
290
+ before do
291
+ allow(described_class.identifier_class).to receive(:find).with("foo") { id }
292
+ allow(id).to receive(:save) { nil }
293
+ end
294
+ specify {
295
+ expect(id).to receive(:delete)
296
+ subject.deaccession!
297
+ }
298
+ describe " when the identifier is not reserved" do
299
+ before { id.public! }
300
+ specify {
301
+ expect { subject.deaccession! }.to change(id, :status).to("unavailable | deaccessioned")
302
+ }
303
+ end
304
+ describe "when the identifier is associated with another repo id" do
305
+ before { subject.identifier_repo_id = "test:2" }
306
+ specify {
307
+ expect { subject.deaccession! }.to raise_error(PermanentId::Error)
308
+ }
309
+ end
310
+ end
311
+
312
+ describe "#delete!" do
313
+ let!(:id) { described_class.identifier_class.new("foo") }
314
+ subject { described_class.new("test:1", "foo") }
315
+ before do
316
+ allow(described_class.identifier_class).to receive(:find).with("foo") { id }
317
+ end
318
+ specify {
319
+ expect(id).to receive(:delete)
320
+ subject.delete!
321
+ }
322
+ describe " when the identifier is not reserved" do
323
+ before do
324
+ allow(id).to receive(:save) { nil }
325
+ id.public!
326
+ end
327
+ specify {
328
+ expect { subject.delete! }.to change(id, :status).to("unavailable | deleted")
329
+ }
330
+ end
331
+ describe "when the identifier is associated with another repo id" do
332
+ before { subject.identifier_repo_id = "test:2" }
333
+ specify {
334
+ expect { subject.delete! }.to raise_error(PermanentId::Error)
335
+ }
336
+ end
337
+ end
338
+
339
+ describe "identifier metadata" do
340
+ let(:obj) { Item.create(pid: "test:1") }
341
+ let!(:id) { described_class.identifier_class.new("foo") }
342
+ subject { described_class.new(obj) }
343
+ before do
344
+ allow(subject).to receive(:identifier) { id }
345
+ end
346
+ describe "#identifier_repo_id" do
347
+ before do
348
+ id["fcrepo3.pid"] = "test:1"
349
+ end
350
+ its(:identifier_repo_id) { is_expected.to eq("test:1") }
351
+ end
352
+ describe "#identifier_repo_id=" do
353
+ specify {
354
+ subject.identifier_repo_id = "test:1"
355
+ expect(id["fcrepo3.pid"]).to eq("test:1")
356
+ }
357
+ describe "when a value was previously assigned" do
358
+ before { subject.identifier_repo_id = "test:1" }
359
+ specify {
360
+ expect { subject.identifier_repo_id = "test:2" }.to raise_error(PermanentId::Error)
361
+ }
362
+ end
363
+ end
364
+ describe "#set_identifier_repo_id" do
365
+ specify {
366
+ subject.set_identifier_repo_id
367
+ expect(subject.identifier_repo_id).to eq("test:1")
368
+ }
369
+ end
370
+ describe "#set_target" do
371
+ specify {
372
+ subject.set_target
373
+ expect(subject.target).to eq("https://repository.duke.edu/id/foo")
374
+ }
375
+ end
376
+ describe "#set_status" do
377
+ describe "when object is published" do
378
+ before { obj.workflow_state = "published" }
379
+ describe "and identifier is public" do
380
+ before { subject.public! }
381
+ it "does not change" do
382
+ expect { subject.set_status }.not_to change(subject, :status)
383
+ end
384
+ end
385
+ describe "and identifier is reserved" do
386
+ it "changes to public" do
387
+ expect { subject.set_status }.to change(subject, :status).to("public")
388
+ end
389
+ end
390
+ describe "and identifier is unavailable" do
391
+ before { subject.unavailable! }
392
+ it "changes to public" do
393
+ expect { subject.set_status }.to change(subject, :status).to("public")
394
+ end
395
+ end
396
+ end
397
+ describe "when object is unpublished" do
398
+ before { obj.workflow_state = "unpublished" }
399
+ describe "and identifier is public" do
400
+ before { subject.public! }
401
+ it "changes to unavailable" do
402
+ expect { subject.set_status }.to change(subject, :status).to("unavailable | not published")
403
+ end
404
+ end
405
+ describe "and identifier is reserved" do
406
+ it "does not change" do
407
+ expect { subject.set_status }.not_to change(subject, :status)
408
+ end
409
+ end
410
+ describe "and identifier is unavailable" do
411
+ before { subject.unavailable! }
412
+ it "does not change" do
413
+ expect { subject.set_status }.not_to change(subject, :status)
414
+ end
415
+ end
416
+ end
417
+ describe "when object has no workflow state" do
418
+ describe "and identifier is public" do
419
+ before { subject.public! }
420
+ it "does not change" do
421
+ expect { subject.set_status }.not_to change(subject, :status)
422
+ end
423
+ end
424
+ describe "and identifier is reserved" do
425
+ it "does not change" do
426
+ expect { subject.set_status }.not_to change(subject, :status)
427
+ end
428
+ end
429
+ describe "and identifier is unavailable" do
430
+ before { subject.unavailable! }
431
+ it "does not change" do
432
+ expect { subject.set_status }.not_to change(subject, :status)
433
+ end
434
+ end
435
+ end
436
+ end
437
+ end
438
+ end
439
+ end
440
+ end
@@ -6,6 +6,36 @@ RSpec.shared_examples "a DDR model" do
6
6
  it_behaves_like "an object that has a display title"
7
7
  it_behaves_like "an object that has identifiers"
8
8
 
9
+ describe "permanent ID assignment" do
10
+ describe "when auto assignment is enabled" do
11
+ before do
12
+ allow(Ddr::Models).to receive(:auto_assign_permanent_id) { true }
13
+ end
14
+ describe "and a permanent ID is pre-assigned" do
15
+ before do
16
+ subject.permanent_id = "foo"
17
+ end
18
+ it "does not assign a permanent ID" do
19
+ expect { subject.save(validate: false) }.not_to change(subject, :permanent_id)
20
+ end
21
+ end
22
+ describe "and no permanent ID has been pre-assigned" do
23
+ before do
24
+ expect(Ddr::Models::PermanentId).to receive(:assign!).with(subject) { nil }
25
+ subject.save(validate: false)
26
+ end
27
+ end
28
+ end
29
+ describe "when auto assignment is disabled" do
30
+ before do
31
+ allow(Ddr::Models).to receive(:auto_assign_permanent_id) { false }
32
+ end
33
+ it "does not assign a permanent ID" do
34
+ expect { subject.save(validate: false) }.not_to change(subject, :permanent_id)
35
+ end
36
+ end
37
+ end
38
+
9
39
  describe "notification on save" do
10
40
  let(:events) { [] }
11
41
  before {
@@ -30,26 +60,6 @@ RSpec.shared_examples "a DDR model" do
30
60
  end
31
61
  end
32
62
 
33
- describe "notification on create" do
34
- let(:events) { [] }
35
- before {
36
- @subscriber = ActiveSupport::Notifications.subscribe("create.#{described_class.to_s.underscore}") do |name, start, finish, id, payload|
37
- events << payload
38
- end
39
- }
40
- after {
41
- ActiveSupport::Notifications.unsubscribe(@subscriber)
42
- }
43
- it "happens after create" do
44
- subject.title = [ "My Title Changed" ]
45
- subject.save
46
- subject.title = [ "My Title Changed Again" ]
47
- subject.save
48
- expect(events.size).to eq(1)
49
- expect(events.first[:pid]).to eq(subject.pid)
50
- end
51
- end
52
-
53
63
  describe "notification on workflow state change" do
54
64
  let(:events) { [] }
55
65
  before {
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ddr-models
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.6.0.rc1
4
+ version: 2.6.0.rc2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jim Coble
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-12-19 00:00:00.000000000 Z
12
+ date: 2017-01-04 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -552,6 +552,7 @@ files:
552
552
  - lib/ddr/models/licenses/inherited_license.rb
553
553
  - lib/ddr/models/licenses/license.rb
554
554
  - lib/ddr/models/licenses/parent_license.rb
555
+ - lib/ddr/models/permanent_id.rb
555
556
  - lib/ddr/models/solr_document.rb
556
557
  - lib/ddr/models/struct_div.rb
557
558
  - lib/ddr/models/structure.rb
@@ -697,6 +698,7 @@ files:
697
698
  - spec/models/indexing_spec.rb
698
699
  - spec/models/item_spec.rb
699
700
  - spec/models/license_spec.rb
701
+ - spec/models/permanent_id_spec.rb
700
702
  - spec/models/solr_document_spec.rb
701
703
  - spec/models/struct_div_spec.rb
702
704
  - spec/models/structure_spec.rb
@@ -874,6 +876,7 @@ test_files:
874
876
  - spec/models/indexing_spec.rb
875
877
  - spec/models/item_spec.rb
876
878
  - spec/models/license_spec.rb
879
+ - spec/models/permanent_id_spec.rb
877
880
  - spec/models/solr_document_spec.rb
878
881
  - spec/models/struct_div_spec.rb
879
882
  - spec/models/structure_spec.rb