hydra-pcdm 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +4 -0
  3. data/Gemfile +0 -4
  4. data/README.md +2 -2
  5. data/hydra-pcdm.gemspec +2 -1
  6. data/lib/hydra/pcdm.rb +21 -30
  7. data/lib/hydra/pcdm/ancestor_checker.rb +18 -0
  8. data/lib/hydra/pcdm/collection_indexer.rb +2 -2
  9. data/lib/hydra/pcdm/deep_member_iterator.rb +31 -0
  10. data/lib/hydra/pcdm/models/concerns/collection_behavior.rb +20 -57
  11. data/lib/hydra/pcdm/models/concerns/object_behavior.rb +12 -37
  12. data/lib/hydra/pcdm/models/concerns/pcdm_behavior.rb +34 -0
  13. data/lib/hydra/pcdm/object_indexer.rb +1 -1
  14. data/lib/hydra/pcdm/services/file/get_mime_type.rb +1 -1
  15. data/lib/hydra/pcdm/validators.rb +8 -0
  16. data/lib/hydra/pcdm/validators/ancestor_validator.rb +26 -0
  17. data/lib/hydra/pcdm/validators/composite_validator.rb +17 -0
  18. data/lib/hydra/pcdm/validators/pcdm_object_validator.rb +9 -0
  19. data/lib/hydra/pcdm/validators/pcdm_validator.rb +9 -0
  20. data/lib/hydra/pcdm/version.rb +1 -1
  21. data/lib/hydra/pcdm/vocab/pcdm_terms.rb +1 -1
  22. data/spec/hydra/pcdm/ancestor_checker_spec.rb +29 -0
  23. data/spec/hydra/pcdm/collection_indexer_spec.rb +11 -11
  24. data/spec/hydra/pcdm/deep_member_iterator_spec.rb +52 -0
  25. data/spec/hydra/pcdm/models/collection_spec.rb +691 -17
  26. data/spec/hydra/pcdm/models/file_spec.rb +16 -0
  27. data/spec/hydra/pcdm/models/object_spec.rb +576 -27
  28. data/spec/hydra/pcdm/object_indexer_spec.rb +6 -6
  29. data/spec/spec_helper.rb +8 -1
  30. metadata +31 -52
  31. data/lib/hydra/pcdm/services/collection/add_collection.rb +0 -20
  32. data/lib/hydra/pcdm/services/collection/add_object.rb +0 -19
  33. data/lib/hydra/pcdm/services/collection/add_related_object.rb +0 -21
  34. data/lib/hydra/pcdm/services/collection/get_collections.rb +0 -18
  35. data/lib/hydra/pcdm/services/collection/get_objects.rb +0 -18
  36. data/lib/hydra/pcdm/services/collection/get_related_objects.rb +0 -17
  37. data/lib/hydra/pcdm/services/collection/remove_collection.rb +0 -36
  38. data/lib/hydra/pcdm/services/collection/remove_object.rb +0 -43
  39. data/lib/hydra/pcdm/services/collection/remove_related_object.rb +0 -36
  40. data/lib/hydra/pcdm/services/object/add_object.rb +0 -20
  41. data/lib/hydra/pcdm/services/object/add_related_object.rb +0 -21
  42. data/lib/hydra/pcdm/services/object/get_objects.rb +0 -18
  43. data/lib/hydra/pcdm/services/object/get_related_objects.rb +0 -17
  44. data/lib/hydra/pcdm/services/object/remove_object.rb +0 -43
  45. data/lib/hydra/pcdm/services/object/remove_related_object.rb +0 -36
  46. data/spec/hydra/pcdm/services/collection/add_collection_spec.rb +0 -197
  47. data/spec/hydra/pcdm/services/collection/add_object_spec.rb +0 -132
  48. data/spec/hydra/pcdm/services/collection/add_related_object_spec.rb +0 -94
  49. data/spec/hydra/pcdm/services/collection/get_collections_spec.rb +0 -40
  50. data/spec/hydra/pcdm/services/collection/get_objects_spec.rb +0 -40
  51. data/spec/hydra/pcdm/services/collection/get_related_objects_spec.rb +0 -37
  52. data/spec/hydra/pcdm/services/collection/remove_collection_spec.rb +0 -143
  53. data/spec/hydra/pcdm/services/collection/remove_object_spec.rb +0 -180
  54. data/spec/hydra/pcdm/services/collection/remove_related_object_spec.rb +0 -146
  55. data/spec/hydra/pcdm/services/file/add_type_spec.rb +0 -19
  56. data/spec/hydra/pcdm/services/object/add_object_spec.rb +0 -186
  57. data/spec/hydra/pcdm/services/object/add_related_object_spec.rb +0 -94
  58. data/spec/hydra/pcdm/services/object/get_objects_spec.rb +0 -33
  59. data/spec/hydra/pcdm/services/object/get_related_objects_spec.rb +0 -39
  60. data/spec/hydra/pcdm/services/object/remove_object_spec.rb +0 -158
  61. data/spec/hydra/pcdm/services/object/remove_related_object_spec.rb +0 -126
@@ -53,4 +53,20 @@ describe Hydra::PCDM::File do
53
53
  end
54
54
  end
55
55
 
56
+ describe "with a file that has no type" do
57
+ subject { file.metadata_node.get_values(:type) }
58
+ let(:pcdm_file) { RDFVocabularies::PCDMTerms.File }
59
+ let(:custom_type) { ::RDF::URI.new("http://example.com/MyType") }
60
+
61
+ it "should add a type that already exists" do
62
+ subject << pcdm_file
63
+ expect(subject).to eq [pcdm_file]
64
+ end
65
+
66
+ it "should add a custom type" do
67
+ subject << custom_type
68
+ expect(subject).to include custom_type
69
+ end
70
+ end
71
+
56
72
  end
@@ -2,43 +2,595 @@ require 'spec_helper'
2
2
 
3
3
  describe Hydra::PCDM::Object do
4
4
 
5
- let(:object1) { Hydra::PCDM::Object.create }
6
- let(:object2) { Hydra::PCDM::Object.create }
7
- let(:object3) { Hydra::PCDM::Object.create }
5
+ describe "#child_object_ids" do
6
+ let(:child1) { described_class.new(id: '1') }
7
+ let(:child2) { described_class.new(id: '2') }
8
+ let(:object) { described_class.new }
9
+ before { object.child_objects = [child1, child2] }
8
10
 
9
- describe '#objects=' do
10
- it 'should aggregate objects' do
11
- object1.objects = [object2, object3]
12
- object1.save
13
- expect(object1.objects).to eq [object2, object3]
11
+ subject { object.child_object_ids }
12
+
13
+ it { is_expected.to eq ["1", "2"] }
14
+ end
15
+
16
+ describe '#child_objects=, +=, <<' do
17
+ context 'with acceptable child objects' do
18
+ let(:object1) { described_class.new }
19
+ let(:object2) { described_class.new }
20
+ let(:object3) { described_class.new }
21
+ let(:object4) { described_class.new }
22
+ let(:object5) { described_class.new }
23
+
24
+ it 'should be empty when no objects have been added' do
25
+ expect( subject.child_objects ).to eq []
26
+ end
27
+
28
+ it 'should add objects' do
29
+ subject.child_objects = [object1,object2]
30
+ subject.child_objects << object3
31
+ subject.child_objects += [object4,object5]
32
+ expect( subject.child_objects ).to eq [object1,object2,object3,object4,object5]
33
+ end
34
+
35
+ it 'should allow sub-objects' do
36
+ subject.child_objects = [object1,object2]
37
+ object1.child_objects = [object3]
38
+ expect( subject.child_objects ).to eq [object1,object2]
39
+ expect( object1.child_objects ).to eq [object3]
40
+ end
41
+
42
+ it 'should allow repeating objects' do
43
+ subject.child_objects = [object1,object2]
44
+ subject.child_objects << object1
45
+ expect( subject.child_objects ).to eq [object1,object2,object1]
46
+ end
47
+
48
+ describe 'adding objects that are ancestors' do
49
+ let(:error_type) { ArgumentError }
50
+ let(:error_message) { 'Hydra::PCDM::Object with ID: failed to pass AncestorChecker validation' }
51
+
52
+ context 'when the source object is the same' do
53
+ it 'raises an error' do
54
+ expect { object1.child_objects = [object1] }.to raise_error(error_type, error_message)
55
+ expect { object1.child_objects += [object1] }.to raise_error(error_type, error_message)
56
+ expect { object1.child_objects << [object1] }.to raise_error(error_type, error_message)
57
+ end
58
+ end
59
+
60
+ before do
61
+ object1.child_objects = [object2]
62
+ end
63
+
64
+ it 'raises an error' do
65
+ expect { object2.child_objects += [object1] }.to raise_error(error_type, error_message)
66
+ expect { object2.child_objects << [object1] }.to raise_error(error_type, error_message)
67
+ expect { object2.child_objects = [object1] }.to raise_error(error_type, error_message)
68
+ end
69
+
70
+ context 'with more ancestors' do
71
+ before do
72
+ object2.child_objects = [object3]
73
+ end
74
+
75
+ it 'raises an error' do
76
+ expect { object3.child_objects << [object1] }.to raise_error(error_type, error_message)
77
+ expect { object3.child_objects = [object1] }.to raise_error(error_type, error_message)
78
+ expect { object3.child_objects += [object1] }.to raise_error(error_type, error_message)
79
+ end
80
+
81
+ context 'with a more complicated example' do
82
+ before do
83
+ object3.child_objects = [object4,object5]
84
+ end
85
+
86
+ it 'raises errors' do
87
+ expect { object4.child_objects = [object1] }.to raise_error(error_type, error_message)
88
+ expect { object4.child_objects += [object1] }.to raise_error(error_type, error_message)
89
+ expect { object4.child_objects << [object1] }.to raise_error(error_type, error_message)
90
+
91
+ expect { object4.child_objects = [object2] }.to raise_error(error_type, error_message)
92
+ expect { object4.child_objects += [object2] }.to raise_error(error_type, error_message)
93
+ expect { object4.child_objects << [object2] }.to raise_error(error_type, error_message)
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
99
+
100
+ context 'with unacceptable child objects' do
101
+ before(:all) do
102
+ @collection101 = Hydra::PCDM::Collection.new
103
+ @object101 = Hydra::PCDM::Object.new
104
+ @file101 = Hydra::PCDM::File.new
105
+ @non_PCDM_object = "I'm not a PCDM object"
106
+ @af_base_object = ActiveFedora::Base.new
107
+ end
108
+
109
+ let(:error_type1) { ArgumentError }
110
+ let(:error_message1) { 'Hydra::PCDM::Collection with ID: was expected to pcdm_object?, but it was false' }
111
+ let(:error_type2) { NoMethodError }
112
+ let(:error_message2) { /undefined method `pcdm_object\?' for .*/ }
113
+
114
+ it 'should NOT aggregate Hydra::PCDM::Collection in objects aggregation' do
115
+ expect { @object101.child_objects = [@collection101] }.to raise_error(error_type1,error_message1)
116
+ expect { @object101.child_objects += [@collection101] }.to raise_error(error_type1,error_message1)
117
+ expect { @object101.child_objects << @collection101 }.to raise_error(error_type1,error_message1)
118
+ end
119
+
120
+ it 'should NOT aggregate Hydra::PCDM::Files in objects aggregation' do
121
+ expect { @object101.child_objects += [@file1] }.to raise_error(error_type2,error_message2)
122
+ expect { @object101.child_objects << @file1 }.to raise_error(error_type2,error_message2)
123
+ expect { @object101.child_objects = [@file1] }.to raise_error(error_type2,error_message2)
124
+ end
125
+
126
+ it 'should NOT aggregate non-PCDM objects in objects aggregation' do
127
+ expect { @object101.child_objects << @non_PCDM_object }.to raise_error(error_type2,error_message2)
128
+ expect { @object101.child_objects = [@non_PCDM_object] }.to raise_error(error_type2,error_message2)
129
+ expect { @object101.child_objects += [@non_PCDM_object] }.to raise_error(error_type2,error_message2)
130
+ end
131
+
132
+ it 'should NOT aggregate AF::Base objects in objects aggregation' do
133
+ expect { @object101.child_objects = [@af_base_object] }.to raise_error(error_type2,error_message2)
134
+ expect { @object101.child_objects += [@af_base_object] }.to raise_error(error_type2,error_message2)
135
+ expect { @object101.child_objects << @af_base_object }.to raise_error(error_type2,error_message2)
136
+ end
14
137
  end
15
138
  end
16
139
 
17
- describe 'Related objects' do
140
+ describe '#members=, +=, <<' do
141
+ context 'with acceptable child objects' do
142
+ let(:object1) { described_class.new }
143
+ let(:object2) { described_class.new }
144
+ let(:object3) { described_class.new }
145
+ let(:object4) { described_class.new }
146
+ let(:object5) { described_class.new }
147
+
148
+ it 'should add objects' do
149
+ subject.members = [object1,object2]
150
+ subject.members << object3
151
+ subject.members += [object4,object5]
152
+ expect( subject.members ).to eq [object1,object2,object3,object4,object5]
153
+ end
154
+
155
+ it 'should allow sub-objects' do
156
+ subject.members = [object1,object2]
157
+ object1.members = [object3]
158
+ expect( subject.members ).to eq [object1,object2]
159
+ expect( object1.members ).to eq [object3]
160
+ end
161
+
162
+ it 'should allow repeating objects' do
163
+ subject.members = [object1,object2,object1]
164
+ expect( subject.members ).to eq [object1,object2,object1]
165
+ end
166
+
167
+ describe 'adding objects that are ancestors' do
168
+ let(:error_type) { ArgumentError }
169
+ let(:error_message) { 'Hydra::PCDM::Object with ID: failed to pass AncestorChecker validation' }
170
+
171
+ context 'when the source object is the same' do
172
+ it 'raises an error' do
173
+ expect { object1.members = [object1] }.to raise_error(error_type, error_message)
174
+ expect { object1.members += [object1] }.to raise_error(error_type, error_message)
175
+ expect { object1.members << [object1] }.to raise_error(error_type, error_message)
176
+ end
177
+ end
178
+
179
+ before do
180
+ object1.members = [object2]
181
+ end
182
+
183
+ it 'raises an error' do
184
+ expect { object2.members += [object1] }.to raise_error(error_type, error_message)
185
+ expect { object2.members << [object1] }.to raise_error(error_type, error_message)
186
+ expect { object2.members = [object1] }.to raise_error(error_type, error_message)
187
+ end
188
+
189
+ context 'with more ancestors' do
190
+ before do
191
+ object2.members = [object3]
192
+ end
193
+
194
+ it 'raises an error' do
195
+ expect { object3.members << [object1] }.to raise_error(error_type, error_message)
196
+ expect { object3.members = [object1] }.to raise_error(error_type, error_message)
197
+ expect { object3.members += [object1] }.to raise_error(error_type, error_message)
198
+ end
199
+
200
+ context 'with a more complicated example' do
201
+ before do
202
+ object3.members = [object4,object5]
203
+ end
204
+
205
+ it 'raises errors' do
206
+ expect { object4.members = [object1] }.to raise_error(error_type, error_message)
207
+ expect { object4.members += [object1] }.to raise_error(error_type, error_message)
208
+ expect { object4.members << [object1] }.to raise_error(error_type, error_message)
209
+
210
+ expect { object4.members = [object2] }.to raise_error(error_type, error_message)
211
+ expect { object4.members += [object2] }.to raise_error(error_type, error_message)
212
+ expect { object4.members << [object2] }.to raise_error(error_type, error_message)
213
+ end
214
+ end
215
+ end
216
+ end
217
+ end
218
+
219
+ context 'with unacceptable child objects' do
220
+ before(:all) do
221
+ @collection101 = Hydra::PCDM::Collection.new
222
+ @object101 = Hydra::PCDM::Object.new
223
+ @file101 = Hydra::PCDM::File.new
224
+ @non_PCDM_object = "I'm not a PCDM object"
225
+ @af_base_object = ActiveFedora::Base.new
226
+ end
227
+
228
+ let(:error_type1) { ActiveFedora::AssociationTypeMismatch }
229
+ let(:error_message1) { /(<ActiveFedora::Base:[\d\s\w]{16}>|\s*) is not a PCDM object./ }
230
+
231
+ let(:error_type2) { ActiveFedora::AssociationTypeMismatch }
232
+ let(:error_message2) { /ActiveFedora::Base\(#\d+\) expected, got NilClass\(#[\d]+\)/ }
233
+
234
+ let(:error_type3) { ActiveFedora::AssociationTypeMismatch }
235
+ let(:error_message3) { /ActiveFedora::Base\(#\d+\) expected, got String\(#[\d]+\)/ }
236
+
237
+ it 'should NOT aggregate Hydra::PCDM::Collection in members aggregation' do
238
+ expect { @object101.members = [@collection101] }.to raise_error(error_type1,error_message1)
239
+ expect { @object101.members += [@collection101] }.to raise_error(error_type1,error_message1)
240
+ expect { @object101.members << @collection101 }.to raise_error(error_type1,error_message1)
241
+ end
242
+ it 'should NOT aggregate Hydra::PCDM::Files in members aggregation' do
243
+ expect { @object101.members += [@file1] }.to raise_error(error_type2,error_message2)
244
+ expect { @object101.members << @file1 }.to raise_error(error_type2,error_message2)
245
+ expect { @object101.members = [@file1] }.to raise_error(error_type2,error_message2)
246
+ end
247
+
248
+ it 'should NOT aggregate non-PCDM objects in members aggregation' do
249
+ expect { @object101.members << @non_PCDM_object }.to raise_error(error_type3,error_message3)
250
+ expect { @object101.members = [@non_PCDM_object] }.to raise_error(error_type3,error_message3)
251
+ expect { @object101.members += [@non_PCDM_object] }.to raise_error(error_type3,error_message3)
252
+ end
253
+
254
+ it 'should NOT aggregate non-PCDM AF::Base objects in members aggregation' do
255
+ expect { @object101.members = [@af_base_object] }.to raise_error(error_type1,error_message1)
256
+ expect { @object101.members += [@af_base_object] }.to raise_error(error_type1,error_message1)
257
+ expect { @object101.members << @af_base_object }.to raise_error(error_type1,error_message1)
258
+ end
259
+ end
260
+ end
261
+
262
+ context 'when aggregated by other objects' do
18
263
  before do
19
- object1.related_objects = [object2]
20
- object1.save
264
+ # Using before(:all) and instance variable because regular :let syntax had a significant impact on performance
265
+ # All of the tests in this context are describing idempotent behavior, so isolation between examples isn't necessary.
266
+ @collection1 = Hydra::PCDM::Collection.new
267
+ @collection2 = Hydra::PCDM::Collection.new
268
+ @parent_object = Hydra::PCDM::Object.new
269
+ @object = Hydra::PCDM::Object.new
270
+ @collection1.members = [@object]
271
+ @collection2.members = [@object]
272
+ @parent_object.members = [@object]
273
+ allow(@object).to receive(:id).and_return("banana")
274
+ proxies = [
275
+ build_proxy(container: @collection1),
276
+ build_proxy(container: @collection2),
277
+ build_proxy(container: @parent_object)
278
+ ]
279
+ allow(ActiveFedora::Aggregation::Proxy).to receive(:where).with(proxyFor_ssim: @object.id).and_return(proxies)
280
+ end
281
+
282
+ describe 'parents' do
283
+ subject { @object.parents }
284
+ it "finds all nodes that aggregate the object with hasMember" do
285
+ expect(subject).to include(@collection1, @collection2, @parent_object)
286
+ end
21
287
  end
22
288
 
23
- it 'persists' do
24
- expect(object1.reload.related_objects).to eq [object2]
289
+ describe 'parent_objects' do
290
+ subject { @object.parent_objects }
291
+ it "finds objects that aggregate the object with hasMember" do
292
+ expect(subject).to eq [@parent_object]
293
+ end
294
+ end
295
+ describe 'parent_collections' do
296
+ subject { @object.parent_collections }
297
+ it "finds collections that aggregate the object with hasMember" do
298
+ expect(subject).to include(@collection1, @collection2)
299
+ expect(subject.count).to eq 2
300
+ end
301
+ end
302
+ def build_proxy(container:)
303
+ instance_double(ActiveFedora::Aggregation::Proxy, container: container)
25
304
  end
26
305
  end
27
306
 
28
- describe '#files' do
29
- let(:object) { described_class.create }
30
- let(:file1) { object.files.build }
31
- let(:file2) { object.files.build }
307
+ describe 'Related objects' do
308
+ context 'with acceptable objects' do
309
+ let(:object1) { Hydra::PCDM::Object.new }
310
+ let(:object2) { Hydra::PCDM::Object.new }
311
+ let(:object3) { Hydra::PCDM::Object.new }
312
+ let(:file1) { Hydra::PCDM::File.new }
32
313
 
33
- before do
34
- file1.content = "I'm a file"
35
- file2.content = "I am too"
36
- object.save!
314
+ it 'should return empty array when no related object' do
315
+ expect( subject.related_objects ).to eq []
316
+ end
317
+
318
+ it 'should add objects to the related object set' do
319
+ subject.related_objects << object1 # first add
320
+ subject.related_objects << object2 # second add to same object
321
+ subject.save
322
+ related_objects = subject.reload.related_objects
323
+ expect( related_objects.include? object1 ).to be true
324
+ expect( related_objects.include? object2 ).to be true
325
+ expect( related_objects.size ).to eq 2
326
+ end
327
+
328
+ it 'should not repeat objects in the related object set' do
329
+ skip 'pending resolution of ActiveFedora issue #853' do
330
+ subject.related_objects << object1 # first add
331
+ subject.related_objects << object2 # second add to same object
332
+ subject.related_objects << object1 # repeat an object replaces the object
333
+ related_objects = subject.related_objects
334
+ expect( related_objects.include? object1 ).to be true
335
+ expect( related_objects.include? object2 ).to be true
336
+ expect( related_objects.size ).to eq 2
337
+ end
338
+ end
37
339
  end
38
340
 
39
- subject { described_class.find(object.id).files }
341
+ context 'with unacceptable inputs' do
342
+ before(:all) do
343
+ @collection101 = Hydra::PCDM::Collection.new
344
+ @object101 = Hydra::PCDM::Object.new
345
+ @file101 = Hydra::PCDM::File.new
346
+ @non_PCDM_object = "I'm not a PCDM object"
347
+ @af_base_object = ActiveFedora::Base.new
348
+ end
349
+ context 'with unacceptable related objects' do
350
+ let(:error_message) { 'child_related_object must be a pcdm object' }
351
+
352
+ it 'should NOT aggregate Hydra::PCDM::Collection in objects aggregation' do
353
+ expect{ @object101.related_objects << @collection101 }.to raise_error(ActiveFedora::AssociationTypeMismatch,/Hydra::PCDM::Collection:.*> is not a PCDM object./)
354
+ end
355
+
356
+ it 'should NOT aggregate Hydra::PCDM::Files in objects aggregation' do
357
+ expect{ @object101.related_objects << @file1 }.to raise_error(ActiveFedora::AssociationTypeMismatch,/ActiveFedora::Base.* expected, got NilClass.*/)
358
+ end
359
+
360
+ it 'should NOT aggregate non-PCDM objects in objects aggregation' do
361
+ expect{ @object101.related_objects << @non_PCDM_object }.to raise_error(ActiveFedora::AssociationTypeMismatch,/ActiveFedora::Base.* expected, got String.*/)
362
+ end
363
+
364
+ it 'should NOT aggregate AF::Base objects in objects aggregation' do
365
+ expect{ @object101.related_objects << @af_base_object }.to raise_error(ActiveFedora::AssociationTypeMismatch,/ActiveFedora::Base:.*> is not a PCDM object./)
366
+ end
367
+ end
368
+
369
+ context 'with unacceptable parent object' do
370
+ it 'should NOT accept Hydra::PCDM::Files as parent object' do
371
+ expect{ @file1.related_objects << @object101 }.to raise_error(NoMethodError)
372
+ end
373
+
374
+ it 'should NOT accept non-PCDM objects as parent object' do
375
+ expect{ @non_PCDM_object.related_objects << @object101 }.to raise_error(NoMethodError)
376
+ end
377
+
378
+ it 'should NOT accept AF::Base objects as parent object' do
379
+ expect{ @af_base_object.related_objects << @object101 }.to raise_error(NoMethodError)
380
+ end
40
381
 
41
- it { is_expected.to eq [file1, file2] }
382
+ it 'should NOT accept Hydra::PCDM::Files as parent object' do
383
+ expect{ @file101.related_objects }.to raise_error(NoMethodError)
384
+ end
385
+
386
+ it 'should NOT accept non-PCDM objects as parent object' do
387
+ expect{ @non_PCDM_object.related_objects }.to raise_error(NoMethodError)
388
+ end
389
+
390
+ it 'should NOT accept AF::Base objects as parent object' do
391
+ expect{ @af_base_object.related_objects }.to raise_error(NoMethodError)
392
+ end
393
+ end
394
+ end
395
+ end
396
+
397
+ describe "removing related objects" do
398
+ subject { Hydra::PCDM::Object.new }
399
+
400
+ let(:object1) { Hydra::PCDM::Object.new }
401
+ let(:object2) { Hydra::PCDM::Object.new }
402
+ let(:object3) { Hydra::PCDM::Object.new }
403
+ let(:object4) { Hydra::PCDM::Object.new }
404
+ let(:object5) { Hydra::PCDM::Object.new }
405
+
406
+ let(:file1) { Hydra::PCDM::File.new }
407
+ let(:file2) { Hydra::PCDM::File.new }
408
+
409
+ context 'when it is the only related object' do
410
+ before do
411
+ subject.related_objects << object1
412
+ expect( subject.related_objects ).to eq [object1]
413
+ end
414
+
415
+ it 'should remove related object while changes are in memory' do
416
+ expect( subject.related_objects.delete object1 ).to eq [object1]
417
+ expect( subject.related_objects ).to eq []
418
+ end
419
+ end
420
+
421
+ context 'when multiple related objects' do
422
+ before do
423
+ subject.related_objects << object1
424
+ subject.related_objects << object2
425
+ subject.related_objects << object3
426
+ subject.related_objects << object4
427
+ subject.related_objects << object5
428
+ expect( subject.related_objects ).to eq [object1,object2,object3,object4,object5]
429
+ end
430
+
431
+ it 'should remove first related object when changes are in memory' do
432
+ expect( subject.related_objects.delete object1 ).to eq [object1]
433
+ expect( subject.related_objects ).to eq [object2,object3,object4,object5]
434
+ end
435
+
436
+ it 'should remove last related object when changes are in memory' do
437
+ expect( subject.related_objects.delete object5 ).to eq [object5]
438
+ expect( subject.related_objects ).to eq [object1,object2,object3,object4]
439
+ end
440
+
441
+ it 'should remove middle related object when changes are in memory' do
442
+ expect( subject.related_objects.delete object3 ).to eq [object3]
443
+ expect( subject.related_objects ).to eq [object1,object2,object4,object5]
444
+ end
445
+
446
+ it 'should remove middle related object when changes are saved' do
447
+ expect( subject.related_objects ).to eq [object1,object2,object3,object4,object5]
448
+ expect( subject.related_objects.delete object3 ).to eq [object3]
449
+ subject.save
450
+ expect( subject.reload.related_objects ).to eq [object1,object2,object4,object5]
451
+ end
452
+ end
453
+
454
+ context 'when related object is missing' do
455
+ it 'should return empty array when 0 related objects and 0 objects' do
456
+ expect( subject.related_objects.delete object1 ).to eq []
457
+ end
458
+
459
+ it 'should return empty array when other related objects and changes in memory' do
460
+ subject.related_objects << object1
461
+ subject.related_objects << object2
462
+ subject.related_objects << object4
463
+ subject.related_objects << object5
464
+ expect( subject.related_objects.delete object3 ).to eq []
465
+ end
466
+
467
+ it 'should return empty array when other related objects and changes are in memory' do
468
+ subject.related_objects << object1
469
+ subject.related_objects << object2
470
+ subject.related_objects << object4
471
+ subject.related_objects << object5
472
+ expect( subject.related_objects.delete object3 ).to eq []
473
+ end
474
+
475
+ it 'should return empty array when changes are saved' do
476
+ subject.related_objects << object1
477
+ subject.related_objects << object2
478
+ subject.related_objects << object4
479
+ subject.related_objects << object5
480
+ subject.save
481
+ expect( subject.reload.related_objects.delete object3 ).to eq []
482
+ end
483
+ end
484
+ end
485
+
486
+ describe "removing child objects" do
487
+ subject { Hydra::PCDM::Object.new }
488
+ let(:object1) { Hydra::PCDM::Object.new }
489
+ let(:object2) { Hydra::PCDM::Object.new }
490
+ let(:object3) { Hydra::PCDM::Object.new }
491
+
492
+ context 'when it is the only object' do
493
+ before do
494
+ subject.child_objects += [object1]
495
+ expect( subject.child_objects ).to eq [object1]
496
+ end
497
+
498
+ it 'should remove object while changes are in memory' do
499
+ expect( subject.child_objects.delete object1 ).to eq [object1]
500
+ expect( subject.child_objects ).to eq []
501
+ end
502
+ end
503
+
504
+ context 'when multiple objects' do
505
+ before do
506
+ subject.child_objects += [object1, object2, object3]
507
+ expect( subject.child_objects ).to eq [object1,object2,object3]
508
+ end
509
+
510
+ it 'should remove first object when changes are in memory' do
511
+ expect( subject.child_objects.delete object1 ).to eq [object1]
512
+ expect( subject.child_objects ).to eq [object2,object3]
513
+ end
514
+
515
+ it 'should remove last object when changes are in memory' do
516
+ expect( subject.child_objects.delete object3 ).to eq [object3]
517
+ expect( subject.child_objects ).to eq [object1,object2]
518
+ end
519
+
520
+ it 'should remove middle object when changes are in memory' do
521
+ expect( subject.child_objects.delete object2 ).to eq [object2]
522
+ expect( subject.child_objects ).to eq [object1,object3]
523
+ end
524
+
525
+ it 'should remove middle object when changes are saved' do
526
+ subject.save
527
+ expect( subject.child_objects ).to eq [object1,object2,object3]
528
+ expect( subject.child_objects.delete object2 ).to eq [object2]
529
+ expect( subject.child_objects ).to eq [object1,object3]
530
+ end
531
+ end
532
+ context 'when object repeats' do
533
+ before do
534
+ subject.child_objects += [object1, object2, object3, object2, object3]
535
+ expect( subject.child_objects ).to eq [object1,object2,object3,object2,object3]
536
+ end
537
+
538
+ it 'should remove first occurrence when changes in memory' do
539
+ expect( subject.child_objects.delete object2 ).to eq [object2]
540
+ expect( subject.child_objects ).to eq [object1,object3,object3]
541
+ end
542
+
543
+ it 'should remove last occurrence when changes in memory' do
544
+ skip( "pending resolution of AF-agg 46 and PCDM 102") do
545
+ expect( subject.child_objects.delete object2, -1 ).to eq object2
546
+ expect( subject.child_objects ).to eq [object1,object2,object3,object3]
547
+ end
548
+ end
549
+
550
+ it 'should remove nth occurrence when changes in memory' do
551
+ skip( "pending resolution of AF-agg 46 and PCDM 102") do
552
+ expect( subject.child_objects.delete object2, 2 ).to eq object2
553
+ expect( subject.child_objects ).to eq [object1,object2,object3,object3]
554
+ end
555
+ end
556
+
557
+ it 'should remove nth occurrence when changes are saved' do
558
+ skip( "pending resolution of AF-agg 46 and PCDM 102") do
559
+ expect( subject.child_objects ).to eq [object1,object2,object3,object2,object3]
560
+ expect( subject.child_objects ).to eq [object1,object2,object3,object2,object3]
561
+
562
+ expect( subject.child_objects.delete object2, 2 ).to eq object2
563
+ subject.save
564
+ expect( subject.child_objects ).to eq [object1,object2,object3,object2,object3]
565
+ end
566
+ end
567
+ end
568
+
569
+ context 'when object is missing' do
570
+ it 'and 0 objects in object should return empty array' do
571
+ expect( subject.child_objects.delete object1 ).to eq []
572
+ end
573
+
574
+ it 'and multiple objects in object should return empty array when changes are in memory' do
575
+ subject.child_objects += [object1, object2]
576
+ expect( subject.child_objects.delete object3 ).to eq []
577
+ end
578
+
579
+ it 'should return empty array when changes are saved' do
580
+ subject.child_objects += [object1, object2]
581
+ expect( subject.child_objects.delete object3 ).to eq []
582
+ end
583
+ end
584
+ end
585
+
586
+ describe '#files' do
587
+ subject { described_class.new }
588
+ it "should have a files relation" do
589
+ reflection = subject.reflections[:files]
590
+ expect(reflection.macro).to eq :directly_contains
591
+ expect(reflection.options[:has_member_relation]).to eq RDFVocabularies::PCDMTerms.hasFile
592
+ expect(reflection.options[:class_name].to_s).to eq "Hydra::PCDM::File"
593
+ end
42
594
  end
43
595
 
44
596
  describe "filtering files" do
@@ -52,8 +604,7 @@ describe Hydra::PCDM::Object do
52
604
  let(:pcdm_thumbnail_uri) { ::RDF::URI("http://pcdm.org/ThumbnailImage") }
53
605
 
54
606
  before do
55
- object.files = [file]
56
- object.save
607
+ file
57
608
  end
58
609
 
59
610
  describe "filter_files_by_type" do
@@ -95,8 +646,6 @@ describe Hydra::PCDM::Object do
95
646
  end
96
647
  end
97
648
 
98
-
99
-
100
649
  describe ".indexer" do
101
650
  after do
102
651
  Object.send(:remove_const, :Foo)