ddr-models 2.6.0.rc1 → 2.6.0.rc2

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 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