active-fedora 13.1.2 → 13.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (140) hide show
  1. checksums.yaml +4 -4
  2. data/.github_changelog_generator +2 -0
  3. data/CHANGELOG.md +3362 -0
  4. data/CONTRIBUTING.md +23 -1
  5. data/README.md +4 -0
  6. data/active-fedora.gemspec +14 -13
  7. data/lib/active_fedora/version.rb +1 -1
  8. metadata +104 -206
  9. data/spec/config_helper.rb +0 -17
  10. data/spec/fixtures/dino.jpg +0 -0
  11. data/spec/fixtures/dino_jpg_no_file_ext +0 -0
  12. data/spec/fixtures/minivan.jpg +0 -0
  13. data/spec/fixtures/rails_root/config/fake_fedora.yml +0 -7
  14. data/spec/fixtures/rails_root/config/fedora.yml +0 -12
  15. data/spec/fixtures/rails_root/config/solr.yml +0 -15
  16. data/spec/fixtures/rails_root/config/solr_mappings.yml +0 -16
  17. data/spec/fixtures/rails_root/config/solr_mappings_af_0.1.yml +0 -9
  18. data/spec/fixtures/rails_root/config/solr_mappings_bl_2.4.yml +0 -17
  19. data/spec/integration/associations/rdf_spec.rb +0 -61
  20. data/spec/integration/associations_spec.rb +0 -680
  21. data/spec/integration/attached_files_spec.rb +0 -146
  22. data/spec/integration/attributes_spec.rb +0 -73
  23. data/spec/integration/autosave_association_spec.rb +0 -24
  24. data/spec/integration/base_spec.rb +0 -184
  25. data/spec/integration/basic_contains_association_spec.rb +0 -121
  26. data/spec/integration/belongs_to_association_spec.rb +0 -260
  27. data/spec/integration/caching_spec.rb +0 -59
  28. data/spec/integration/clean_connection_spec.rb +0 -21
  29. data/spec/integration/collection_association_spec.rb +0 -166
  30. data/spec/integration/date_time_properties_spec.rb +0 -41
  31. data/spec/integration/delete_all_spec.rb +0 -64
  32. data/spec/integration/direct_container_spec.rb +0 -250
  33. data/spec/integration/directly_contains_one_association_spec.rb +0 -96
  34. data/spec/integration/eradicate_spec.rb +0 -52
  35. data/spec/integration/fedora_solr_sync_spec.rb +0 -30
  36. data/spec/integration/file_fixity_spec.rb +0 -36
  37. data/spec/integration/file_spec.rb +0 -221
  38. data/spec/integration/generators/fedora_generator_spec.rb +0 -26
  39. data/spec/integration/generators/solr_generator_spec.rb +0 -23
  40. data/spec/integration/gone_spec.rb +0 -41
  41. data/spec/integration/has_and_belongs_to_many_associations_spec.rb +0 -414
  42. data/spec/integration/has_many_associations_spec.rb +0 -436
  43. data/spec/integration/has_subresource_spec.rb +0 -34
  44. data/spec/integration/indexing/descendant_fetcher_spec.rb +0 -64
  45. data/spec/integration/indexing_spec.rb +0 -110
  46. data/spec/integration/indirect_container_spec.rb +0 -290
  47. data/spec/integration/json_serialization_spec.rb +0 -32
  48. data/spec/integration/marshal_spec.rb +0 -39
  49. data/spec/integration/nested_attribute_spec.rb +0 -177
  50. data/spec/integration/nested_hash_resources_spec.rb +0 -43
  51. data/spec/integration/persistence_spec.rb +0 -37
  52. data/spec/integration/query_result_builder_spec.rb +0 -37
  53. data/spec/integration/rdf_nested_attributes_spec.rb +0 -85
  54. data/spec/integration/relation_delegation_spec.rb +0 -52
  55. data/spec/integration/relation_spec.rb +0 -117
  56. data/spec/integration/scoped_query_spec.rb +0 -134
  57. data/spec/integration/scoping_spec.rb +0 -48
  58. data/spec/integration/solr_hit_spec.rb +0 -32
  59. data/spec/integration/versionable_spec.rb +0 -256
  60. data/spec/integration/with_metadata_spec.rb +0 -111
  61. data/spec/lib/active_fedora/null_logger_spec.rb +0 -10
  62. data/spec/rcov.opts +0 -2
  63. data/spec/spec.opts +0 -5
  64. data/spec/spec_helper.rb +0 -106
  65. data/spec/support/an_active_model.rb +0 -29
  66. data/spec/unit/active_fedora/indexing/inserter_spec.rb +0 -35
  67. data/spec/unit/active_fedora_spec.rb +0 -118
  68. data/spec/unit/aggregation/list_source_spec.rb +0 -134
  69. data/spec/unit/aggregation/ordered_reader_spec.rb +0 -43
  70. data/spec/unit/association_hash_spec.rb +0 -64
  71. data/spec/unit/attached_files_spec.rb +0 -218
  72. data/spec/unit/attributes_spec.rb +0 -146
  73. data/spec/unit/base_active_model_spec.rb +0 -28
  74. data/spec/unit/base_cma_spec.rb +0 -15
  75. data/spec/unit/base_extra_spec.rb +0 -33
  76. data/spec/unit/base_spec.rb +0 -328
  77. data/spec/unit/builder/has_and_belongs_to_many_spec.rb +0 -8
  78. data/spec/unit/callback_spec.rb +0 -65
  79. data/spec/unit/change_set_spec.rb +0 -60
  80. data/spec/unit/checksum_spec.rb +0 -25
  81. data/spec/unit/code_configurator_spec.rb +0 -41
  82. data/spec/unit/collection_proxy_spec.rb +0 -25
  83. data/spec/unit/config_spec.rb +0 -18
  84. data/spec/unit/core/fedora_id_translator_spec.rb +0 -29
  85. data/spec/unit/core/fedora_uri_translator_spec.rb +0 -19
  86. data/spec/unit/core/logger_spec.rb +0 -18
  87. data/spec/unit/core_spec.rb +0 -242
  88. data/spec/unit/default_model_mapper_spec.rb +0 -39
  89. data/spec/unit/fedora_spec.rb +0 -31
  90. data/spec/unit/file/streaming_spec.rb +0 -33
  91. data/spec/unit/file_configurator_spec.rb +0 -295
  92. data/spec/unit/file_io_spec.rb +0 -137
  93. data/spec/unit/file_path_builder_spec.rb +0 -18
  94. data/spec/unit/file_spec.rb +0 -489
  95. data/spec/unit/files_hash_spec.rb +0 -52
  96. data/spec/unit/filter_spec.rb +0 -133
  97. data/spec/unit/finder_methods_spec.rb +0 -154
  98. data/spec/unit/fixity_service_spec.rb +0 -128
  99. data/spec/unit/forbidden_attributes_protection_spec.rb +0 -50
  100. data/spec/unit/has_and_belongs_to_many_association_spec.rb +0 -125
  101. data/spec/unit/has_many_association_spec.rb +0 -131
  102. data/spec/unit/indexers/global_indexer_spec.rb +0 -41
  103. data/spec/unit/indexing/map/index_object_spec.rb +0 -25
  104. data/spec/unit/indexing/map_spec.rb +0 -27
  105. data/spec/unit/indexing_service_spec.rb +0 -28
  106. data/spec/unit/indexing_spec.rb +0 -86
  107. data/spec/unit/inheritance_spec.rb +0 -60
  108. data/spec/unit/ldp_resource_spec.rb +0 -15
  109. data/spec/unit/loadable_from_json_spec.rb +0 -40
  110. data/spec/unit/logger_spec.rb +0 -19
  111. data/spec/unit/model_classifier_spec.rb +0 -49
  112. data/spec/unit/ordered_spec.rb +0 -367
  113. data/spec/unit/orders/list_node_spec.rb +0 -151
  114. data/spec/unit/orders/ordered_list_spec.rb +0 -335
  115. data/spec/unit/orders/reflection_spec.rb +0 -22
  116. data/spec/unit/pathing_spec.rb +0 -35
  117. data/spec/unit/persistence_spec.rb +0 -115
  118. data/spec/unit/property_predicate_spec.rb +0 -35
  119. data/spec/unit/property_spec.rb +0 -25
  120. data/spec/unit/query_result_builder_spec.rb +0 -31
  121. data/spec/unit/query_spec.rb +0 -307
  122. data/spec/unit/querying_spec.rb +0 -24
  123. data/spec/unit/rdf/indexing_service_spec.rb +0 -114
  124. data/spec/unit/rdf_vocab_spec.rb +0 -30
  125. data/spec/unit/readonly_spec.rb +0 -24
  126. data/spec/unit/reflection_spec.rb +0 -42
  127. data/spec/unit/rspec_matchers/belong_to_associated_active_fedora_object_matcher_spec.rb +0 -37
  128. data/spec/unit/rspec_matchers/have_many_associated_active_fedora_objects_matcher_spec.rb +0 -38
  129. data/spec/unit/rspec_matchers/have_predicate_matcher_spec.rb +0 -38
  130. data/spec/unit/schema_indexing_strategy_spec.rb +0 -68
  131. data/spec/unit/scoping_spec.rb +0 -67
  132. data/spec/unit/serializers_spec.rb +0 -19
  133. data/spec/unit/solr_config_options_spec.rb +0 -57
  134. data/spec/unit/solr_hit_spec.rb +0 -57
  135. data/spec/unit/solr_query_builder_spec.rb +0 -18
  136. data/spec/unit/solr_service_spec.rb +0 -165
  137. data/spec/unit/sparql_insert_spec.rb +0 -31
  138. data/spec/unit/validations_spec.rb +0 -92
  139. data/spec/unit/with_metadata/default_metadata_class_factory_spec.rb +0 -29
  140. data/spec/unit/with_metadata/metadata_node_spec.rb +0 -69
@@ -1,52 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe ActiveFedora::Base do
4
- before(:all) do
5
- class ResurrectionModel < ActiveFedora::Base
6
- after_destroy :eradicate
7
- end
8
- end
9
-
10
- after(:all) do
11
- Object.send(:remove_const, :ResurrectionModel)
12
- end
13
-
14
- context "when an object is has already been deleted" do
15
- let(:ghost) do
16
- obj = described_class.create
17
- obj.destroy
18
- obj.id
19
- end
20
- context "in a typical sitation" do
21
- specify "it cannot be reused" do
22
- expect { described_class.create(id: ghost) }.to raise_error(Ldp::Gone)
23
- end
24
- end
25
- specify "remove its tombstone" do
26
- expect(described_class.eradicate(ghost)).to be true
27
- end
28
- end
29
-
30
- context "when an object has just been deleted" do
31
- let(:zombie) do
32
- obj = described_class.create
33
- obj.destroy
34
- return obj
35
- end
36
- specify "remove its tombstone" do
37
- expect(zombie.eradicate).to be true
38
- end
39
- end
40
-
41
- describe "a model with no tombstones" do
42
- let(:lazarus) do
43
- body = ResurrectionModel.create
44
- soul = body.id
45
- body.destroy
46
- return soul
47
- end
48
- it "allows reusing a uri" do
49
- expect(ResurrectionModel.create(id: lazarus)).to be_kind_of(ResurrectionModel)
50
- end
51
- end
52
- end
@@ -1,30 +0,0 @@
1
- require 'spec_helper'
2
- require 'timeout'
3
-
4
- describe "fedora_solr_sync_issues" do
5
- before :all do
6
- class ParentThing < ActiveFedora::Base
7
- has_many :things, class_name: 'ChildThing', predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isPartOf
8
- end
9
-
10
- class ChildThing < ActiveFedora::Base
11
- belongs_to :parent, class_name: 'ParentThing', predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isPartOf
12
- end
13
- end
14
-
15
- after :all do
16
- Object.send(:remove_const, :ChildThing)
17
- Object.send(:remove_const, :ParentThing)
18
- end
19
-
20
- subject(:child) { ChildThing.create parent: parent }
21
- let(:parent) { ParentThing.create }
22
-
23
- before { Ldp::Resource::RdfSource.new(ActiveFedora.fedora.connection, child.uri).delete }
24
-
25
- it "does not go into an infinite loop" do
26
- parent.reload
27
- expect(ActiveFedora::Base.logger).to receive(:error).with("Solr and Fedora may be out of sync:\n")
28
- expect(parent.things).to eq []
29
- end
30
- end
@@ -1,36 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe "Checking fixity" do
4
- before(:all) do
5
- class MockAFBase < ActiveFedora::Base
6
- has_subresource "data", autocreate: true
7
- end
8
- end
9
-
10
- after(:all) do
11
- Object.send(:remove_const, :MockAFBase)
12
- end
13
-
14
- subject do
15
- obj = MockAFBase.create
16
- obj.data.content = "some content"
17
- obj.save
18
- obj.data.check_fixity
19
- end
20
-
21
- context "with a valid resource" do
22
- it { is_expected.to be true }
23
- end
24
- context "when no uri has been set" do
25
- subject(:file) { ActiveFedora::File.new }
26
- it "raises an error" do
27
- expect { file.check_fixity }.to raise_error(ArgumentError, "You must provide a uri")
28
- end
29
- end
30
- context "with missing resource" do
31
- subject(:file) { ActiveFedora::File.new(ActiveFedora::Base.id_to_uri('123')) }
32
- it "raises an error" do
33
- expect { file.check_fixity }.to raise_error(Ldp::NotFound)
34
- end
35
- end
36
- end
@@ -1,221 +0,0 @@
1
- require 'spec_helper'
2
-
3
- require 'active_fedora'
4
- require "rexml/document"
5
-
6
- describe ActiveFedora::File do
7
- let(:file) { described_class.new }
8
- describe "#save" do
9
- context "with new files" do
10
- context "with a string" do
11
- before { file.content = "hello" }
12
- it "saves" do
13
- expect(file.save).to be true
14
- end
15
- end
16
-
17
- context "with no content" do
18
- before { file.content = nil }
19
- it "does not save" do
20
- expect(file.save).to be false
21
- end
22
- end
23
- end
24
-
25
- context "with UploadedFile" do
26
- before do
27
- module ActionDispatch
28
- module Http
29
- class UploadedFile
30
- def initialize
31
- @content = StringIO.new("hello world")
32
- end
33
-
34
- def read(a, b)
35
- @content.read(a, b)
36
- end
37
-
38
- def size
39
- @content.length
40
- end
41
- end
42
- end
43
- end
44
- end
45
-
46
- it "saves" do
47
- file.content = ActionDispatch::Http::UploadedFile.new
48
- file.save
49
- expect(file).not_to be_new_record
50
- end
51
- end
52
- end
53
-
54
- context "with a sub-resource that autocreates" do
55
- before do
56
- class MockAFBase < ActiveFedora::Base
57
- has_subresource "descMetadata", class_name: 'SampleResource', autocreate: true
58
- end
59
-
60
- class SampleResource < ActiveFedora::File
61
- def content
62
- 'something to save'
63
- end
64
- end
65
- end
66
-
67
- after do
68
- Object.send(:remove_const, :SampleResource)
69
- Object.send(:remove_const, :MockAFBase)
70
- end
71
-
72
- let(:test_object) { MockAFBase.create }
73
- let(:descMetadata) { test_object.descMetadata }
74
-
75
- describe "changed attributes are set" do
76
- it "marks profile as changed" do
77
- expect_any_instance_of(SampleResource).to receive(:attribute_will_change!).with(:ldp_source)
78
- test_object
79
- end
80
- end
81
-
82
- describe "content_changed? is called" do
83
- before do
84
- allow_any_instance_of(SampleResource).to receive(:content_changed?).and_return(true)
85
- end
86
- subject { descMetadata.described_by }
87
- it { is_expected.to eq descMetadata.uri + '/fcr:metadata' }
88
- end
89
- end
90
-
91
- describe "#content" do
92
- let(:file) { described_class.new { |ds| ds.content = content } }
93
-
94
- before do
95
- file.save
96
- end
97
-
98
- describe "#content" do
99
- subject(:resource) { described_class.new(file.uri).content }
100
-
101
- before { content.rewind }
102
-
103
- context "when encoding is not set" do
104
- let(:content) { fixture('dino.jpg') }
105
-
106
- it "is read from fedora" do
107
- expect(resource).to eq content.read
108
- expect(resource.encoding).to eq Encoding::ASCII_8BIT
109
- end
110
- end
111
-
112
- context "when encoding is set" do
113
- let(:file) do
114
- described_class.new do |f|
115
- f.content = content
116
- f.mime_type = 'text/plain;charset=UTF-8'
117
- end
118
- end
119
- let(:content) { StringIO.new "I'm a little teåpot" }
120
-
121
- it "is read from fedora" do
122
- expect(resource).to eq content.read
123
- expect(resource.encoding).to eq Encoding::UTF_8
124
- end
125
- end
126
- end
127
- end
128
-
129
- context "with a sub-resource" do
130
- before do
131
- class MockAFBase < ActiveFedora::Base
132
- has_subresource "descMetadata", class_name: 'SampleResource'
133
- end
134
-
135
- class SampleResource < ActiveFedora::File
136
- end
137
- end
138
-
139
- after do
140
- Object.send(:remove_const, :SampleResource)
141
- Object.send(:remove_const, :MockAFBase)
142
- end
143
-
144
- let(:test_object) { MockAFBase.create }
145
- let(:descMetadata) { test_object.descMetadata }
146
-
147
- describe "the metadata file" do
148
- subject { descMetadata }
149
- it { is_expected.to be_a_kind_of(described_class) }
150
- end
151
-
152
- context "a binary file" do
153
- let(:path) { "ds#{Time.now.to_i}" }
154
- let(:content) { fixture('dino.jpg') }
155
- let(:file) { described_class.new { |ds| ds.content = content } }
156
-
157
- before do
158
- test_object.attach_file(file, path)
159
- test_object.save
160
- end
161
-
162
- it "is not changed" do
163
- expect(test_object.attached_files[path]).to_not be_content_changed
164
- end
165
-
166
- describe "streaming the response" do
167
- let(:stream_reader) { instance_double(IO) }
168
- it "streams the response" do
169
- expect(stream_reader).to receive(:read).at_least(:once)
170
- test_object.attached_files[path].stream.each { |buff| stream_reader.read(buff) }
171
- end
172
-
173
- context "with a range request" do
174
- before do
175
- test_object.add_file('one1two2threfour', path: 'webm', mime_type: 'video/webm')
176
- test_object.save!
177
- end
178
- subject { str = ''; test_object.webm.stream(range).each { |chunk| str << chunk }; str }
179
- context "whole thing" do
180
- let(:range) { 'bytes=0-15' }
181
- it { is_expected.to eq 'one1two2threfour' }
182
- end
183
- context "open ended" do
184
- let(:range) { 'bytes=0-' }
185
- it { is_expected.to eq 'one1two2threfour' }
186
- end
187
- context "not starting at the beginning" do
188
- let(:range) { 'bytes=3-15' }
189
- it { is_expected.to eq '1two2threfour' }
190
- end
191
- context "not ending at the end" do
192
- let(:range) { 'bytes=4-11' }
193
- it { is_expected.to eq 'two2thre' }
194
- end
195
- end
196
-
197
- context "when the request results in a redirect" do
198
- before do
199
- test_object.add_file('one1two2threfour', path: 'webm', mime_type: 'video/webm')
200
- test_object.add_file('', path: 'redirector', mime_type: "message/external-body; access-type=URL; url=\"#{test_object.webm.uri}\"")
201
- test_object.save!
202
- end
203
- subject { str = ''; test_object.redirector.stream.each { |chunk| str << chunk }; str }
204
- it { is_expected.to eq 'one1two2threfour' }
205
- end
206
-
207
- context "when there are more than 3 requests because of redirects" do
208
- before do
209
- test_object.add_file('', path: 'one', mime_type: "message/external-body; access-type=URL; url=\"#{test_object.attached_files[path].uri}\"")
210
- test_object.add_file('', path: 'two', mime_type: "message/external-body; access-type=URL; url=\"#{test_object.one.uri}\"")
211
- test_object.add_file('', path: 'three', mime_type: "message/external-body; access-type=URL; url=\"#{test_object.two.uri}\"")
212
- test_object.save!
213
- end
214
- it "raises a HTTP redirect too deep Error" do
215
- expect { test_object.three.stream.each { |chunk| chunk } }.to raise_error('HTTP redirect too deep')
216
- end
217
- end
218
- end
219
- end
220
- end
221
- end
@@ -1,26 +0,0 @@
1
- require 'spec_helper'
2
- require 'generators/active_fedora/config/fedora/fedora_generator'
3
-
4
- describe ActiveFedora::Config::FedoraGenerator do
5
- describe "#fcrepo_wrapper_config" do
6
- let(:generator) { described_class.new }
7
- let(:files_to_test) { [
8
- 'config/fcrepo_wrapper_test.yml',
9
- '.fcrepo_wrapper.yml'
10
- ]}
11
-
12
- before do
13
- generator.fcrepo_wrapper_config
14
- end
15
-
16
- after do
17
- files_to_test.each { |file| File.delete(file) if File.exist?(file) }
18
- end
19
-
20
- it "creates config files" do
21
- files_to_test.each do |file|
22
- expect(File).to exist(file), "Expected #{file} to exist"
23
- end
24
- end
25
- end
26
- end
@@ -1,23 +0,0 @@
1
- require 'spec_helper'
2
- require 'generators/active_fedora/config/solr/solr_generator'
3
-
4
- describe ActiveFedora::Config::SolrGenerator do
5
- describe "#solr_wrapper_config" do
6
- let(:generator) { described_class.new }
7
- let(:files_to_test) { [
8
- 'config/solr_wrapper_test.yml',
9
- '.solr_wrapper.yml'
10
- ]}
11
-
12
- it "creates config files" do
13
- Dir.mktmpdir do |dir|
14
- Dir.chdir(dir) do
15
- generator.solr_wrapper_config
16
- files_to_test.each do |file|
17
- expect(File).to exist(file), "Expected #{file} to exist"
18
- end
19
- end
20
- end
21
- end
22
- end
23
- end
@@ -1,41 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe ActiveFedora::Base do
4
- before(:all) do
5
- class ResurrectionModel < ActiveFedora::Base
6
- after_destroy :eradicate
7
- end
8
- end
9
-
10
- after(:all) do
11
- Object.send(:remove_const, :ResurrectionModel)
12
- end
13
-
14
- context "when an object is has already been deleted" do
15
- let(:ghost) do
16
- obj = described_class.create
17
- obj.destroy
18
- obj.id
19
- end
20
- it "is gone" do
21
- expect(described_class.gone?(ghost)).to be true
22
- end
23
- end
24
-
25
- context "when the id has never been used" do
26
- let(:id) { "abc123" }
27
- it "is not gone" do
28
- expect(described_class.gone?(id)).to be false
29
- end
30
- end
31
-
32
- context "when the id is in use" do
33
- let(:active) do
34
- obj = described_class.create
35
- obj.id
36
- end
37
- it "is not gone" do
38
- expect(described_class.gone?(active)).to be false
39
- end
40
- end
41
- end
@@ -1,414 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe ActiveFedora::Base do
4
- describe "with inverse" do
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::Vocab::FOAF.primaryTopic, inverse_of: :books
9
- end
10
-
11
- class Topic < ActiveFedora::Base
12
- has_and_belongs_to_many :books, predicate: ::RDF::Vocab::FOAF.isPrimaryTopicOf
13
- end
14
- end
15
-
16
- after do
17
- Object.send(:remove_const, :Book)
18
- Object.send(:remove_const, :Topic)
19
- end
20
-
21
- describe "an unsaved instance" do
22
- let(:topic1) { Topic.create }
23
- let(:book) { Book.create }
24
-
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]
30
-
31
- book.topics.delete(topic1)
32
- expect(book.topics).to be_empty
33
- expect(topic1.books).to be_empty
34
- end
35
-
36
- it "allows for more than 10 items" do
37
- 12.times 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
45
-
46
- context "with subclassed objects" do
47
- before do
48
- class SpecialInheritedBook < Book
49
- end
50
- end
51
-
52
- after do
53
- Object.send(:remove_const, :SpecialInheritedBook)
54
- end
55
-
56
- let!(:special_book) { SpecialInheritedBook.create }
57
- it "finds 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
64
- end
65
-
66
- describe "a saved instance" do
67
- let!(:book) { Book.create }
68
- let!(:topic1) { Topic.create }
69
- let!(:topic2) { Topic.create }
70
-
71
- it "sets 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.
77
- end
78
-
79
- it "saves new child objects" do
80
- book.topics << Topic.new
81
- expect(book.topics.first.id).to_not be_nil
82
- end
83
-
84
- it "clears out the old associtions" do
85
- book.topics = [topic1]
86
- book.topics = [topic2]
87
- expect(book.topic_ids).to eq [topic2.id]
88
- end
89
-
90
- context "with members" do
91
- before do
92
- book.topics = [topic1, topic2]
93
- book.save
94
- end
95
-
96
- context "destroy" do
97
- it "removes the associations" do
98
- book.destroy
99
- end
100
- end
101
- end
102
- end
103
- end
104
-
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
114
- end
115
-
116
- after do
117
- Object.send(:remove_const, :Book)
118
- Object.send(:remove_const, :Collection)
119
- end
120
-
121
- describe "add and remove members" do
122
- let(:collection) { Collection.create }
123
- let(:book) { Book.create }
124
-
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)
130
- end
131
- end
132
- end
133
- end
134
-
135
- describe "when inverse is not specified" do
136
- before do
137
- class Book < ActiveFedora::Base
138
- has_and_belongs_to_many :collections, predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isMemberOfCollection
139
- end
140
-
141
- class Collection < ActiveFedora::Base
142
- has_and_belongs_to_many :books, predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isMemberOfCollection
143
- end
144
- end
145
-
146
- after do
147
- Object.send(:remove_const, :Book)
148
- Object.send(:remove_const, :Collection)
149
- end
150
-
151
- let(:book) { Book.create }
152
- let(:collection) { Collection.create }
153
-
154
- context "when the book is a member of the collection" do
155
- before do
156
- book.collections << collection
157
- book.save!
158
- end
159
-
160
- it "has a collection" do
161
- expect(book['collection_ids']).to eq [collection.id]
162
- expect(book.collections).to eq [collection]
163
- end
164
- it "habtm should not set foreign relationships if :inverse_of is not specified" do
165
- expect(collection['book_ids']).to be_empty
166
- end
167
- it "loads the collections" do
168
- reloaded = Book.find(book.id)
169
- expect(reloaded.collections).to eq [collection]
170
- end
171
-
172
- describe "#empty?" do
173
- subject { book.collections }
174
- it { is_expected.to_not be_empty }
175
- end
176
- end
177
-
178
- context "when a book isn't in a collection" do
179
- describe "#empty?" do
180
- subject { book.collections }
181
- it { is_expected.to be_empty }
182
- end
183
- end
184
- end
185
-
186
- describe "when destroying the association" do
187
- describe "without callbacks" do
188
- before do
189
- class Book < ActiveFedora::Base
190
- has_and_belongs_to_many :collections, predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isMemberOfCollection
191
- end
192
-
193
- class Collection < ActiveFedora::Base
194
- end
195
- end
196
-
197
- after do
198
- Object.send(:remove_const, :Book)
199
- Object.send(:remove_const, :Collection)
200
- end
201
-
202
- let(:book) { Book.create }
203
- let(:collection1) { Collection.create }
204
- let(:collection2) { Collection.create }
205
- before do
206
- book.collections << collection1 << collection2
207
- book.save!
208
- end
209
-
210
- it "delete should cause the entries to be removed from RELS-EXT, but not destroy the original record" do
211
- expect(book.collections).to contain_exactly collection1, collection2
212
- book.collections.delete(collection1)
213
- expect(book.collections).to eq [collection2]
214
- book.save!
215
- book.reload
216
- expect(book.collections).to eq [collection2]
217
- expect(Collection.find(collection1.id)).to_not be_nil
218
- end
219
-
220
- it "destroy should cause the entries to be removed from RELS-EXT, but not destroy the original record" do
221
- expect(book.collections).to contain_exactly collection1, collection2
222
- book.collections.destroy(collection1)
223
- expect(book.collections).to eq [collection2]
224
- book.save!
225
- book.reload
226
- expect(book.collections).to eq [collection2]
227
- expect(Collection.find(collection1.id)).to_not be_nil
228
- end
229
- end
230
-
231
- describe "with remove callbacks" do
232
- before do
233
- class Book < ActiveFedora::Base
234
- has_and_belongs_to_many :collections,
235
- predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isMemberOfCollection,
236
- before_remove: :foo, after_remove: :bar
237
- end
238
-
239
- class Collection < ActiveFedora::Base
240
- end
241
- end
242
-
243
- after do
244
- Object.send(:remove_const, :Book)
245
- Object.send(:remove_const, :Collection)
246
- end
247
-
248
- let(:book) { Book.create }
249
- let(:collection) { Collection.create }
250
- before do
251
- book.collections << collection
252
- book.save!
253
- end
254
-
255
- it "destroy should cause the before_remove and after_remove callback to be triggered" do
256
- expect(book).to receive(:foo).with(collection)
257
- expect(book).to receive(:bar).with(collection)
258
- book.collections.destroy(collection)
259
- end
260
-
261
- it "delete should cause the before_remove and after_remove callback to be triggered" do
262
- expect(book).to receive(:foo).with(collection)
263
- expect(book).to receive(:bar).with(collection)
264
- book.collections.delete(collection)
265
- end
266
-
267
- it "does not remove if an exception is thrown in before_remove" do
268
- expect(book).to receive(:foo).with(collection).and_raise
269
- expect(book).to_not receive(:bar)
270
- begin
271
- book.collections.delete(collection)
272
- rescue RuntimeError
273
- end
274
- expect(book.collections).to eq [collection]
275
- end
276
- end
277
-
278
- describe "with add callbacks" do
279
- before do
280
- class Book < ActiveFedora::Base
281
- has_and_belongs_to_many :collections,
282
- predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isMemberOfCollection,
283
- before_add: :foo, after_add: :bar
284
- end
285
-
286
- class Collection < ActiveFedora::Base
287
- end
288
- end
289
-
290
- after do
291
- Object.send(:remove_const, :Book)
292
- Object.send(:remove_const, :Collection)
293
- end
294
-
295
- let(:book) { Book.create }
296
- let(:collection) { Collection.create }
297
-
298
- it "shift should cause the before_add and after_add callback to be triggered" do
299
- expect(book).to receive(:foo).with(collection)
300
- expect(book).to receive(:bar).with(collection)
301
- book.collections << collection
302
- end
303
-
304
- it "assignment should cause the before_add and after_add callback to be triggered" do
305
- expect(book).to receive(:foo).with(collection)
306
- expect(book).to receive(:bar).with(collection)
307
- book.collections = [collection]
308
- end
309
-
310
- it "does not add if an exception is thrown in before_add" do
311
- expect(book).to receive(:foo).with(collection).and_raise
312
- expect(book).to_not receive(:bar)
313
- begin
314
- book.collections << collection
315
- rescue RuntimeError
316
- end
317
- expect(book.collections).to eq []
318
- end
319
- end
320
- end
321
-
322
- describe "create" do
323
- before do
324
- class Book < ActiveFedora::Base
325
- has_and_belongs_to_many :collections, predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isMemberOfCollection
326
- end
327
-
328
- class Collection < ActiveFedora::Base
329
- property :title, predicate: ::RDF::Vocab::DC.title
330
- end
331
- end
332
-
333
- after do
334
- Object.send(:remove_const, :Book)
335
- Object.send(:remove_const, :Collection)
336
- end
337
-
338
- let(:book) { Book.create }
339
-
340
- it "creates" do
341
- collection = book.collections.create(title: ["Permanent"])
342
- expect(collection).to be_kind_of Collection
343
- expect(book.collections).to include collection
344
- book.save
345
- expect(book.reload.collections.first.title).to eq ['Permanent']
346
- end
347
- end
348
-
349
- describe "Autosave" do
350
- before do
351
- class Item < ActiveFedora::Base
352
- has_many :components
353
- property :title, predicate: ::RDF::Vocab::DC.title
354
- end
355
-
356
- class Component < ActiveFedora::Base
357
- has_and_belongs_to_many :items, predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isPartOf
358
- property :description, predicate: ::RDF::Vocab::DC.description
359
- end
360
- end
361
-
362
- after do
363
- Object.send(:remove_const, :Item)
364
- Object.send(:remove_const, :Component)
365
- end
366
-
367
- describe "From the has_and_belongs_to_many side" do
368
- describe "dependent records" do
369
- let(:component) { Component.create(items: [Item.new(title: ['my title'])]) }
370
-
371
- it "is saved" do
372
- component.reload
373
- expect(component.items.first.title).to eq ['my title']
374
- end
375
- end
376
-
377
- describe "shifting" do
378
- let(:component) { Component.new }
379
- let(:item) { Item.create }
380
-
381
- it "sets item_ids" do
382
- component.items << item
383
- expect(component.item_ids).to eq [item.id]
384
- end
385
- end
386
-
387
- context "when the has_and_belongs_to_many provides an inverse_of" do
388
- let(:reflection) { Component._reflect_on_association(:items) }
389
- before do
390
- reflection.options[:inverse_of] = :components
391
- end
392
-
393
- describe "shifting" do
394
- let(:component) { Component.create }
395
- let(:item) { Item.new }
396
-
397
- it "sets item_ids" do
398
- component.items << item
399
- expect(component.item_ids).to eq [item.id]
400
- end
401
- end
402
- end
403
- end
404
-
405
- describe "From the has_many side" do
406
- let(:item) { Item.create(components: [Component.new(description: ['my description'])]) }
407
-
408
- it "saves dependent records" do
409
- item.reload
410
- expect(item.components.first.description).to eq ['my description']
411
- end
412
- end
413
- end
414
- end