active-fedora 6.8.0 → 7.0.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (215) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +15 -5
  4. data/CONTRIBUTING.md +2 -0
  5. data/Gemfile +0 -2
  6. data/History.txt +2 -32
  7. data/README.md +143 -0
  8. data/Rakefile +5 -7
  9. data/active-fedora.gemspec +9 -9
  10. data/gemfiles/rails3.gemfile +11 -0
  11. data/gemfiles/rails4.gemfile +10 -0
  12. data/lib/active_fedora.rb +31 -4
  13. data/lib/active_fedora/association_relation.rb +18 -0
  14. data/lib/active_fedora/associations.rb +38 -171
  15. data/lib/active_fedora/associations/association.rb +163 -0
  16. data/lib/active_fedora/associations/association_scope.rb +39 -0
  17. data/lib/active_fedora/associations/belongs_to_association.rb +47 -25
  18. data/lib/active_fedora/associations/builder/association.rb +55 -0
  19. data/lib/active_fedora/associations/builder/belongs_to.rb +100 -0
  20. data/lib/active_fedora/associations/builder/collection_association.rb +56 -0
  21. data/lib/active_fedora/associations/builder/has_and_belongs_to_many.rb +30 -0
  22. data/lib/active_fedora/associations/builder/has_many.rb +63 -0
  23. data/lib/active_fedora/associations/builder/singular_association.rb +32 -0
  24. data/lib/active_fedora/associations/{association_collection.rb → collection_association.rb} +203 -53
  25. data/lib/active_fedora/associations/collection_proxy.rb +862 -0
  26. data/lib/active_fedora/associations/has_and_belongs_to_many_association.rb +35 -25
  27. data/lib/active_fedora/associations/has_many_association.rb +36 -11
  28. data/lib/active_fedora/associations/singular_association.rb +62 -0
  29. data/lib/active_fedora/attributes.rb +43 -139
  30. data/lib/active_fedora/autosave_association.rb +317 -0
  31. data/lib/active_fedora/base.rb +10 -327
  32. data/lib/active_fedora/callbacks.rb +1 -3
  33. data/lib/active_fedora/content_model.rb +16 -0
  34. data/lib/active_fedora/core.rb +151 -0
  35. data/lib/active_fedora/datastream_attribute.rb +76 -0
  36. data/lib/active_fedora/datastream_hash.rb +8 -13
  37. data/lib/active_fedora/datastreams.rb +39 -26
  38. data/lib/active_fedora/digital_object.rb +2 -2
  39. data/lib/active_fedora/fedora_attributes.rb +45 -0
  40. data/lib/active_fedora/fixture_loader.rb +1 -1
  41. data/lib/active_fedora/indexing.rb +6 -1
  42. data/lib/active_fedora/model.rb +0 -17
  43. data/lib/active_fedora/nested_attributes.rb +2 -2
  44. data/lib/active_fedora/null_relation.rb +7 -0
  45. data/lib/active_fedora/om_datastream.rb +3 -4
  46. data/lib/active_fedora/persistence.rb +41 -29
  47. data/lib/active_fedora/querying.rb +2 -163
  48. data/lib/active_fedora/rdf.rb +1 -0
  49. data/lib/active_fedora/rdf/indexing.rb +67 -0
  50. data/lib/active_fedora/rdf_datastream.rb +2 -50
  51. data/lib/active_fedora/rdf_node.rb +12 -7
  52. data/lib/active_fedora/rdf_node/term_proxy.rb +30 -21
  53. data/lib/active_fedora/rdfxml_rdf_datastream.rb +1 -1
  54. data/lib/active_fedora/reflection.rb +163 -20
  55. data/lib/active_fedora/relation.rb +33 -130
  56. data/lib/active_fedora/relation/calculations.rb +19 -0
  57. data/lib/active_fedora/relation/delegation.rb +22 -0
  58. data/lib/active_fedora/relation/finder_methods.rb +247 -0
  59. data/lib/active_fedora/relation/merger.rb +22 -0
  60. data/lib/active_fedora/relation/query_methods.rb +58 -0
  61. data/lib/active_fedora/relation/spawn_methods.rb +46 -0
  62. data/lib/active_fedora/relationship_graph.rb +0 -2
  63. data/lib/active_fedora/rels_ext_datastream.rb +1 -4
  64. data/lib/active_fedora/rubydora_connection.rb +1 -1
  65. data/lib/active_fedora/scoping.rb +20 -0
  66. data/lib/active_fedora/scoping/default.rb +38 -0
  67. data/lib/active_fedora/scoping/named.rb +32 -0
  68. data/lib/active_fedora/semantic_node.rb +54 -106
  69. data/lib/active_fedora/serialization.rb +19 -0
  70. data/lib/active_fedora/sharding.rb +58 -0
  71. data/lib/active_fedora/solr_digital_object.rb +15 -5
  72. data/lib/active_fedora/solr_instance_loader.rb +1 -1
  73. data/lib/active_fedora/solr_service.rb +1 -1
  74. data/lib/active_fedora/unsaved_digital_object.rb +6 -4
  75. data/lib/active_fedora/version.rb +1 -1
  76. data/lib/tasks/active_fedora.rake +3 -0
  77. data/lib/tasks/active_fedora_dev.rake +6 -5
  78. data/spec/config_helper.rb +14 -14
  79. data/spec/integration/associations_spec.rb +168 -455
  80. data/spec/integration/attributes_spec.rb +12 -11
  81. data/spec/integration/auditable_spec.rb +11 -11
  82. data/spec/integration/autosave_association_spec.rb +25 -0
  83. data/spec/integration/base_spec.rb +163 -163
  84. data/spec/integration/belongs_to_association_spec.rb +166 -0
  85. data/spec/integration/bug_spec.rb +7 -7
  86. data/spec/integration/collection_association_spec.rb +58 -0
  87. data/spec/integration/complex_rdf_datastream_spec.rb +88 -88
  88. data/spec/integration/datastream_collections_spec.rb +69 -69
  89. data/spec/integration/datastream_spec.rb +43 -43
  90. data/spec/integration/datastreams_spec.rb +63 -63
  91. data/spec/integration/delete_all_spec.rb +46 -39
  92. data/spec/integration/fedora_solr_sync_spec.rb +5 -5
  93. data/spec/integration/field_to_solr_name_spec.rb +34 -0
  94. data/spec/integration/full_featured_model_spec.rb +100 -101
  95. data/spec/integration/has_and_belongs_to_many_associations_spec.rb +341 -0
  96. data/spec/integration/has_many_associations_spec.rb +172 -24
  97. data/spec/integration/json_serialization_spec.rb +31 -0
  98. data/spec/integration/load_from_solr_spec.rb +48 -0
  99. data/spec/integration/model_spec.rb +35 -40
  100. data/spec/integration/nested_attribute_spec.rb +42 -43
  101. data/spec/integration/ntriples_datastream_spec.rb +131 -113
  102. data/spec/integration/om_datastream_spec.rb +67 -67
  103. data/spec/integration/persistence_spec.rb +7 -7
  104. data/spec/integration/rdf_nested_attributes_spec.rb +56 -56
  105. data/spec/integration/relation_delegation_spec.rb +26 -25
  106. data/spec/integration/relation_spec.rb +42 -0
  107. data/spec/integration/rels_ext_datastream_spec.rb +20 -20
  108. data/spec/integration/scoped_query_spec.rb +61 -51
  109. data/spec/integration/solr_instance_loader_spec.rb +5 -5
  110. data/spec/integration/solr_service_spec.rb +46 -46
  111. data/spec/samples/hydra-mods_article_datastream.rb +334 -334
  112. data/spec/samples/hydra-rights_metadata_datastream.rb +57 -57
  113. data/spec/samples/marpa-dc_datastream.rb +17 -17
  114. data/spec/samples/models/audio_record.rb +16 -16
  115. data/spec/samples/models/image.rb +2 -2
  116. data/spec/samples/models/mods_article.rb +5 -5
  117. data/spec/samples/models/oral_history.rb +18 -18
  118. data/spec/samples/models/seminar.rb +24 -24
  119. data/spec/samples/models/seminar_audio_file.rb +17 -17
  120. data/spec/samples/oral_history_sample_model.rb +21 -21
  121. data/spec/samples/special_thing.rb +14 -14
  122. data/spec/spec_helper.rb +11 -7
  123. data/spec/support/an_active_model.rb +2 -8
  124. data/spec/support/freeze_mocks.rb +12 -0
  125. data/spec/support/mock_fedora.rb +17 -16
  126. data/spec/unit/active_fedora_spec.rb +58 -60
  127. data/spec/unit/attributes_spec.rb +314 -0
  128. data/spec/unit/base_active_model_spec.rb +28 -27
  129. data/spec/unit/base_cma_spec.rb +5 -5
  130. data/spec/unit/base_datastream_management_spec.rb +27 -27
  131. data/spec/unit/base_extra_spec.rb +76 -48
  132. data/spec/unit/base_spec.rb +277 -348
  133. data/spec/unit/callback_spec.rb +18 -19
  134. data/spec/unit/code_configurator_spec.rb +17 -17
  135. data/spec/unit/config_spec.rb +8 -16
  136. data/spec/unit/content_model_spec.rb +79 -60
  137. data/spec/unit/datastream_collections_spec.rb +229 -229
  138. data/spec/unit/datastream_spec.rb +51 -63
  139. data/spec/unit/datastreams_spec.rb +87 -87
  140. data/spec/unit/file_configurator_spec.rb +217 -217
  141. data/spec/unit/has_and_belongs_to_many_collection_spec.rb +44 -25
  142. data/spec/unit/has_many_collection_spec.rb +26 -8
  143. data/spec/unit/inheritance_spec.rb +13 -12
  144. data/spec/unit/model_spec.rb +39 -45
  145. data/spec/unit/nom_datastream_spec.rb +15 -15
  146. data/spec/unit/ntriples_datastream_spec.rb +123 -118
  147. data/spec/unit/om_datastream_spec.rb +227 -233
  148. data/spec/unit/persistence_spec.rb +34 -15
  149. data/spec/unit/predicates_spec.rb +73 -73
  150. data/spec/unit/property_spec.rb +17 -9
  151. data/spec/unit/qualified_dublin_core_datastream_spec.rb +33 -33
  152. data/spec/unit/query_spec.rb +222 -198
  153. data/spec/unit/rdf_datastream_spec.rb +21 -28
  154. data/spec/unit/rdf_list_nested_attributes_spec.rb +34 -34
  155. data/spec/unit/rdf_list_spec.rb +65 -64
  156. data/spec/unit/rdf_node_spec.rb +7 -7
  157. data/spec/unit/rdf_xml_writer_spec.rb +10 -10
  158. data/spec/unit/rdfxml_rdf_datastream_spec.rb +27 -27
  159. data/spec/unit/relationship_graph_spec.rb +51 -51
  160. data/spec/unit/rels_ext_datastream_spec.rb +68 -74
  161. data/spec/unit/rspec_matchers/belong_to_associated_active_fedora_object_matcher_spec.rb +15 -15
  162. data/spec/unit/rspec_matchers/have_many_associated_active_fedora_objects_matcher_spec.rb +15 -15
  163. data/spec/unit/rspec_matchers/have_predicate_matcher_spec.rb +15 -15
  164. data/spec/unit/rspec_matchers/match_fedora_datastream_matcher_spec.rb +12 -12
  165. data/spec/unit/rubydora_connection_spec.rb +5 -5
  166. data/spec/unit/semantic_node_spec.rb +48 -107
  167. data/spec/unit/serializers_spec.rb +4 -4
  168. data/spec/unit/service_definitions_spec.rb +26 -26
  169. data/spec/unit/simple_datastream_spec.rb +17 -17
  170. data/spec/unit/solr_config_options_spec.rb +29 -28
  171. data/spec/unit/solr_digital_object_spec.rb +17 -25
  172. data/spec/unit/solr_service_spec.rb +95 -82
  173. data/spec/unit/unsaved_digital_object_spec.rb +24 -23
  174. data/spec/unit/validations_spec.rb +21 -21
  175. metadata +110 -159
  176. data/.rspec +0 -1
  177. data/.rubocop.yml +0 -1
  178. data/.rubocop_todo.yml +0 -938
  179. data/CONSOLE_GETTING_STARTED.textile +0 -1
  180. data/NOKOGIRI_DATASTREAMS.textile +0 -1
  181. data/README.textile +0 -116
  182. data/lib/active_fedora/associations/association_proxy.rb +0 -178
  183. data/lib/active_fedora/delegating.rb +0 -72
  184. data/lib/active_fedora/nokogiri_datastream.rb +0 -11
  185. data/spec/integration/delegating_spec.rb +0 -59
  186. data/spec/rails3_test_app/.gitignore +0 -4
  187. data/spec/rails3_test_app/.rspec +0 -1
  188. data/spec/rails3_test_app/Gemfile +0 -40
  189. data/spec/rails3_test_app/Rakefile +0 -7
  190. data/spec/rails3_test_app/app/controllers/application_controller.rb +0 -3
  191. data/spec/rails3_test_app/app/helpers/application_helper.rb +0 -2
  192. data/spec/rails3_test_app/app/views/layouts/application.html.erb +0 -14
  193. data/spec/rails3_test_app/config.ru +0 -4
  194. data/spec/rails3_test_app/config/application.rb +0 -42
  195. data/spec/rails3_test_app/config/boot.rb +0 -6
  196. data/spec/rails3_test_app/config/database.yml +0 -22
  197. data/spec/rails3_test_app/config/environment.rb +0 -5
  198. data/spec/rails3_test_app/config/environments/development.rb +0 -25
  199. data/spec/rails3_test_app/config/environments/production.rb +0 -49
  200. data/spec/rails3_test_app/config/environments/test.rb +0 -35
  201. data/spec/rails3_test_app/config/initializers/backtrace_silencers.rb +0 -7
  202. data/spec/rails3_test_app/config/initializers/inflections.rb +0 -10
  203. data/spec/rails3_test_app/config/initializers/mime_types.rb +0 -5
  204. data/spec/rails3_test_app/config/initializers/secret_token.rb +0 -7
  205. data/spec/rails3_test_app/config/initializers/session_store.rb +0 -8
  206. data/spec/rails3_test_app/config/locales/en.yml +0 -5
  207. data/spec/rails3_test_app/config/routes.rb +0 -58
  208. data/spec/rails3_test_app/db/seeds.rb +0 -7
  209. data/spec/rails3_test_app/run_tests +0 -3
  210. data/spec/rails3_test_app/script/rails +0 -6
  211. data/spec/rails3_test_app/spec/spec_helper.rb +0 -27
  212. data/spec/rails3_test_app/spec/unit/rails_3_init.rb +0 -15
  213. data/spec/unit/association_proxy_spec.rb +0 -12
  214. data/spec/unit/base_delegate_spec.rb +0 -197
  215. data/spec/unit/base_delegate_to_spec.rb +0 -73
@@ -1,56 +1,63 @@
1
1
  require 'spec_helper'
2
2
 
3
- module SpecModelD
4
- class Basic < ActiveFedora::Base
5
- class_attribute :callback_counter
6
- before_destroy :inc_counter
7
-
8
- def inc_counter
9
- self.class.callback_counter += 1
3
+ describe ActiveFedora::Base do
4
+
5
+ before(:all) do
6
+ module SpecModel
7
+ class Basic < ActiveFedora::Base
8
+ class_attribute :callback_counter
9
+
10
+ before_destroy :inc_counter
11
+
12
+ def inc_counter
13
+ self.class.callback_counter += 1
14
+ end
15
+ end
10
16
  end
11
17
  end
12
- end
13
-
14
- describe ActiveFedora::Base do
18
+
19
+ after(:all) do
20
+ Object.send(:remove_const, :SpecModel)
21
+ end
15
22
 
16
- let!(:model1) { SpecModelD::Basic.create! }
17
- let!(:model2) { SpecModelD::Basic.create! }
23
+ let!(:model1) { SpecModel::Basic.create! }
24
+ let!(:model2) { SpecModel::Basic.create! }
18
25
 
19
- before :each do
20
- SpecModelD::Basic.callback_counter = 0
26
+ before do
27
+ SpecModel::Basic.callback_counter = 0
21
28
  end
22
29
 
23
- describe '.destroy_all' do
24
- it 'should remove both and run callbacks' do
25
- model1
26
- model2
27
- expect(SpecModelD::Basic.count).to eq(2)
28
- expect(SpecModelD::Basic.callback_counter).to eq(0)
29
- SpecModelD::Basic.destroy_all
30
- expect(SpecModelD::Basic.count).to eq(0)
31
- expect(SpecModelD::Basic.callback_counter).to eq(2)
30
+
31
+ describe ".destroy_all" do
32
+ it "should remove both and run callbacks" do
33
+ SpecModel::Basic.destroy_all
34
+ SpecModel::Basic.count.should == 0
35
+ SpecModel::Basic.callback_counter.should == 2
32
36
  end
33
37
 
34
- describe 'when a model is missing' do
35
- let(:model3) { SpecModelD::Basic.create! }
36
- after { model3.delete }
37
- it 'should be able to skip a missing model' do
38
- expect(model1).to receive(:destroy).and_call_original
39
- expect(model2).to receive(:destroy).and_call_original
40
- expect(model3).to receive(:destroy).and_raise(ActiveFedora::ObjectNotFoundError)
41
- expect_any_instance_of(ActiveFedora::Relation).to receive(:to_a).and_return([model1, model3, model2])
42
- expect(ActiveFedora::Relation.logger).to receive(:error).with("When trying to destroy #{model3.pid}, encountered an ObjectNotFoundError. Solr may be out of sync with Fedora")
43
- SpecModelD::Basic.destroy_all
44
- expect(SpecModelD::Basic.count).to eq(1)
38
+ describe "when a model is missing" do
39
+ let(:model3) { SpecModel::Basic.create! }
40
+ let!(:pid) { model3.pid }
41
+ before { model3.inner_object.delete }
42
+ after do
43
+ ActiveFedora::SolrService.instance.conn.tap do |conn|
44
+ conn.delete_by_query "id:\"#{pid}\""
45
+ conn.commit
46
+ end
47
+ end
48
+ it "should be able to skip a missing model" do
49
+ ActiveFedora::Relation.logger.should_receive(:error).with("Although #{pid} was found in Solr, it doesn't seem to exist in Fedora. The index is out of synch.")
50
+ SpecModel::Basic.destroy_all
51
+ SpecModel::Basic.count.should == 1
45
52
  end
46
53
  end
47
54
  end
48
55
 
49
- describe '.delete_all' do
50
- it 'should remove both and not run callbacks' do
51
- SpecModelD::Basic.delete_all
52
- expect(SpecModelD::Basic.count).to eq(0)
53
- expect(SpecModelD::Basic.callback_counter).to eq(0)
56
+ describe ".delete_all" do
57
+ it "should remove both and not run callbacks" do
58
+ SpecModel::Basic.delete_all
59
+ SpecModel::Basic.count.should == 0
60
+ SpecModel::Basic.callback_counter.should == 0
54
61
  end
55
62
  end
56
63
  end
@@ -1,14 +1,14 @@
1
1
  require 'spec_helper'
2
2
  require 'timeout'
3
3
 
4
- describe 'fedora_solr_sync_issues' do
4
+ describe "fedora_solr_sync_issues" do
5
5
  before :all do
6
6
  class ParentThing < ActiveFedora::Base
7
- has_many :things, :class_name => 'ChildThing', :property => :is_part_of
7
+ has_many :things, :class_name=>'ChildThing', :property=>:is_part_of
8
8
  end
9
9
 
10
10
  class ChildThing < ActiveFedora::Base
11
- belongs_to :parent, :class_name => 'ParentThing', :property => :is_part_of
11
+ belongs_to :parent, :class_name=>'ParentThing', :property=>:is_part_of
12
12
  end
13
13
  end
14
14
 
@@ -20,9 +20,9 @@ describe 'fedora_solr_sync_issues' do
20
20
  let(:parent) { ParentThing.create }
21
21
  subject { ChildThing.create :parent => parent }
22
22
 
23
- it 'should not go into an infinite loop' do
23
+ it "should not go into an infinite loop" do
24
24
  subject.inner_object.delete
25
25
  parent.reload
26
- expect(parent.things).to eq([])
26
+ parent.things.should == []
27
27
  end
28
28
  end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe "An object with RDF backed attributes" do
4
+
5
+ before do
6
+ class TestOne < ActiveFedora::Base
7
+ class MyMetadata < ActiveFedora::NtriplesRDFDatastream
8
+ map_predicates do |map|
9
+ map.title(in: RDF::DC) do |index|
10
+ index.as :stored_searchable
11
+ end
12
+ map.date_uploaded(to: "dateSubmitted", in: RDF::DC) do |index|
13
+ index.type :date
14
+ index.as :stored_searchable, :sortable
15
+ end
16
+ end
17
+ end
18
+ has_metadata 'descMetadata', type: MyMetadata
19
+ has_attributes :title, :date_uploaded, datastream: 'descMetadata'
20
+ end
21
+ end
22
+
23
+ after do
24
+ Object.send(:remove_const, :TestOne)
25
+ end
26
+
27
+ it "should be able to grab the solr name" do
28
+ expect(TestOne.defined_attributes[:title].primary_solr_name).to eq 'desc_metadata__title_tesim'
29
+ end
30
+
31
+ it "should be able to grab the solr name for a date" do
32
+ expect(TestOne.defined_attributes[:date_uploaded].primary_solr_name).to eq 'desc_metadata__date_uploaded_dtsim'
33
+ end
34
+ end
@@ -9,24 +9,24 @@ describe ActiveFedora::Base do
9
9
  class OralHistory < ActiveFedora::Base
10
10
  # These are all the properties that don't quite fit into Qualified DC
11
11
  # Put them on the object itself (in the properties datastream) for now.
12
- has_metadata :name => 'properties', :type => ActiveFedora::SimpleDatastream do |m|
13
- m.field 'narrator', :string
14
- m.field 'interviewer', :string
15
- m.field 'transcript_editor', :text
16
- m.field 'bio', :string
17
- m.field 'notes', :text
18
- m.field 'hard_copy_availability', :text
19
- m.field 'hard_copy_location', :text
20
- m.field 'other_contributor', :string
21
- m.field 'restrictions', :text
22
- m.field 'series', :string
23
- m.field 'location', :string
12
+ has_metadata :name => "properties", :type => ActiveFedora::SimpleDatastream do |m|
13
+ m.field "narrator", :string
14
+ m.field "interviewer", :string
15
+ m.field "transcript_editor", :text
16
+ m.field "bio", :string
17
+ m.field "notes", :text
18
+ m.field "hard_copy_availability", :text
19
+ m.field "hard_copy_location", :text
20
+ m.field "other_contributor", :string
21
+ m.field "restrictions", :text
22
+ m.field "series", :string
23
+ m.field "location", :string
24
24
  end
25
-
26
-
27
- has_metadata :name => 'mods_article', :type => Hydra::ModsArticleDatastream
28
-
29
- has_metadata :name => 'dublin_core', :type => ActiveFedora::QualifiedDublinCoreDatastream do |m|
25
+
26
+
27
+ has_metadata :name=>"mods_article", :type=> Hydra::ModsArticleDatastream
28
+
29
+ has_metadata :name => "dublin_core", :type => ActiveFedora::QualifiedDublinCoreDatastream do |m|
30
30
  # Default :multiple => true
31
31
  #
32
32
  # on retrieval, these will be pluralized and returned as arrays
@@ -34,30 +34,30 @@ describe ActiveFedora::Base do
34
34
  #
35
35
  # aimint to use method-missing to support calling methods like
36
36
  # my_oral_history.subjects OR my_oral_history.titles OR EVEN my_oral_history.title whenever possible
37
-
37
+
38
38
  # Setting new Types for dates and text content
39
39
  #m.field "creation_date", :date, :xml_node => "date"
40
40
  #m.field "abstract", :text, :xml_node => "abstract"
41
41
  #m.field "rights", :text, :xml_node => "rights"
42
-
42
+
43
43
  # Setting up special named fields
44
- #m.field "subject_heading", :string, :xml_node => "subject", :encoding => "LCSH"
44
+ #m.field "subject_heading", :string, :xml_node => "subject", :encoding => "LCSH"
45
45
  #m.field "spatial_coverage", :string, :xml_node => "spatial", :encoding => "TGN"
46
46
  #m.field "temporal_coverage", :string, :xml_node => "temporal", :encoding => "Period"
47
47
  #m.field "type", :string, :xml_node => "type", :encoding => "DCMITYPE"
48
48
  #m.field "alt_title", :string, :xml_node => "alternative"
49
49
  end
50
-
51
- has_metadata :name => 'significant_passages', :type => ActiveFedora::SimpleDatastream do |m|
52
- m.field 'significant_passage', :text
50
+
51
+ has_metadata :name => "significant_passages", :type => ActiveFedora::SimpleDatastream do |m|
52
+ m.field "significant_passage", :text
53
53
  end
54
-
55
- has_metadata :name => 'sensitive_passages', :type => ActiveFedora::SimpleDatastream do |m|
56
- m.field 'sensitive_passage', :text
54
+
55
+ has_metadata :name => "sensitive_passages", :type => ActiveFedora::SimpleDatastream do |m|
56
+ m.field "sensitive_passage", :text
57
57
  end
58
58
 
59
59
  end
60
- sample_location = 'Boston, Massachusetts'
60
+ sample_location = "Boston, Massachusetts"
61
61
  sample_notes = 'Addelson, Frances. (1973?) "The Induced Abortion," American Journal of Ortho-Psychiatry, Addelson, Frances. "Abortion: Source of Guilt or Growth," National Journal of Gynecology and Obstetrics., Addelson, Frances. "First Zionist Novel," Jewish Frontier.'
62
62
  sample_other_contributor = 'any other contributors, people or corporate names (eg. Temple Israel)'
63
63
  sample_transcript_editor = 'Siegel, Cheryl'
@@ -68,113 +68,112 @@ describe ActiveFedora::Base do
68
68
  sample_bio = <<-END
69
69
  Rochelle Ruthchild interviewed Frances Addleson on October 18, November 14, and December 10, 1997. The interview thoroughly examined the trajectory of Frances\' life from birth until the time of the interview. As a young child, Frances\' father died during the influenza epidemic, and her mother was not equipped to care for her and her siblings. Consequently, they were placed in a Jewish foster home. Although her experience was mostly positive, this experience would leave life-long effects. Frances attended Radcliffe upon the urging of a mentor and later obtained her Master\'s degree in social work from Simmons College in 1954. In the 1940\'s, she returned to work while her children were still young; a rather unusual event for that time period. While working as a social worker at Beth Israel Hospital in the early 1970\'s, she helped counsel countless women who came to the hospital seeking abortions before the procedure was officially legalized during the landmark Roe vs. Wade decision in 1973. Frances would later write two articles that were published in medical journals about her experience during this time. Although not a very religious person, Frances felt connected to the Jewish notion of social justice and remained very active until an accident in the late 1990\'s.
70
70
  END
71
- sample_interviewer = 'Ruthchild, & Rochelle'
72
-
73
- @properties_sample_values2 = Hash[:narrator => 'Narrator1 & Narrator2', :interviewer => 'Interviewer', :transcript_editor => 'Transcript Editor', :bio => 'Biographic info',
74
- :notes => "My Note\\\'s a good one", :hard_copy_availability => 'Yes', :hard_copy_location => 'Archives', :other_contributor => 'Sally Ride',
75
- :restrictions => 'None', :series => 'My Series', :location => 'location']
76
-
77
- @properties_sample_values = Hash[:narrator => sample_narrator, :interviewer => sample_interviewer, :transcript_editor => sample_transcript_editor, :bio => sample_bio,
78
- :notes => sample_notes, :hard_copy_availability => sample_hard_copy_availability, :hard_copy_location => 'Archives', :other_contributor => sample_other_contributor,
79
- :restrictions => 'None', :series => 'My Series', :location => sample_location]
80
-
81
- @dublin_core_sample_values = Hash[:creator => 'Matt && McClain', :publisher => "Jewish Womens's Archive", :description => 'description', :identifier => 'jwa:sample_pid',
82
- :title => 'title',
83
- #:alt_title => "alt_title", :subject => "subject",
84
- #:subject_heading => "subject heading",
85
- #:creation_date => "2008-07-02T05:09:42.015Z",
86
- :language => 'language',
87
- #:spatial_coverage => "spatial coverage",
88
- #:temporal_coverage => "temporal coverage",
71
+ sample_interviewer = "Ruthchild, & Rochelle"
72
+
73
+ @properties_sample_values2 = Hash[:narrator => "Narrator1 & Narrator2", :interviewer => "Interviewer", :transcript_editor => "Transcript Editor", :bio => "Biographic info",
74
+ :notes => "My Note\\\'s a good one", :hard_copy_availability => "Yes", :hard_copy_location => "Archives", :other_contributor => "Sally Ride",
75
+ :restrictions => "None", :series => "My Series", :location => "location"]
76
+
77
+ @properties_sample_values = Hash[:narrator => sample_narrator, :interviewer => sample_interviewer, :transcript_editor => sample_transcript_editor, :bio => sample_bio,
78
+ :notes => sample_notes, :hard_copy_availability => sample_hard_copy_availability, :hard_copy_location => "Archives", :other_contributor => sample_other_contributor,
79
+ :restrictions => "None", :series => "My Series", :location => sample_location]
80
+
81
+ @dublin_core_sample_values = Hash[:creator => 'Matt && McClain', :publisher => "Jewish Womens's Archive", :description => "description", :identifier => "jwa:sample_pid",
82
+ :title => "title",
83
+ #:alt_title => "alt_title", :subject => "subject",
84
+ #:subject_heading => "subject heading",
85
+ #:creation_date => "2008-07-02T05:09:42.015Z",
86
+ :language => "language",
87
+ #:spatial_coverage => "spatial coverage",
88
+ #:temporal_coverage => "temporal coverage",
89
89
  #:abstract => "abstract",
90
- :rights => 'rights', :type => 'type',
91
- #:extent => "extent",
92
- :format => 'format', :medium => 'medium']
90
+ :rights => "rights", :type => "type",
91
+ #:extent => "extent",
92
+ :format => "format", :medium => "medium"]
93
93
  @signigicant_passages_sample_values = {}
94
- @sensitive_passages_sample_values = {}
95
- @sample_xml = '<xml><fields><system_create_date>REMOVED</system_create_date><system_modified_date>REMOVED</system_modified_date><active_fedora_model_s>OralHistory</active_fedora_model_s><id>changeme:14527</id><subject_heading>subject heading</subject_heading><type>type</type><rights>rights</rights><publisher>publisher</publisher><creation_date>creation date</creation_date><identifier>jwa:sample_pid</identifier><format>format</format><extent>extent</extent><language>language</language><description>description</description><title>title</title><medium>medium</medium><spatial_coverage>spatial coverage</spatial_coverage><alt_title>alt_title</alt_title><temporal_coverage>temporal coverage</temporal_coverage><subject>subject</subject><creator>creator</creator><abstract>abstract</abstract><other_contributor>Sally Ride</other_contributor><transcript_editor>Transcript Editor</transcript_editor><restrictions>None</restrictions><bio>Biographic info</bio><series>My Series</series><notes>My Note</notes><location>location</location><hard_copy_availability>Yes</hard_copy_availability><narrator>Narrator</narrator><hard_copy_location>Archives</hard_copy_location><interviewer>Interviewer</interviewer></fields><content/></xml>'
96
-
97
- end
98
-
94
+ @sensitive_passages_sample_values = {}
95
+ @sample_xml = "<xml><fields><system_create_date>REMOVED</system_create_date><system_modified_date>REMOVED</system_modified_date><active_fedora_model_s>OralHistory</active_fedora_model_s><id>changeme:14527</id><subject_heading>subject heading</subject_heading><type>type</type><rights>rights</rights><publisher>publisher</publisher><creation_date>creation date</creation_date><identifier>jwa:sample_pid</identifier><format>format</format><extent>extent</extent><language>language</language><description>description</description><title>title</title><medium>medium</medium><spatial_coverage>spatial coverage</spatial_coverage><alt_title>alt_title</alt_title><temporal_coverage>temporal coverage</temporal_coverage><subject>subject</subject><creator>creator</creator><abstract>abstract</abstract><other_contributor>Sally Ride</other_contributor><transcript_editor>Transcript Editor</transcript_editor><restrictions>None</restrictions><bio>Biographic info</bio><series>My Series</series><notes>My Note</notes><location>location</location><hard_copy_availability>Yes</hard_copy_availability><narrator>Narrator</narrator><hard_copy_location>Archives</hard_copy_location><interviewer>Interviewer</interviewer></fields><content/></xml>"
96
+
97
+ end
98
+
99
99
  before(:each) do
100
100
  @test_history = OralHistory.new
101
101
  end
102
-
102
+
103
103
  after(:each) do
104
104
  end
105
-
105
+
106
106
  after(:all) do
107
107
  Object.send(:remove_const, :OralHistory)
108
108
  end
109
-
110
- it 'should be an instance of ActiveFedora::Base' do
111
- expect(@test_history).to be_kind_of(ActiveFedora::Base)
112
- end
113
-
114
-
115
- it 'should create proxies to all the datastreams' do
116
- properties_ds = @test_history.datastreams['properties']
117
- dublin_core_ds = @test_history.datastreams['dublin_core']
118
- expect(@test_history).not_to respond_to(:properties)
119
- expect(@test_history.properties).to be properties_ds
120
- expect(@test_history).to respond_to(:properties)
121
- expect(OralHistory.new).to respond_to(:properties)
109
+
110
+ it "should be an instance of ActiveFedora::Base" do
111
+ @test_history.should be_kind_of(ActiveFedora::Base)
122
112
  end
123
-
124
-
125
- it 'should push all of the metadata fields into solr' do
113
+
114
+
115
+ it "should create proxies to all the datastreams" do
116
+ properties_ds = @test_history.datastreams["properties"]
117
+ dublin_core_ds = @test_history.datastreams["dublin_core"]
118
+ @test_history.properties.should be properties_ds
119
+ @test_history.should respond_to(:properties)
120
+ OralHistory.new.should respond_to(:properties)
121
+ end
122
+
123
+
124
+ it "should push all of the metadata fields into solr" do
126
125
  # TODO: test must test values using solr symbol names (ie. _field, _text and _date)
127
- properties_ds = @test_history.datastreams['properties']
128
- dublin_core_ds = @test_history.datastreams['dublin_core']
129
-
126
+ properties_ds = @test_history.datastreams["properties"]
127
+ dublin_core_ds = @test_history.datastreams["dublin_core"]
128
+
130
129
  @properties_sample_values.each_pair do |field, value|
131
130
  next if field == :hard_copy_availability #FIXME HYDRA-824
132
131
  properties_ds.send("#{field.to_s}=", [value])
133
132
  end
134
-
133
+
135
134
  @dublin_core_sample_values.each_pair do |field, value|
136
135
  next if [:format, :type].include?(field) #format and type are methods declared on Object
137
136
  dublin_core_ds.send("#{field.to_s}=", [value])
138
137
  end
139
-
138
+
140
139
  @test_history.save
141
-
142
- @solr_result = OralHistory.find_with_conditions(:id => @test_history.pid)[0]
140
+
141
+ @solr_result = OralHistory.find_with_conditions(:id=>@test_history.pid)[0]
143
142
  @properties_sample_values.each_pair do |field, value|
144
143
  next if field == :hard_copy_availability #FIXME HYDRA-824
145
- next if field == :location #FIXME HYDRA-825
146
- expect(@solr_result[ActiveFedora::SolrService.solr_name(field, type: :string)] || @solr_result[ActiveFedora::SolrService.solr_name(field, type: :date)]).to eq([::Solrizer::Extractor.format_node_value(value)])
144
+ next if field == :location #FIXME HYDRA-825
145
+ (@solr_result[ActiveFedora::SolrService.solr_name(field, type: :string)] || @solr_result[ActiveFedora::SolrService.solr_name(field, type: :date)]).should == [::Solrizer::Extractor.format_node_value(value)]
147
146
  end
148
-
147
+
149
148
  @dublin_core_sample_values.each_pair do |field, value|
150
149
  next if [:format, :type].include?(field) #format and type are methods declared on Object
151
- expect(dublin_core_ds.send("#{field.to_s}")).to eq([value])
152
- end
150
+ dublin_core_ds.send("#{field.to_s}").should == [value]
151
+ end
153
152
  end
154
-
155
- it 'should have Qualified Dublin core, with custom accessors' do
156
-
157
- dublin_core_ds = @test_history.datastreams['dublin_core']
158
-
159
- dublin_core_ds.subject = 'My Subject Heading'
153
+
154
+ it "should have Qualified Dublin core, with custom accessors" do
155
+
156
+ dublin_core_ds = @test_history.datastreams["dublin_core"]
157
+
158
+ dublin_core_ds.subject = "My Subject Heading"
160
159
  dc_xml = REXML::Document.new(dublin_core_ds.to_xml)
161
-
162
- expect(dc_xml.root.elements['dcterms:subject'].text).to eq('My Subject Heading')
163
-
160
+
161
+ dc_xml.root.elements["dcterms:subject"].text.should == "My Subject Heading"
162
+
164
163
  end
165
-
166
- it 'should support #find_with_conditions' do
164
+
165
+ it "should support #find_with_conditions" do
167
166
  solr_result = OralHistory.find_with_conditions({})
168
- expect(solr_result).not_to be_nil
167
+ solr_result.should_not be_nil
169
168
  end
170
-
169
+
171
170
  describe '#new' do
172
- it 'should support custom pids' do
173
- oh = OralHistory.new(:pid => 'uuid:blah-blah-blah')
174
- expect(oh.pid).to eq('uuid:blah-blah-blah')
171
+ it "should support custom pids" do
172
+ oh = OralHistory.new(:pid=>"uuid:blah-blah-blah")
173
+ oh.pid.should == "uuid:blah-blah-blah"
175
174
  end
176
175
  end
176
+
177
177
 
178
-
179
-
178
+
180
179
  end
@@ -0,0 +1,341 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveFedora::Base do
4
+ describe "with inverse" do
5
+ before do
6
+ class Book < ActiveFedora::Base
7
+ has_and_belongs_to_many :topics, :property=>:has_topic, :inverse_of=>:is_topic_of
8
+ has_and_belongs_to_many :collections, :property=>:is_member_of_collection
9
+ end
10
+
11
+ class SpecialInheritedBook < Book
12
+ end
13
+
14
+
15
+ class Collection < ActiveFedora::Base
16
+ end
17
+
18
+ class Topic < ActiveFedora::Base
19
+ has_and_belongs_to_many :books, :property=>:is_topic_of
20
+ end
21
+ end
22
+
23
+ after do
24
+ Object.send(:remove_const, :SpecialInheritedBook)
25
+ Object.send(:remove_const, :Book)
26
+ Object.send(:remove_const, :Collection)
27
+ Object.send(:remove_const, :Topic)
28
+ end
29
+
30
+ describe "an unsaved instance" do
31
+ before do
32
+ @topic1 = Topic.create
33
+ @topic2 = Topic.create
34
+ @book = Book.create
35
+ @special_book = SpecialInheritedBook.create #TODO this isnt' needed in every test.
36
+ end
37
+ it "habtm should set and remove relationships bidirectionally" do
38
+ @book.topics << @topic1
39
+ @book.topics.should == [@topic1]
40
+ @topic1.books.should == [@book]
41
+ @topic1.reload.books.should == [@book]
42
+
43
+ @book.topics.delete(@topic1)
44
+ #@topic1.books.delete(@book)
45
+ @book.topics.should == []
46
+ @topic1.books.should == []
47
+ end
48
+ it "Should allow for more than 10 items" do
49
+
50
+ (0..11).each do
51
+ @book.topics << Topic.create
52
+ end
53
+ @book.save
54
+ @book.topics.count.should == 12
55
+ book2 = Book.find(@book.pid)
56
+ book2.topics.count.should == 12
57
+ end
58
+
59
+ it "Should find inherited objects along with base objects" do
60
+ @book.topics << @topic1
61
+ @special_book.topics << @topic1
62
+ @topic1.books.should == [@book, @special_book]
63
+ @topic1.reload.books.should == [@book, @special_book]
64
+ end
65
+
66
+ it "Should cast found books to the correct cmodel" do
67
+ @topic1.books[0].class == Book
68
+ @topic1.books[1].class == SpecialInheritedBook
69
+ end
70
+
71
+ after do
72
+ @topic1.delete
73
+ @topic2.delete
74
+ @book.delete
75
+ @special_book.delete
76
+ end
77
+ end
78
+ describe "a saved instance" do
79
+ before do
80
+ @book = Book.create
81
+ @topic1 = Topic.create
82
+ @topic2 = Topic.create
83
+ end
84
+ it "should set relationships bidirectionally" do
85
+ @book.topics << @topic1
86
+ @book.topics.should == [@topic1]
87
+ @book.relationships(:has_topic).should == [@topic1.internal_uri]
88
+ @topic1.relationships(:has_topic).should == []
89
+ @topic1.relationships(:is_topic_of).should == [@book.internal_uri]
90
+ Topic.find(@topic1.pid).books.should == [@book] #Can't have saved it because @book isn't saved yet.
91
+ end
92
+ it "should save new child objects" do
93
+ @book.topics << Topic.new
94
+ @book.topics.first.pid.should_not be_nil
95
+ end
96
+ it "should clear out the old associtions" do
97
+ @book.topics = [@topic1]
98
+ @book.topics = [@topic2]
99
+ @book.topic_ids.should == [@topic2.pid]
100
+ end
101
+ after do
102
+ @book.delete
103
+ @topic1.delete
104
+ @topic2.delete
105
+ end
106
+ end
107
+ end
108
+
109
+ describe "when inverse is not specified" do
110
+ before do
111
+ class Book < ActiveFedora::Base
112
+ has_and_belongs_to_many :collections, :property=>:is_member_of_collection
113
+ end
114
+
115
+ class Collection < ActiveFedora::Base
116
+ end
117
+ end
118
+
119
+ after do
120
+ Object.send(:remove_const, :Book)
121
+ Object.send(:remove_const, :Collection)
122
+ end
123
+
124
+ let (:book) { Book.create }
125
+ let (:collection) { Collection.create }
126
+ before do
127
+ book.collections << collection
128
+ book.save!
129
+ end
130
+ after do
131
+ collection.delete
132
+ book.delete
133
+ end
134
+ it "should have a collection" do
135
+ book.relationships(:is_member_of_collection).should == [collection.internal_uri]
136
+ book.collections.should == [collection]
137
+ end
138
+ it "habtm should not set foreign relationships if :inverse_of is not specified" do
139
+ collection.relationships(:is_member_of_collection).should == []
140
+ end
141
+ it "should load the collections" do
142
+ reloaded = Book.find(book.pid)
143
+ reloaded.collections.should == [collection]
144
+ end
145
+ end
146
+
147
+
148
+ describe "when destroying the association" do
149
+ describe "without callbacks" do
150
+ before do
151
+ class Book < ActiveFedora::Base
152
+ has_and_belongs_to_many :collections, property: :is_member_of_collection
153
+ end
154
+
155
+ class Collection < ActiveFedora::Base
156
+ end
157
+ end
158
+
159
+ after do
160
+ Object.send(:remove_const, :Book)
161
+ Object.send(:remove_const, :Collection)
162
+ end
163
+
164
+ let (:book) { Book.create }
165
+ let (:collection1) { Collection.create }
166
+ let (:collection2) { Collection.create }
167
+ before do
168
+ book.collections << collection1 << collection2
169
+ book.save!
170
+ end
171
+ after do
172
+ collection1.delete
173
+ collection2.delete
174
+ book.delete
175
+ end
176
+
177
+ it "delete should cause the entries to be removed from RELS-EXT, but not destroy the original record" do
178
+ book.collections.should == [collection1, collection2]
179
+ book.collections.delete(collection1)
180
+ book.collections.should == [collection2]
181
+ book.save!
182
+ book.reload
183
+ book.collections.should == [collection2]
184
+ expect {Collection.find(collection1.pid)}.to_not be_nil
185
+ end
186
+
187
+ it "destroy should cause the entries to be removed from RELS-EXT, but not destroy the original record" do
188
+ book.collections.should == [collection1, collection2]
189
+ book.collections.destroy(collection1)
190
+ book.collections.should == [collection2]
191
+ book.save!
192
+ book.reload
193
+ book.collections.should == [collection2]
194
+ expect {Collection.find(collection1.pid)}.to_not be_nil
195
+ end
196
+ end
197
+
198
+ describe "with remove callbacks" do
199
+ before do
200
+ class Book < ActiveFedora::Base
201
+ has_and_belongs_to_many :collections,
202
+ property: :is_member_of_collection,
203
+ before_remove: :foo, after_remove: :bar
204
+ end
205
+
206
+ class Collection < ActiveFedora::Base
207
+ end
208
+ end
209
+
210
+ after do
211
+ Object.send(:remove_const, :Book)
212
+ Object.send(:remove_const, :Collection)
213
+ end
214
+
215
+ let (:book) { Book.create }
216
+ let (:collection) { Collection.create }
217
+ before do
218
+ book.collections << collection
219
+ book.save!
220
+ end
221
+ after do
222
+ collection.delete
223
+ book.delete
224
+ end
225
+
226
+ it "destroy should cause the before_remove and after_remove callback to be triggered" do
227
+ book.should_receive(:foo).with(collection)
228
+ book.should_receive(:bar).with(collection)
229
+ book.collections.destroy(collection)
230
+ end
231
+
232
+ it "delete should cause the before_remove and after_remove callback to be triggered" do
233
+ book.should_receive(:foo).with(collection)
234
+ book.should_receive(:bar).with(collection)
235
+ book.collections.delete(collection)
236
+ end
237
+
238
+ it "should not remove if an exception is thrown in before_remove" do
239
+ book.should_receive(:foo).with(collection).and_raise
240
+ book.should_not_receive(:bar)
241
+ begin
242
+ book.collections.delete(collection)
243
+ rescue RuntimeError
244
+ end
245
+ book.collections.should == [collection]
246
+ end
247
+ end
248
+
249
+ describe "with add callbacks" do
250
+ before do
251
+ class Book < ActiveFedora::Base
252
+ has_and_belongs_to_many :collections,
253
+ property: :is_member_of_collection,
254
+ before_add: :foo, after_add: :bar
255
+ end
256
+
257
+ class Collection < ActiveFedora::Base
258
+ end
259
+ end
260
+
261
+ after do
262
+ Object.send(:remove_const, :Book)
263
+ Object.send(:remove_const, :Collection)
264
+ end
265
+
266
+ let (:book) { Book.create }
267
+ let (:collection) { Collection.create }
268
+ after do
269
+ collection.delete
270
+ book.delete
271
+ end
272
+
273
+ it "shift should cause the before_add and after_add callback to be triggered" do
274
+ book.should_receive(:foo).with(collection)
275
+ book.should_receive(:bar).with(collection)
276
+ book.collections << collection
277
+ end
278
+
279
+ it "assignment should cause the before_add and after_add callback to be triggered" do
280
+ book.should_receive(:foo).with(collection)
281
+ book.should_receive(:bar).with(collection)
282
+ book.collections = [collection]
283
+ end
284
+
285
+ it "should not add if an exception is thrown in before_add" do
286
+ book.should_receive(:foo).with(collection).and_raise
287
+ book.should_not_receive(:bar)
288
+ begin
289
+ book.collections << collection
290
+ rescue RuntimeError
291
+ end
292
+ book.collections.should == []
293
+ end
294
+ end
295
+
296
+ end
297
+
298
+ end
299
+
300
+ describe "Autosave" do
301
+ before do
302
+ class Item < ActiveFedora::Base
303
+ has_many :components
304
+ has_metadata "foo", type: ActiveFedora::SimpleDatastream do |m|
305
+ m.field "title", :string
306
+ end
307
+ has_attributes :title, datastream: 'foo'
308
+ end
309
+ class Component < ActiveFedora::Base
310
+ has_and_belongs_to_many :items, :property => :is_part_of
311
+ has_metadata "foo", type: ActiveFedora::SimpleDatastream do |m|
312
+ m.field "description", :string
313
+ end
314
+ has_attributes :description, datastream: 'foo'
315
+ end
316
+ end
317
+
318
+ after do
319
+ Object.send(:remove_const, :Item)
320
+ Object.send(:remove_const, :Component)
321
+ end
322
+
323
+ describe "From the has_and_belongs_to_many side" do
324
+ let(:component) { Component.create(items: [Item.new(title: 'my title')]) }
325
+
326
+ it "should save dependent records" do
327
+ component.reload
328
+ component.items.first.title.should == 'my title'
329
+ end
330
+ end
331
+ describe "From the has_many side" do
332
+ let(:item) { Item.create(components: [Component.new(description: 'my description')]) }
333
+
334
+ it "should save dependent records" do
335
+ item.reload
336
+ item.components.first.description.should == 'my description'
337
+ end
338
+ end
339
+
340
+ end
341
+