active-fedora 9.0.6 → 9.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/History.txt +57 -0
- data/lib/active_fedora.rb +5 -0
- data/lib/active_fedora/associations/collection_association.rb +1 -18
- data/lib/active_fedora/associations/has_and_belongs_to_many_association.rb +12 -10
- data/lib/active_fedora/core.rb +15 -17
- data/lib/active_fedora/core/fedora_id_translator.rb +12 -0
- data/lib/active_fedora/core/fedora_uri_translator.rb +9 -0
- data/lib/active_fedora/errors.rb +4 -0
- data/lib/active_fedora/fedora_attributes.rb +15 -5
- data/lib/active_fedora/file.rb +2 -0
- data/lib/active_fedora/inheritable_accessors.rb +26 -0
- data/lib/active_fedora/reflection.rb +3 -1
- data/lib/active_fedora/relation/finder_methods.rb +27 -3
- data/lib/active_fedora/version.rb +1 -1
- data/lib/active_fedora/versions_graph.rb +7 -8
- data/spec/integration/associations_spec.rb +34 -22
- data/spec/integration/belongs_to_association_spec.rb +118 -47
- data/spec/integration/collection_association_spec.rb +46 -0
- data/spec/integration/has_and_belongs_to_many_associations_spec.rb +178 -139
- data/spec/integration/versionable_spec.rb +38 -1
- data/spec/samples/samples.rb +0 -1
- data/spec/unit/base_spec.rb +51 -0
- data/spec/unit/core/fedora_id_translator_spec.rb +20 -0
- data/spec/unit/core/fedora_uri_translator_spec.rb +19 -0
- data/spec/unit/core_spec.rb +50 -0
- data/spec/unit/has_many_association_spec.rb +27 -2
- data/spec/unit/qualified_dublin_core_datastream_spec.rb +0 -6
- data/spec/unit/reflection_spec.rb +44 -0
- metadata +9 -13
- data/spec/samples/marpa-dc_datastream.rb +0 -102
- data/spec/samples/models/audio_record.rb +0 -29
- data/spec/samples/models/image.rb +0 -5
- data/spec/samples/models/oral_history.rb +0 -36
- data/spec/samples/models/seminar.rb +0 -29
- data/spec/samples/models/seminar_audio_file.rb +0 -32
- data/spec/samples/oral_history_sample_model.rb +0 -30
- data/spec/samples/special_thing.rb +0 -44
@@ -10,6 +10,9 @@ describe ActiveFedora::Base do
|
|
10
10
|
belongs_to :library, predicate: ActiveFedora::RDF::Fcrepo::RelsExt.hasConstituent
|
11
11
|
end
|
12
12
|
class SpecialInheritedBook < Book
|
13
|
+
def assert_content_model
|
14
|
+
self.has_model = [self.class.to_s, self.class.superclass.to_s]
|
15
|
+
end
|
13
16
|
end
|
14
17
|
|
15
18
|
end
|
@@ -73,8 +76,8 @@ describe ActiveFedora::Base do
|
|
73
76
|
end
|
74
77
|
|
75
78
|
it "should cast to the most specific class for the association" do
|
76
|
-
@library2.books[0].
|
77
|
-
@library2.books[1].
|
79
|
+
expect(@library2.books[0]).to be_instance_of Book
|
80
|
+
expect(@library2.books[1]).to be_instance_of SpecialInheritedBook
|
78
81
|
end
|
79
82
|
|
80
83
|
after do
|
@@ -90,104 +93,172 @@ describe ActiveFedora::Base do
|
|
90
93
|
belongs_to :complex_collection, predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isPartOf, class_name: 'ComplexCollection'
|
91
94
|
end
|
92
95
|
|
93
|
-
|
96
|
+
#NOTE: As RDF assertions seem to be returned in alphabetical order, the "Z" is to insure this is stored
|
97
|
+
# after the SimpleObject relationship for this particular case. This is to ensure people don't just change ActiveFedora
|
98
|
+
# to pick the first content model and it works by alphabetical chance.
|
99
|
+
class ZComplexObject < SimpleObject
|
94
100
|
belongs_to :simple_collection, predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isPartOf, class_name: 'SimpleCollection'
|
95
101
|
belongs_to :complex_collection, predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isPartOf, class_name: 'ComplexCollection'
|
102
|
+
|
103
|
+
def assert_content_model
|
104
|
+
self.has_model = [self.class.to_s, self.class.superclass.to_s]
|
105
|
+
end
|
96
106
|
end
|
97
107
|
|
98
108
|
class SimpleCollection < ActiveFedora::Base
|
99
109
|
has_many :objects, predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isPartOf, class_name: 'SimpleObject', autosave: true
|
100
|
-
has_many :complex_objects, predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isPartOf, class_name: '
|
110
|
+
has_many :complex_objects, predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isPartOf, class_name: 'ZComplexObject', autosave: true
|
101
111
|
end
|
102
112
|
|
103
113
|
class ComplexCollection < SimpleCollection
|
104
114
|
has_many :objects, predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isPartOf, class_name: 'SimpleObject', autosave: true
|
105
|
-
has_many :complex_objects, predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isPartOf, class_name: '
|
115
|
+
has_many :complex_objects, predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isPartOf, class_name: 'ZComplexObject', autosave: true
|
116
|
+
|
117
|
+
def assert_content_model
|
118
|
+
self.has_model = [self.class.to_s, self.class.superclass.to_s]
|
119
|
+
end
|
106
120
|
end
|
107
121
|
|
108
122
|
end
|
109
123
|
after :all do
|
110
124
|
Object.send(:remove_const, :SimpleObject)
|
111
|
-
Object.send(:remove_const, :
|
125
|
+
Object.send(:remove_const, :ZComplexObject)
|
112
126
|
Object.send(:remove_const, :SimpleCollection)
|
113
127
|
Object.send(:remove_const, :ComplexCollection)
|
114
128
|
end
|
115
129
|
|
116
130
|
describe "saving between the before and after hooks" do
|
131
|
+
let(:complex_object) { ZComplexObject.find(ZComplexObject.create.id) }
|
132
|
+
let(:complex_collection) { ComplexCollection.find(ComplexCollection.create.id) }
|
133
|
+
|
134
|
+
context "Verify that an inherited object will save and retrieve with the correct models" do
|
135
|
+
it "should have added the inverse relationship for the correct class" do
|
136
|
+
expect(complex_object.has_model).to match_array(["SimpleObject", "ZComplexObject"])
|
137
|
+
expect(complex_collection.has_model).to match_array(["SimpleCollection", "ComplexCollection"])
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
117
141
|
context "Add a complex_object into a simple_collection" do
|
142
|
+
let(:simple_collection) { SimpleCollection.create }
|
143
|
+
|
118
144
|
before do
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
@simple_collection.objects = [@complex_object]
|
123
|
-
@simple_collection.save!
|
124
|
-
@complex_collection.save!
|
145
|
+
simple_collection.objects = [complex_object]
|
146
|
+
simple_collection.save!
|
147
|
+
complex_collection.save!
|
125
148
|
end
|
126
149
|
it "should have added the inverse relationship for the correct class" do
|
127
|
-
expect(
|
128
|
-
expect(
|
150
|
+
expect(complex_object.simple_collection).to be_instance_of SimpleCollection
|
151
|
+
expect(complex_object.complex_collection).to be_nil
|
129
152
|
end
|
130
153
|
end
|
131
154
|
|
132
155
|
context "Add a complex_object into a complex_collection" do
|
133
156
|
before do
|
134
|
-
|
135
|
-
|
136
|
-
@complex_collection.objects = [@complex_object] # this sticks it into the :objects association, but since it is a ComplexObject it should also be fetched by :complex_collection association
|
137
|
-
@complex_collection.save
|
157
|
+
complex_collection.objects = [complex_object] # this sticks it into the :objects association, but since it is a ZComplexObject it should also be fetched by :complex_collection association
|
158
|
+
complex_collection.save
|
138
159
|
end
|
139
160
|
|
140
161
|
it "should have added the inverse relationship for the correct class" do
|
141
|
-
expect(
|
142
|
-
expect(
|
162
|
+
expect(complex_object.complex_collection).to be_instance_of ComplexCollection
|
163
|
+
expect(complex_object.reload.simple_collection).to be_instance_of ComplexCollection
|
143
164
|
end
|
144
165
|
end
|
145
166
|
|
146
167
|
context "Adding mixed types on a base class with a filtered has_many relationship" do
|
168
|
+
let(:simple_collection) { SimpleCollection.create }
|
169
|
+
let(:simple_object) { SimpleObject.create }
|
170
|
+
|
147
171
|
before do
|
148
|
-
|
149
|
-
|
150
|
-
@simple_object = SimpleObject.create
|
151
|
-
@simple_collection.objects = [@complex_object, @simple_object]
|
152
|
-
@simple_collection.save!
|
172
|
+
simple_collection.objects = [complex_object, simple_object]
|
173
|
+
simple_collection.save!
|
153
174
|
end
|
154
175
|
it "ignores objects who's classes aren't specified" do
|
155
|
-
expect(
|
156
|
-
expect(
|
157
|
-
expect(
|
176
|
+
expect(simple_collection.complex_objects.size).to eq 1
|
177
|
+
expect(simple_collection.complex_objects[0]).to be_instance_of ZComplexObject
|
178
|
+
expect(simple_collection.complex_objects[1]).to be_nil
|
158
179
|
|
159
|
-
expect(
|
160
|
-
expect(
|
161
|
-
expect(
|
180
|
+
expect(simple_collection.objects.size).to eq 2
|
181
|
+
expect(simple_collection.objects[0]).to be_instance_of ZComplexObject
|
182
|
+
expect(simple_collection.objects[1]).to be_instance_of SimpleObject
|
162
183
|
|
163
|
-
expect(
|
164
|
-
expect(
|
184
|
+
expect(simple_object.simple_collection).to be_instance_of SimpleCollection
|
185
|
+
expect(simple_object.complex_collection).to be_nil
|
165
186
|
end
|
166
187
|
end
|
167
188
|
|
168
189
|
context "Adding mixed types on a subclass with a filtered has_many relationship" do
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
@complex_collection.save!
|
190
|
+
let(:simple_object) { SimpleObject.create }
|
191
|
+
|
192
|
+
before do
|
193
|
+
complex_collection.objects = [complex_object, simple_object]
|
194
|
+
complex_collection.save!
|
175
195
|
end
|
176
196
|
it "ignores objects who's classes aren't specified" do
|
177
|
-
expect(
|
178
|
-
expect(
|
179
|
-
expect(
|
197
|
+
expect(complex_collection.complex_objects.size).to eq 1
|
198
|
+
expect(complex_collection.complex_objects[0]).to be_instance_of ZComplexObject
|
199
|
+
expect(complex_collection.complex_objects[1]).to be_nil
|
180
200
|
|
181
|
-
expect(
|
182
|
-
expect(
|
183
|
-
expect(
|
201
|
+
expect(complex_collection.objects.size).to eq 2
|
202
|
+
expect(complex_collection.objects[0]).to be_instance_of ZComplexObject
|
203
|
+
expect(complex_collection.objects[1]).to be_instance_of SimpleObject
|
184
204
|
|
185
|
-
expect(
|
186
|
-
expect(
|
205
|
+
expect(simple_object.complex_collection).to be_instance_of ComplexCollection
|
206
|
+
expect(simple_object.reload.simple_collection).to be_instance_of ComplexCollection
|
187
207
|
end
|
188
208
|
end
|
189
209
|
end
|
190
210
|
end
|
211
|
+
|
212
|
+
describe "casting inheritance super class test cases" do
|
213
|
+
before :all do
|
214
|
+
class SuperclassObject < ActiveFedora::Base
|
215
|
+
belongs_to :superclass_collection, predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isPartOf, class_name: 'SuperclassCollection'
|
216
|
+
|
217
|
+
def assert_content_model
|
218
|
+
self.has_model = [self.class.to_s, self.class.superclass.to_s]
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
class SubclassObject < SuperclassObject
|
223
|
+
end
|
224
|
+
|
225
|
+
class SuperclassCollection < ActiveFedora::Base
|
226
|
+
has_many :objects, predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isPartOf, class_name: 'SuperclassObject', autosave: true
|
227
|
+
end
|
228
|
+
end
|
229
|
+
after :all do
|
230
|
+
Object.send(:remove_const, :SuperclassObject)
|
231
|
+
Object.send(:remove_const, :SubclassObject)
|
232
|
+
Object.send(:remove_const, :SuperclassCollection)
|
233
|
+
end
|
234
|
+
|
235
|
+
describe "Adding subclass objects" do
|
236
|
+
let(:superclass_collection) { SuperclassCollection.create }
|
237
|
+
let(:superclass_object) { SubclassObject.create }
|
238
|
+
|
239
|
+
context "Add a subclass_object into a superclass_collection" do
|
240
|
+
before do
|
241
|
+
superclass_collection.objects = [subclass_object]
|
242
|
+
superclass_collection.save!
|
243
|
+
end
|
244
|
+
it "should have added the inverse relationship for the correct class" do
|
245
|
+
expect(subclass_object.superclass_collection).to be_instance_of SuperclassCollection
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
context "Set the superclass_collection of a subclass object"
|
250
|
+
let(:subclass_object) { SubclassObject.create }
|
251
|
+
|
252
|
+
before do
|
253
|
+
subclass_object.superclass_collection = superclass_collection
|
254
|
+
subclass_object.save!
|
255
|
+
end
|
256
|
+
it "should have added the inverse relationship for the correct class" do
|
257
|
+
expect(superclass_collection.objects.size).to eq 1
|
258
|
+
expect(superclass_collection.objects[0]).to be_instance_of SubclassObject
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
191
262
|
end
|
192
263
|
|
193
264
|
|
@@ -71,4 +71,50 @@ describe ActiveFedora::Base do
|
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
|
+
describe "finding the inverse" do
|
75
|
+
context "when no inverse exists" do
|
76
|
+
before do
|
77
|
+
class Item < ActiveFedora::Base
|
78
|
+
end
|
79
|
+
class Container < ActiveFedora::Base
|
80
|
+
has_many :items
|
81
|
+
end
|
82
|
+
end
|
83
|
+
after do
|
84
|
+
Object.send(:remove_const, :Item)
|
85
|
+
Object.send(:remove_const, :Container)
|
86
|
+
end
|
87
|
+
|
88
|
+
let(:instance) { Container.new }
|
89
|
+
subject { instance.items }
|
90
|
+
|
91
|
+
it "raises an error" do
|
92
|
+
expect { subject }.to raise_error "No :inverse_of or :predicate attribute was set or could be inferred for has_many :items on Container"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context "when classes are namespaced" do
|
97
|
+
before do
|
98
|
+
class Item < ActiveFedora::Base
|
99
|
+
has_and_belongs_to_many :container, predicate: ::RDF::DC.extent, class_name: 'Foo::Container'
|
100
|
+
end
|
101
|
+
module Foo
|
102
|
+
class Container < ActiveFedora::Base
|
103
|
+
has_many :items
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
after do
|
108
|
+
Object.send(:remove_const, :Item)
|
109
|
+
Object.send(:remove_const, :Foo)
|
110
|
+
end
|
111
|
+
|
112
|
+
let(:instance) { Foo::Container.new }
|
113
|
+
subject { instance.items }
|
114
|
+
|
115
|
+
it "finds the association" do
|
116
|
+
expect(subject).to eq []
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
74
120
|
end
|
@@ -2,109 +2,131 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe ActiveFedora::Base do
|
4
4
|
describe "with inverse" do
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
context "that is also a HABTM" do
|
6
|
+
before do
|
7
|
+
class Book < ActiveFedora::Base
|
8
|
+
has_and_belongs_to_many :topics, predicate: ::RDF::FOAF.primaryTopic, inverse_of: :books
|
9
|
+
end
|
10
|
+
|
11
|
+
class Topic < ActiveFedora::Base
|
12
|
+
has_and_belongs_to_many :books, predicate: ::RDF::FOAF.isPrimaryTopicOf
|
13
|
+
end
|
9
14
|
end
|
10
15
|
|
11
|
-
|
16
|
+
after do
|
17
|
+
Object.send(:remove_const, :Book)
|
18
|
+
Object.send(:remove_const, :Topic)
|
12
19
|
end
|
13
20
|
|
21
|
+
describe "an unsaved instance" do
|
22
|
+
let(:topic1) { Topic.create }
|
23
|
+
let(:book) { Book.create }
|
14
24
|
|
15
|
-
|
16
|
-
|
25
|
+
it "habtm should set and remove relationships bidirectionally" do
|
26
|
+
book.topics << topic1
|
27
|
+
expect(book.topics).to eq [topic1]
|
28
|
+
expect(topic1.books).to eq [book]
|
29
|
+
expect(topic1.reload.books).to eq [book]
|
17
30
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
31
|
+
book.topics.delete(topic1)
|
32
|
+
expect(book.topics).to be_empty
|
33
|
+
expect(topic1.books).to be_empty
|
34
|
+
end
|
22
35
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
36
|
+
it "Should allow for more than 10 items" do
|
37
|
+
(1..12).each do
|
38
|
+
book.topics << Topic.create
|
39
|
+
end
|
40
|
+
book.save
|
41
|
+
expect(book.topics.count).to eq 12
|
42
|
+
book2 = Book.find(book.id)
|
43
|
+
expect(book2.topics.count).to eq 12
|
44
|
+
end
|
29
45
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
46
|
+
context "with subclassed objects" do
|
47
|
+
before do
|
48
|
+
class SpecialInheritedBook < Book
|
49
|
+
end
|
50
|
+
end
|
35
51
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
expect(topic1.books).to eq [@book]
|
40
|
-
expect(topic1.reload.books).to eq [@book]
|
52
|
+
after do
|
53
|
+
Object.send(:remove_const, :SpecialInheritedBook)
|
54
|
+
end
|
41
55
|
|
42
|
-
|
43
|
-
|
44
|
-
|
56
|
+
let!(:special_book) { SpecialInheritedBook.create }
|
57
|
+
it "Should find inherited objects along with base objects" do
|
58
|
+
book.topics << topic1
|
59
|
+
special_book.topics << topic1
|
60
|
+
expect(topic1.books).to match_array [book, special_book]
|
61
|
+
expect(topic1.reload.books).to match_array [book, special_book]
|
62
|
+
end
|
63
|
+
end
|
45
64
|
end
|
46
65
|
|
47
|
-
|
48
|
-
(
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
let!(:special_book) { SpecialInheritedBook.create }
|
59
|
-
it "Should find inherited objects along with base objects" do
|
60
|
-
@book.topics << topic1
|
61
|
-
special_book.topics << topic1
|
62
|
-
expect(topic1.books).to eq [@book, special_book]
|
63
|
-
expect(topic1.reload.books).to eq [@book, special_book]
|
66
|
+
describe "a saved instance" do
|
67
|
+
let!(:book) { Book.create }
|
68
|
+
let!(:topic1) { Topic.create }
|
69
|
+
let!(:topic2) { Topic.create }
|
70
|
+
|
71
|
+
it "should set relationships bidirectionally" do
|
72
|
+
book.topics << topic1
|
73
|
+
expect(book.topics).to eq [topic1]
|
74
|
+
expect(book['topic_ids']).to eq [topic1.id]
|
75
|
+
expect(topic1['book_ids']).to eq [book.id]
|
76
|
+
expect(Topic.find(topic1.id).books).to eq [book] #Can't have saved it because book isn't saved yet.
|
64
77
|
end
|
65
|
-
end
|
66
78
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
79
|
+
it "should save new child objects" do
|
80
|
+
book.topics << Topic.new
|
81
|
+
expect(book.topics.first.id).to_not be_nil
|
82
|
+
end
|
71
83
|
|
72
|
-
|
84
|
+
it "should clear out the old associtions" do
|
85
|
+
book.topics = [topic1]
|
86
|
+
book.topics = [topic2]
|
87
|
+
expect(book.topic_ids).to eq [topic2.id]
|
88
|
+
end
|
73
89
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
90
|
+
context "with members" do
|
91
|
+
before do
|
92
|
+
book.topics = [topic1, topic2]
|
93
|
+
book.save
|
94
|
+
end
|
78
95
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
96
|
+
context "destroy" do
|
97
|
+
it "should remove the associations" do
|
98
|
+
book.destroy
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
85
102
|
end
|
103
|
+
end
|
86
104
|
|
87
|
-
|
88
|
-
|
89
|
-
|
105
|
+
context "that is a has_many" do
|
106
|
+
before do
|
107
|
+
class Book < ActiveFedora::Base
|
108
|
+
has_many :collections
|
109
|
+
end
|
110
|
+
|
111
|
+
class Collection < ActiveFedora::Base
|
112
|
+
has_and_belongs_to_many :books, predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isMemberOfCollection
|
113
|
+
end
|
90
114
|
end
|
91
115
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
expect(book.topic_ids).to eq [topic2.id]
|
116
|
+
after do
|
117
|
+
Object.send(:remove_const, :Book)
|
118
|
+
Object.send(:remove_const, :Collection)
|
96
119
|
end
|
97
120
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
book.save
|
102
|
-
end
|
121
|
+
describe "add and remove members" do
|
122
|
+
let(:collection) { Collection.create }
|
123
|
+
let(:book) { Book.create }
|
103
124
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
125
|
+
it "is successful" do
|
126
|
+
collection.books << book
|
127
|
+
expect {
|
128
|
+
collection.books.delete(book)
|
129
|
+
}.to change { collection.books.size }.from(1).to(0)
|
108
130
|
end
|
109
131
|
end
|
110
132
|
end
|
@@ -297,87 +319,104 @@ describe ActiveFedora::Base do
|
|
297
319
|
end
|
298
320
|
end
|
299
321
|
end
|
300
|
-
end
|
301
322
|
|
302
|
-
describe "create" do
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
323
|
+
describe "create" do
|
324
|
+
before do
|
325
|
+
class Book < ActiveFedora::Base
|
326
|
+
has_and_belongs_to_many :collections, predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isMemberOfCollection
|
327
|
+
end
|
307
328
|
|
308
|
-
|
309
|
-
|
329
|
+
class Collection < ActiveFedora::Base
|
330
|
+
property :title, predicate: ::RDF::DC.title
|
331
|
+
end
|
310
332
|
end
|
311
|
-
end
|
312
333
|
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
334
|
+
after do
|
335
|
+
Object.send(:remove_const, :Book)
|
336
|
+
Object.send(:remove_const, :Collection)
|
337
|
+
end
|
317
338
|
|
318
|
-
|
339
|
+
let(:book) { Book.create }
|
319
340
|
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
341
|
+
it "should create" do
|
342
|
+
collection = book.collections.create(title: ["Permanent"])
|
343
|
+
expect(collection).to be_kind_of Collection
|
344
|
+
expect(book.collections).to include collection
|
345
|
+
book.save
|
346
|
+
expect(book.reload.collections.first.title).to eq ['Permanent']
|
347
|
+
end
|
326
348
|
end
|
327
|
-
end
|
328
349
|
|
329
350
|
|
330
|
-
describe "Autosave" do
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
351
|
+
describe "Autosave" do
|
352
|
+
before do
|
353
|
+
class Item < ActiveFedora::Base
|
354
|
+
has_many :components
|
355
|
+
has_metadata "foo", type: ActiveFedora::SimpleDatastream do |m|
|
356
|
+
m.field "title", :string
|
357
|
+
end
|
358
|
+
has_attributes :title, datastream: 'foo'
|
359
|
+
end
|
360
|
+
|
361
|
+
class Component < ActiveFedora::Base
|
362
|
+
has_and_belongs_to_many :items, predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isPartOf
|
363
|
+
has_metadata "foo", type: ActiveFedora::SimpleDatastream do |m|
|
364
|
+
m.field "description", :string
|
365
|
+
end
|
366
|
+
has_attributes :description, datastream: 'foo'
|
336
367
|
end
|
337
|
-
has_attributes :title, datastream: 'foo'
|
338
|
-
end
|
339
368
|
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
m.field "description", :string
|
369
|
+
after do
|
370
|
+
Object.send(:remove_const, :Item)
|
371
|
+
Object.send(:remove_const, :Component)
|
344
372
|
end
|
345
|
-
has_attributes :description, datastream: 'foo'
|
346
|
-
end
|
347
|
-
end
|
348
373
|
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
374
|
+
describe "From the has_and_belongs_to_many side" do
|
375
|
+
describe "dependent records" do
|
376
|
+
let(:component) { Component.create(items: [Item.new(title: 'my title')]) }
|
377
|
+
|
378
|
+
it "should be saved" do
|
379
|
+
component.reload
|
380
|
+
expect(component.items.first.title).to eq 'my title'
|
381
|
+
end
|
382
|
+
end
|
353
383
|
|
354
|
-
|
355
|
-
|
356
|
-
|
384
|
+
describe "shifting" do
|
385
|
+
let(:component) { Component.new }
|
386
|
+
let(:item) { Item.create }
|
357
387
|
|
358
|
-
|
359
|
-
|
360
|
-
|
388
|
+
it "should set item_ids" do
|
389
|
+
component.items << item
|
390
|
+
expect(component.item_ids).to eq [item.id]
|
391
|
+
end
|
392
|
+
end
|
361
393
|
end
|
362
|
-
end
|
363
394
|
|
364
|
-
|
365
|
-
|
366
|
-
|
395
|
+
context "when the has_and_belongs_to_many provides an inverse_of" do
|
396
|
+
let(:reflection) { Component.reflect_on_association(:items) }
|
397
|
+
before do
|
398
|
+
reflection.options[:inverse_of] = :components
|
399
|
+
end
|
400
|
+
|
401
|
+
describe "shifting" do
|
402
|
+
let(:component) { Component.create }
|
403
|
+
let(:item) { Item.new }
|
367
404
|
|
368
|
-
|
369
|
-
|
370
|
-
|
405
|
+
it "should set item_ids" do
|
406
|
+
component.items << item
|
407
|
+
expect(component.item_ids).to eq [item.id]
|
408
|
+
end
|
409
|
+
end
|
371
410
|
end
|
372
|
-
end
|
373
|
-
end
|
374
411
|
|
375
|
-
|
376
|
-
|
412
|
+
describe "From the has_many side" do
|
413
|
+
let(:item) { Item.create(components: [Component.new(description: 'my description')]) }
|
377
414
|
|
378
|
-
|
379
|
-
|
380
|
-
|
415
|
+
it "should save dependent records" do
|
416
|
+
item.reload
|
417
|
+
expect(item.components.first.description).to eq 'my description'
|
418
|
+
end
|
419
|
+
end
|
381
420
|
end
|
382
421
|
end
|
383
422
|
end
|