active-fedora 4.5.3 → 4.6.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -20,6 +20,7 @@ Gem::Specification.new do |s|
20
20
  s.add_dependency('solrizer', '~>1.2.0')
21
21
  s.add_dependency("activeresource", '>= 3.0.0')
22
22
  s.add_dependency("activesupport", '>= 3.0.0')
23
+ s.add_dependency("builder", '~> 3.0.0')
23
24
  s.add_dependency("mediashelf-loggable")
24
25
  s.add_dependency("equivalent-xml")
25
26
  s.add_dependency("rubydora", '~>0.5.13')
@@ -22,6 +22,7 @@ module ActiveFedora #:nodoc:
22
22
 
23
23
  eager_autoload do
24
24
  autoload :Associations
25
+ autoload :Attributes
25
26
  autoload :Base
26
27
  autoload :ContentModel
27
28
  autoload :Callbacks
@@ -35,7 +35,7 @@ module ActiveFedora
35
35
  # ActiveFedora::Associations::HasManyAssociation.
36
36
 
37
37
  class AssociationProxy
38
- delegate :to_param, :to=>:target
38
+ #delegate :to_param, :to=>:target
39
39
  instance_methods.each { |m| undef_method m unless m.to_s =~ /^(?:nil\?|send|object_id|to_a)$|^__|^respond_to|proxy_/ }
40
40
 
41
41
  def initialize(owner, reflection)
@@ -0,0 +1,82 @@
1
+ module ActiveFedora
2
+ module Attributes
3
+ extend ActiveSupport::Concern
4
+ extend ActiveSupport::Autoload
5
+ autoload :Serializers
6
+
7
+ included do
8
+ include Serializers
9
+ end
10
+
11
+ def attributes=(properties)
12
+ properties.each do |k, v|
13
+ respond_to?(:"#{k}=") ? send(:"#{k}=", v) : raise(UnknownAttributeError, "unknown attribute: #{k}")
14
+ end
15
+ end
16
+
17
+
18
+ # A convenience method for updating indexed attributes. The passed in hash
19
+ # must look like this :
20
+ # {{:name=>{"0"=>"a","1"=>"b"}}
21
+ #
22
+ # This will result in any datastream field of name :name having the value [a,b]
23
+ #
24
+ # An index of -1 will insert a new value. any existing value at the relevant index
25
+ # will be overwritten.
26
+ #
27
+ # As in update_attributes, this overwrites _all_ available fields by default.
28
+ #
29
+ # If you want to specify which datastream(s) to update,
30
+ # use the :datastreams argument like so:
31
+ # m.update_attributes({"fubar"=>{"-1"=>"mork", "0"=>"york", "1"=>"mangle"}}, :datastreams=>"my_ds")
32
+ # or
33
+ # m.update_attributes({"fubar"=>{"-1"=>"mork", "0"=>"york", "1"=>"mangle"}}, :datastreams=>["my_ds", "my_other_ds"])
34
+ #
35
+ def update_indexed_attributes(params={}, opts={})
36
+ if ds = opts[:datastreams]
37
+ ds_array = []
38
+ ds = [ds] unless ds.respond_to? :each
39
+ ds.each do |dsname|
40
+ ds_array << datastreams[dsname]
41
+ end
42
+ else
43
+ ds_array = metadata_streams
44
+ end
45
+ result = {}
46
+ ds_array.each do |d|
47
+ result[d.dsid] = d.update_indexed_attributes(params,opts)
48
+ end
49
+ return result
50
+ end
51
+
52
+ # Updates the attributes for each datastream named in the params Hash
53
+ # @param [Hash] params A Hash whose keys correspond to datastream ids and whose values are appropriate Hashes to submit to update_indexed_attributes on that datastream
54
+ # @param [Hash] opts (currently ignored.)
55
+ # @example Update the descMetadata and properties datastreams with new values
56
+ # article = HydrangeaArticle.new
57
+ # ds_values_hash = {
58
+ # "descMetadata"=>{ [{:person=>0}, :role]=>{"0"=>"role1", "1"=>"role2", "2"=>"role3"} },
59
+ # "properties"=>{ "notes"=>"foo" }
60
+ # }
61
+ # article.update_datastream_attributes( ds_values_hash )
62
+ def update_datastream_attributes(params={}, opts={})
63
+ result = params.dup
64
+ params.each_pair do |dsid, ds_params|
65
+ if datastreams.include?(dsid)
66
+ result[dsid] = datastreams[dsid].update_indexed_attributes(ds_params)
67
+ else
68
+ result.delete(dsid)
69
+ end
70
+ end
71
+ return result
72
+ end
73
+
74
+ def get_values_from_datastream(dsid,field_key,default=[])
75
+ if datastreams.include?(dsid)
76
+ return datastreams[dsid].get_values(field_key,default)
77
+ else
78
+ return nil
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,74 @@
1
+ module ActiveFedora
2
+ module Attributes
3
+ module Serializers
4
+ extend ActiveSupport::Concern
5
+
6
+ ## This allows you to use date_select helpers in rails views
7
+ # @param [Hash] parms parameters hash
8
+ # @return [Hash] a parameters list with the date select parameters replaced with dates
9
+ def deserialize_dates_from_form(params)
10
+ dates = {}
11
+ params.each do |key, value|
12
+ if data = key.to_s.match(/^(.+)\((\d)i\)$/)
13
+ dates[data[1]] ||= {}
14
+ dates[data[1]][data[2]] = value
15
+ params.delete(key)
16
+ end
17
+ end
18
+ dates.each do |key, value|
19
+ params[key] = [value['1'], value['2'], value['3']].join('-')
20
+ end
21
+ params
22
+ end
23
+
24
+ # set a hash of attributes on the object
25
+ # @param [Hash] params the properties to set on the object
26
+ def attributes=(params)
27
+ super(deserialize_dates_from_form(params))
28
+ end
29
+
30
+ module ClassMethods
31
+ # @param [String] value a string to be cast to integer
32
+ # @param [Hash] options
33
+ # @option options [Integer] :default a value to return if the passed value argument is blank
34
+ # @return [Integer]
35
+ def coerce_to_integer(value, options={})
36
+ if value.blank?
37
+ options[:default] || nil
38
+ else
39
+ value.to_i
40
+ end
41
+ end
42
+
43
+ # @param [String] value a string to be cast to boolean
44
+ # @param [Hash] options
45
+ # @option options [Boolean] :default a value to return if the passed value argument is blank
46
+ # @return [Boolean] true if value == "true" or default if value is blank
47
+ def coerce_to_boolean(value, options={})
48
+ if value.blank?
49
+ options[:default] || nil
50
+ else
51
+ value=="true"
52
+ end
53
+ end
54
+
55
+ # @param [String] value a string to be cast to boolean
56
+ # @param [Hash] options
57
+ # @option options [Boolean] :default a value to return if the passed value argument is blank
58
+ # @return [Boolean] true if value == "true" or default if value is blank
59
+ def coerce_to_date(v, options={})
60
+ if v.blank? && options[:default]
61
+ options[:default] == :today ? Date.today : options[:default]
62
+ else
63
+ begin
64
+ Date.parse(v)
65
+ rescue TypeError, ArgumentError
66
+ nil
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ end
73
+ end
74
+ end
@@ -61,11 +61,6 @@ module ActiveFedora
61
61
  !new_object?
62
62
  end
63
63
 
64
- def attributes=(properties)
65
- properties.each do |k, v|
66
- respond_to?(:"#{k}=") ? send(:"#{k}=", v) : raise(UnknownAttributeError, "unknown attribute: #{k}")
67
- end
68
- end
69
64
 
70
65
  # Constructor. You may supply a custom +:pid+, or we call the Fedora Rest API for the
71
66
  # next available Fedora pid, and mark as new object.
@@ -207,6 +202,10 @@ module ActiveFedora
207
202
  self.pid
208
203
  end
209
204
 
205
+ def to_param
206
+ persisted? ? to_key.join('-') : nil
207
+ end
208
+
210
209
  def to_key
211
210
  persisted? ? [pid] : nil
212
211
  end
@@ -420,70 +419,6 @@ module ActiveFedora
420
419
  obj.inner_object.freeze
421
420
  obj
422
421
  end
423
-
424
- # A convenience method for updating indexed attributes. The passed in hash
425
- # must look like this :
426
- # {{:name=>{"0"=>"a","1"=>"b"}}
427
- #
428
- # This will result in any datastream field of name :name having the value [a,b]
429
- #
430
- # An index of -1 will insert a new value. any existing value at the relevant index
431
- # will be overwritten.
432
- #
433
- # As in update_attributes, this overwrites _all_ available fields by default.
434
- #
435
- # If you want to specify which datastream(s) to update,
436
- # use the :datastreams argument like so:
437
- # m.update_attributes({"fubar"=>{"-1"=>"mork", "0"=>"york", "1"=>"mangle"}}, :datastreams=>"my_ds")
438
- # or
439
- # m.update_attributes({"fubar"=>{"-1"=>"mork", "0"=>"york", "1"=>"mangle"}}, :datastreams=>["my_ds", "my_other_ds"])
440
- #
441
- def update_indexed_attributes(params={}, opts={})
442
- if ds = opts[:datastreams]
443
- ds_array = []
444
- ds = [ds] unless ds.respond_to? :each
445
- ds.each do |dsname|
446
- ds_array << datastreams[dsname]
447
- end
448
- else
449
- ds_array = metadata_streams
450
- end
451
- result = {}
452
- ds_array.each do |d|
453
- result[d.dsid] = d.update_indexed_attributes(params,opts)
454
- end
455
- return result
456
- end
457
-
458
- # Updates the attributes for each datastream named in the params Hash
459
- # @param [Hash] params A Hash whose keys correspond to datastream ids and whose values are appropriate Hashes to submit to update_indexed_attributes on that datastream
460
- # @param [Hash] opts (currently ignored.)
461
- # @example Update the descMetadata and properties datastreams with new values
462
- # article = HydrangeaArticle.new
463
- # ds_values_hash = {
464
- # "descMetadata"=>{ [{:person=>0}, :role]=>{"0"=>"role1", "1"=>"role2", "2"=>"role3"} },
465
- # "properties"=>{ "notes"=>"foo" }
466
- # }
467
- # article.update_datastream_attributes( ds_values_hash )
468
- def update_datastream_attributes(params={}, opts={})
469
- result = params.dup
470
- params.each_pair do |dsid, ds_params|
471
- if datastreams.include?(dsid)
472
- result[dsid] = datastreams[dsid].update_indexed_attributes(ds_params)
473
- else
474
- result.delete(dsid)
475
- end
476
- end
477
- return result
478
- end
479
-
480
- def get_values_from_datastream(dsid,field_key,default=[])
481
- if datastreams.include?(dsid)
482
- return datastreams[dsid].get_values(field_key,default)
483
- else
484
- return nil
485
- end
486
- end
487
422
 
488
423
  def self.pids_from_uris(uris)
489
424
  if uris.class == String
@@ -500,6 +435,7 @@ module ActiveFedora
500
435
  end
501
436
 
502
437
  Base.class_eval do
438
+ include Attributes
503
439
  include ActiveFedora::Persistence
504
440
  include Model
505
441
  include Solrizer::FieldNameMapper
@@ -6,6 +6,11 @@ module ActiveFedora
6
6
  # much in the way ActiveRecord does.
7
7
  module Model
8
8
  extend ActiveSupport::Concern
9
+
10
+ included do
11
+ class_attribute :solr_query_handler
12
+ self.solr_query_handler = 'standard'
13
+ end
9
14
 
10
15
  # Takes a Fedora URI for a cModel and returns classname, namespace
11
16
  def self.classname_from_uri(uri)
@@ -131,7 +136,7 @@ module ActiveFedora
131
136
 
132
137
  def find_in_batches conditions, opts={}
133
138
  opts[:q] = create_query(conditions)
134
- opts[:qt] = 'standard'
139
+ opts[:qt] = solr_query_handler
135
140
  #set default sort to created date ascending
136
141
  unless opts.include?(:sort)
137
142
  opts[:sort]=[ActiveFedora::SolrService.solr_name(:system_create,:date)+' asc']
@@ -180,9 +185,9 @@ module ActiveFedora
180
185
  # Get a count of the number of objects from solr
181
186
  # Takes :conditions as an argument
182
187
  def count(args = {})
183
- q = search_model_clause
184
- q << " AND #{args[:conditions]}" if args[:conditions]
185
- SolrService.query(q, :raw=>true, :rows=>0)['response']['numFound']
188
+ q = search_model_clause ? [search_model_clause] : []
189
+ q << "#{args[:conditions]}" if args[:conditions]
190
+ SolrService.query(q.join(' AND '), :raw=>true, :rows=>0)['response']['numFound']
186
191
  end
187
192
 
188
193
  #@deprecated
@@ -218,8 +223,8 @@ module ActiveFedora
218
223
  # Find all ActiveFedora objects for this model that match arguments
219
224
  # passed in by querying Solr. Like find_by_solr this returns a solr result.
220
225
  #
221
- # query_fields a hash of object field names and values to filter on (query_fields must be the solr_field_name for non-MetadataDatastream derived datastreams)
222
- # opts specifies options for the solr query
226
+ # @param query_fields [Hash] field names and values to filter on (query_fields must be the solr_field_name for non-MetadataDatastream derived datastreams)
227
+ # @param opts [Hash] specifies options for the solr query
223
228
  #
224
229
  # options may include:
225
230
  #
@@ -32,11 +32,11 @@ module ActiveFedora
32
32
  module ClassMethods
33
33
  # Creates an object just like Base.create but calls <tt>save!</tt> instead of +save+
34
34
  # so an exception is raised if the record is invalid.
35
- def create!(attributes = nil, options = {}, &block)
35
+ def create!(attributes = nil, &block)
36
36
  if attributes.is_a?(Array)
37
- attributes.collect { |attr| create!(attr, options, &block) }
37
+ attributes.collect { |attr| create!(attr, &block) }
38
38
  else
39
- object = new(attributes, options)
39
+ object = new(attributes)
40
40
  yield(object) if block_given?
41
41
  object.save!
42
42
  object
@@ -1,3 +1,3 @@
1
1
  module ActiveFedora
2
- VERSION = "4.5.3"
2
+ VERSION = "4.6.0.rc1"
3
3
  end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ describe "persisting objects" do
4
+ before :all do
5
+ class MockAFBaseRelationship < ActiveFedora::Base
6
+ has_metadata :type=>ActiveFedora::SimpleDatastream, :name=>"foo" do |m|
7
+ m.field "name", :string
8
+ end
9
+ delegate :name, :to=>'foo', :unique=>true
10
+ validates :name, :presence=>true
11
+ end
12
+ end
13
+ after :all do
14
+ Object.send(:remove_const, :MockAFBaseRelationship)
15
+ end
16
+
17
+ describe "#create!" do
18
+ it "should validate" do
19
+ lambda { MockAFBaseRelationship.create!}.should raise_error ActiveFedora::RecordInvalid, "Validation failed: Name can't be blank"
20
+ end
21
+ end
22
+ end
@@ -17,6 +17,19 @@ describe ActiveFedora::Model do
17
17
  Object.send(:remove_const, :SpecModel)
18
18
  end
19
19
 
20
+ describe '.solr_query_handler' do
21
+ after do
22
+ # reset to default
23
+ SpecModel::Basic.solr_query_handler = 'standard'
24
+ end
25
+ it "should have a default" do
26
+ SpecModel::Basic.solr_query_handler.should == 'standard'
27
+ end
28
+ it "should be settable" do
29
+ SpecModel::Basic.solr_query_handler = 'search'
30
+ SpecModel::Basic.solr_query_handler.should == 'search'
31
+ end
32
+ end
20
33
 
21
34
  describe '#find' do
22
35
  describe "without :cast" do
@@ -173,6 +186,12 @@ describe ActiveFedora::Model do
173
186
  ActiveFedora::SolrService.expects(:query).with("#{@model_query} AND foo:bar", :rows=>0, :raw=>true).returns(mock_result)
174
187
  SpecModel::Basic.count(:conditions=>'foo:bar').should == 7
175
188
  end
189
+
190
+ it "should count without a class specified" do
191
+ mock_result = {'response'=>{'numFound'=>7}}
192
+ ActiveFedora::SolrService.expects(:query).with("foo:bar", :rows=>0, :raw=>true).returns(mock_result)
193
+ ActiveFedora::Base.count(:conditions=>'foo:bar').should == 7
194
+ end
176
195
  end
177
196
 
178
197
  describe '#find_by_solr' do
@@ -0,0 +1,75 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveFedora::Attributes::Serializers do
4
+ subject { ActiveFedora::Base }
5
+ describe "serialize to integer" do
6
+ it "should cast to integer" do
7
+ subject.coerce_to_integer("0").should == 0
8
+ subject.coerce_to_integer("01").should == 1
9
+ subject.coerce_to_integer("seven").should == 0 # same as "seven".to_i => 0
10
+ subject.coerce_to_integer("007seven").should == 7 # same as "007seven".to_i => 7
11
+ subject.coerce_to_integer("").should be_nil
12
+ subject.coerce_to_integer(nil).should be_nil
13
+ subject.coerce_to_integer("", :default=>7).should == 7
14
+ subject.coerce_to_integer(nil, :default=>7).should == 7
15
+ subject.coerce_to_integer("9", :default=>7).should == 9
16
+ end
17
+ end
18
+
19
+ describe "serialize to date" do
20
+ it "should cast to date" do
21
+ unless RUBY_VERSION < "1.9"
22
+ subject.coerce_to_date("30/10/2010").should == Date.parse('2010-10-30') # ruby interprets this as DD/MM/YYYY
23
+ end
24
+ subject.coerce_to_date("2010-01-31").should == Date.parse('2010-01-31')
25
+ end
26
+ it "should handle invalid dates" do
27
+ subject.coerce_to_date("0").should == nil #
28
+ unless RUBY_VERSION < "1.9"
29
+ subject.coerce_to_date("01/15/2010").should == nil # ruby interprets this as DD/MM/YYYY
30
+ end
31
+ subject.coerce_to_date("2010-31-01").should == nil
32
+ end
33
+ it "should work with a blank string" do
34
+ subject.coerce_to_date("").should == nil
35
+ subject.coerce_to_date("", :default=>:today).should be_kind_of Date
36
+ subject.coerce_to_date("", :default=>Date.parse('2010-01-31')).should == Date.parse('2010-01-31')
37
+ end
38
+ it "should work when nil is passed in" do
39
+ subject.coerce_to_date(nil).should == nil
40
+ subject.coerce_to_date(nil, :default=>:today).should be_kind_of Date
41
+ subject.coerce_to_date(nil, :default=>Date.parse('2010-01-31')).should == Date.parse('2010-01-31')
42
+ end
43
+ end
44
+ describe "serialize to boolean" do
45
+ it "should cast to bool" do
46
+ subject.coerce_to_boolean("true").should be_true
47
+ subject.coerce_to_boolean("false").should be_false
48
+ subject.coerce_to_boolean("faoo").should be_false
49
+ subject.coerce_to_boolean("").should be_false
50
+ subject.coerce_to_boolean("", :default=>true).should be_true
51
+ subject.coerce_to_boolean("", :default=>false).should be_false
52
+ subject.coerce_to_boolean("x", :default=>true).should be_false
53
+ subject.coerce_to_boolean("x", :default=>false).should be_false
54
+ subject.coerce_to_boolean(nil, :default=>true).should be_true
55
+ subject.coerce_to_boolean(nil, :default=>false).should be_false
56
+ end
57
+ end
58
+
59
+ describe "deserialize_dates_from_form" do
60
+ before do
61
+ class Foo < ActiveFedora::Base
62
+ attr_accessor :birthday
63
+ end
64
+ end
65
+ after do
66
+ Object.send(:remove_const, :Foo)
67
+ end
68
+ subject { Foo.new }
69
+ it "should deserialize dates" do
70
+ subject.attributes = {'birthday(1i)' =>'2012', 'birthday(2i)' =>'10', 'birthday(3i)' => '31'}
71
+ subject.birthday.should == '2012-10-31'
72
+ end
73
+ end
74
+
75
+ end
metadata CHANGED
@@ -1,8 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active-fedora
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.5.3
5
- prerelease:
4
+ version: 4.6.0.rc1
5
+ prerelease: 6
6
6
  platform: ruby
7
7
  authors:
8
8
  - Matt Zumwalt
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2012-10-08 00:00:00.000000000 Z
14
+ date: 2012-10-12 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: rsolr
@@ -93,6 +93,22 @@ dependencies:
93
93
  - - ! '>='
94
94
  - !ruby/object:Gem::Version
95
95
  version: 3.0.0
96
+ - !ruby/object:Gem::Dependency
97
+ name: builder
98
+ requirement: !ruby/object:Gem::Requirement
99
+ none: false
100
+ requirements:
101
+ - - ~>
102
+ - !ruby/object:Gem::Version
103
+ version: 3.0.0
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ none: false
108
+ requirements:
109
+ - - ~>
110
+ - !ruby/object:Gem::Version
111
+ version: 3.0.0
96
112
  - !ruby/object:Gem::Dependency
97
113
  name: mediashelf-loggable
98
114
  requirement: !ruby/object:Gem::Requirement
@@ -328,6 +344,8 @@ files:
328
344
  - lib/active_fedora/associations/belongs_to_association.rb
329
345
  - lib/active_fedora/associations/has_and_belongs_to_many_association.rb
330
346
  - lib/active_fedora/associations/has_many_association.rb
347
+ - lib/active_fedora/attributes.rb
348
+ - lib/active_fedora/attributes/serializers.rb
331
349
  - lib/active_fedora/base.rb
332
350
  - lib/active_fedora/callbacks.rb
333
351
  - lib/active_fedora/config.rb
@@ -417,6 +435,7 @@ files:
417
435
  - spec/integration/nested_attribute_spec.rb
418
436
  - spec/integration/nokogiri_datastream_spec.rb
419
437
  - spec/integration/ntriples_datastream_spec.rb
438
+ - spec/integration/persistence_spec.rb
420
439
  - spec/integration/rels_ext_datastream_spec.rb
421
440
  - spec/integration/semantic_node_spec.rb
422
441
  - spec/integration/solr_service_spec.rb
@@ -501,6 +520,7 @@ files:
501
520
  - spec/unit/rels_ext_datastream_spec.rb
502
521
  - spec/unit/rubydora_connection_spec.rb
503
522
  - spec/unit/semantic_node_spec.rb
523
+ - spec/unit/serializers_spec.rb
504
524
  - spec/unit/service_definitions_spec.rb
505
525
  - spec/unit/simple_datastream_spec.rb
506
526
  - spec/unit/solr_config_options_spec.rb
@@ -520,12 +540,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
520
540
  - - ! '>='
521
541
  - !ruby/object:Gem::Version
522
542
  version: '0'
543
+ segments:
544
+ - 0
545
+ hash: 190185801018639774
523
546
  required_rubygems_version: !ruby/object:Gem::Requirement
524
547
  none: false
525
548
  requirements:
526
- - - ! '>='
549
+ - - ! '>'
527
550
  - !ruby/object:Gem::Version
528
- version: '0'
551
+ version: 1.3.1
529
552
  requirements: []
530
553
  rubyforge_project: rubyfedora
531
554
  rubygems_version: 1.8.24
@@ -569,6 +592,7 @@ test_files:
569
592
  - spec/integration/nested_attribute_spec.rb
570
593
  - spec/integration/nokogiri_datastream_spec.rb
571
594
  - spec/integration/ntriples_datastream_spec.rb
595
+ - spec/integration/persistence_spec.rb
572
596
  - spec/integration/rels_ext_datastream_spec.rb
573
597
  - spec/integration/semantic_node_spec.rb
574
598
  - spec/integration/solr_service_spec.rb
@@ -653,6 +677,7 @@ test_files:
653
677
  - spec/unit/rels_ext_datastream_spec.rb
654
678
  - spec/unit/rubydora_connection_spec.rb
655
679
  - spec/unit/semantic_node_spec.rb
680
+ - spec/unit/serializers_spec.rb
656
681
  - spec/unit/service_definitions_spec.rb
657
682
  - spec/unit/simple_datastream_spec.rb
658
683
  - spec/unit/solr_config_options_spec.rb