hydra-pbcore 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +17 -0
- data/.rvmrc +48 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +31 -0
- data/Rakefile +2 -0
- data/hydra-pbcore.gemspec +30 -0
- data/lib/hydra-pbcore.rb +18 -0
- data/lib/hydra-pbcore/behaviors.rb +60 -0
- data/lib/hydra-pbcore/datastream/digital_document.rb +269 -0
- data/lib/hydra-pbcore/datastream/document.rb +325 -0
- data/lib/hydra-pbcore/datastream/instantiation.rb +210 -0
- data/lib/hydra-pbcore/methods.rb +96 -0
- data/spec/digital_document_spec.rb +169 -0
- data/spec/document_spec.rb +189 -0
- data/spec/fixtures/pbcore_digital_document_template.xml +67 -0
- data/spec/fixtures/pbcore_document_template.xml +86 -0
- data/spec/fixtures/pbcore_instantiation_template.xml +62 -0
- data/spec/instantiation_spec.rb +134 -0
- data/spec/methods_spec.rb +63 -0
- data/spec/spec_helper.rb +21 -0
- metadata +235 -0
@@ -0,0 +1,96 @@
|
|
1
|
+
module HydraPbcore::Methods
|
2
|
+
|
3
|
+
# Module for inserting different types of PBcore xml nodes into
|
4
|
+
# an existing PBcore document
|
5
|
+
|
6
|
+
module ClassMethods
|
7
|
+
|
8
|
+
def publisher_template(opts={})
|
9
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
10
|
+
xml.pbcorePublisher {
|
11
|
+
xml.publisher
|
12
|
+
xml.publisherRole(:source=>"PBCore publisherRole")
|
13
|
+
}
|
14
|
+
end
|
15
|
+
return builder.doc.root
|
16
|
+
end
|
17
|
+
|
18
|
+
def contributor_template(opts={})
|
19
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
20
|
+
xml.pbcoreContributor {
|
21
|
+
xml.contributor
|
22
|
+
xml.contributorRole(:source=>"MARC relator terms")
|
23
|
+
}
|
24
|
+
end
|
25
|
+
return builder.doc.root
|
26
|
+
end
|
27
|
+
|
28
|
+
def previous_template(opts={})
|
29
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
30
|
+
xml.instantiationRelation {
|
31
|
+
xml.instantiationRelationType(:annotation=>"One of a multi-part instantiation") {
|
32
|
+
xml.text "Follows in Sequence"
|
33
|
+
}
|
34
|
+
xml.instantiationRelationIdentifier(:source=>"Rock and Roll Hall of Fame and Museum")
|
35
|
+
}
|
36
|
+
end
|
37
|
+
return builder.doc.root
|
38
|
+
end
|
39
|
+
|
40
|
+
def next_template(opts={})
|
41
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
42
|
+
xml.instantiationRelation {
|
43
|
+
xml.instantiationRelationType(:annotation=>"One of a multi-part instantiation") {
|
44
|
+
xml.text "Precedes in Sequence"
|
45
|
+
}
|
46
|
+
xml.instantiationRelationIdentifier(:source=>"Rock and Roll Hall of Fame and Museum")
|
47
|
+
}
|
48
|
+
end
|
49
|
+
return builder.doc.root
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.included(klass)
|
55
|
+
klass.extend(ClassMethods)
|
56
|
+
end
|
57
|
+
|
58
|
+
def insert_node(type, opts={})
|
59
|
+
|
60
|
+
unless self.class.respond_to?("#{type}_template".to_sym)
|
61
|
+
raise "No XML template is defined for a PBcore node of type #{type}."
|
62
|
+
end
|
63
|
+
|
64
|
+
node = self.class.send("#{type}_template".to_sym)
|
65
|
+
nodeset = self.find_by_terms(type.to_sym)
|
66
|
+
|
67
|
+
unless nodeset.nil?
|
68
|
+
if nodeset.empty?
|
69
|
+
if opts[:root]
|
70
|
+
self.find_by_terms(opts[:root].to_sym).first.add_child(node)
|
71
|
+
else
|
72
|
+
self.ng_xml.root.add_child(node)
|
73
|
+
end
|
74
|
+
index = 0
|
75
|
+
else
|
76
|
+
nodeset.after(node)
|
77
|
+
index = nodeset.length
|
78
|
+
end
|
79
|
+
self.dirty = true
|
80
|
+
end
|
81
|
+
|
82
|
+
return node, index
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
def remove_node(type, index)
|
87
|
+
if type == "education" or type == "television"
|
88
|
+
self.find_by_terms(type.to_sym).slice(index.to_i).parent.remove
|
89
|
+
else
|
90
|
+
self.find_by_terms(type.to_sym).slice(index.to_i).remove
|
91
|
+
end
|
92
|
+
self.dirty = true
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
end
|
@@ -0,0 +1,169 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe HydraPbcore::Datastream::DigitalDocument do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@object_ds = HydraPbcore::Datastream::DigitalDocument.new(nil, nil)
|
7
|
+
end
|
8
|
+
|
9
|
+
describe ".update_indexed_attributes" do
|
10
|
+
it "should update all of the fields in #xml_template and fields not requiring additional inserted nodes" do
|
11
|
+
[
|
12
|
+
[:pbc_id],
|
13
|
+
[:main_title],
|
14
|
+
[:alternative_title],
|
15
|
+
[:chapter],
|
16
|
+
[:episode],
|
17
|
+
[:label],
|
18
|
+
[:segment],
|
19
|
+
[:subtitle],
|
20
|
+
[:track],
|
21
|
+
[:translation],
|
22
|
+
[:summary],
|
23
|
+
[:parts_list],
|
24
|
+
[:lc_subject],
|
25
|
+
[:lc_name],
|
26
|
+
[:rh_subject],
|
27
|
+
[:getty_genre],
|
28
|
+
[:lc_genre],
|
29
|
+
[:lc_subject_genre],
|
30
|
+
[:event_series],
|
31
|
+
[:event_place],
|
32
|
+
[:event_date],
|
33
|
+
[:contributor_name],
|
34
|
+
[:contributor_role],
|
35
|
+
[:publisher_name],
|
36
|
+
[:publisher_role],
|
37
|
+
[:note],
|
38
|
+
[:archival_collection],
|
39
|
+
[:archival_series],
|
40
|
+
[:collection_number],
|
41
|
+
[:accession_number],
|
42
|
+
[:usage],
|
43
|
+
].each do |pointer|
|
44
|
+
test_val = "#{pointer.last.to_s} value"
|
45
|
+
@object_ds.update_values( {pointer=>{"0"=>test_val}} )
|
46
|
+
@object_ds.get_values(pointer).first.should == test_val
|
47
|
+
@object_ds.get_values(pointer).length.should == 1
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should work for fields that require added xml nodes" do
|
52
|
+
@object_ds.insert_node("publisher")
|
53
|
+
@object_ds.insert_node("contributor")
|
54
|
+
[
|
55
|
+
[:publisher_name],
|
56
|
+
[:publisher_role],
|
57
|
+
[:contributor_name],
|
58
|
+
[:contributor_role]
|
59
|
+
].each do |pointer|
|
60
|
+
test_val = "#{pointer.last.to_s} value"
|
61
|
+
@object_ds.update_indexed_attributes( {pointer=>{"0"=>test_val}} )
|
62
|
+
@object_ds.get_values(pointer).first.should == test_val
|
63
|
+
@object_ds.get_values(pointer).length.should == 1
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should differentiate between multiple added nodes" do
|
68
|
+
@object_ds.insert_node(:contributor)
|
69
|
+
@object_ds.insert_node(:contributor)
|
70
|
+
@object_ds.update_indexed_attributes( {[:contributor_name] => { 0 => "first contributor" }} )
|
71
|
+
@object_ds.update_indexed_attributes( {[:contributor_name] => { 1 => "second contributor" }} )
|
72
|
+
@object_ds.update_indexed_attributes( {[:contributor_role] => { 0 => "first contributor role" }} )
|
73
|
+
@object_ds.update_indexed_attributes( {[:contributor_role] => { 1 => "second contributor role" }} )
|
74
|
+
@object_ds.get_values(:contributor).length.should == 2
|
75
|
+
@object_ds.get_values(:contributor_name)[0].should == "first contributor"
|
76
|
+
@object_ds.get_values(:contributor_name)[1].should == "second contributor"
|
77
|
+
@object_ds.get_values(:contributor_role)[0].should == "first contributor role"
|
78
|
+
@object_ds.get_values(:contributor_role)[1].should == "second contributor role"
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
describe "#xml_template" do
|
84
|
+
it "should return an empty xml document matching a valid exmplar" do
|
85
|
+
# insert additional nodes
|
86
|
+
@object_ds.insert_node("publisher")
|
87
|
+
@object_ds.insert_node("contributor")
|
88
|
+
@object_ds.insert_node("publisher")
|
89
|
+
@object_ds.insert_node("contributor")
|
90
|
+
|
91
|
+
# update additional nodes that OM will insert automatically
|
92
|
+
@object_ds.update_indexed_attributes({ [:alternative_title] => { 0 => "inserted" }} )
|
93
|
+
@object_ds.update_indexed_attributes({ [:chapter] => { 0 => "inserted" }} )
|
94
|
+
@object_ds.update_indexed_attributes({ [:episode] => { 0 => "inserted" }} )
|
95
|
+
@object_ds.update_indexed_attributes({ [:label] => { 0 => "inserted" }} )
|
96
|
+
@object_ds.update_indexed_attributes({ [:segment] => { 0 => "inserted" }} )
|
97
|
+
@object_ds.update_indexed_attributes({ [:subtitle] => { 0 => "inserted" }} )
|
98
|
+
@object_ds.update_indexed_attributes({ [:track] => { 0 => "inserted" }} )
|
99
|
+
@object_ds.update_indexed_attributes({ [:translation] => { 0 => "inserted" }} )
|
100
|
+
@object_ds.update_indexed_attributes({ [:lc_subject] => { 0 => "inserted" }} )
|
101
|
+
@object_ds.update_indexed_attributes({ [:lc_name] => { 0 => "inserted" }} )
|
102
|
+
@object_ds.update_indexed_attributes({ [:rh_subject] => { 0 => "inserted" }} )
|
103
|
+
@object_ds.update_indexed_attributes({ [:getty_genre] => { 0 => "inserted" }} )
|
104
|
+
@object_ds.update_indexed_attributes({ [:lc_genre] => { 0 => "inserted" }} )
|
105
|
+
@object_ds.update_indexed_attributes({ [:lc_subject_genre] => { 0 => "inserted" }} )
|
106
|
+
@object_ds.update_indexed_attributes({ [:subject] => { 0 => "inserted" }} )
|
107
|
+
@object_ds.update_indexed_attributes({ [:genre] => { 0 => "inserted" }} )
|
108
|
+
|
109
|
+
# Load example fixture
|
110
|
+
f = fixture "pbcore_digital_document_template.xml"
|
111
|
+
ref_node = Nokogiri::XML(f)
|
112
|
+
f.close
|
113
|
+
|
114
|
+
# Nokogiri-fy our sample document and reorder nodes
|
115
|
+
sample_node = Nokogiri::XML(@object_ds.to_xml)
|
116
|
+
reordered = HydraPbcore::Behaviors.reorder_document(sample_node)
|
117
|
+
|
118
|
+
# Save this for later...
|
119
|
+
out = File.new("tmp/pbcore_digital_document_sample.xml", "w")
|
120
|
+
out.write(reordered.to_s)
|
121
|
+
out.close
|
122
|
+
|
123
|
+
EquivalentXml.equivalent?(ref_node, reordered, opts = { :element_order => false, :normalize_whitespace => true }).should be_true
|
124
|
+
HydraPbcore::Behaviors.validate(reordered).should be_empty
|
125
|
+
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
describe ".insert_node" do
|
130
|
+
it "should return a node and index for a given template type" do
|
131
|
+
["publisher", "contributor"].each do |type|
|
132
|
+
node, index = @object_ds.insert_node(type.to_s)
|
133
|
+
index.should == 0
|
134
|
+
@object_ds.dirty?.should be_true
|
135
|
+
node, index = @object_ds.insert_node(type.to_s)
|
136
|
+
index.should == 1
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
it "should raise an exception for non-exisitent templates" do
|
141
|
+
lambda { @object_ds.insert_node("blarg") }.should raise_error
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
describe ".remove_node" do
|
146
|
+
it "should remove a node a given type and index" do
|
147
|
+
["publisher", "contributor"].each do |type|
|
148
|
+
@object_ds.insert_node(type.to_sym)
|
149
|
+
@object_ds.insert_node(type.to_sym)
|
150
|
+
@object_ds.find_by_terms(type.to_sym).count.should == 2
|
151
|
+
@object_ds.remove_node(type.to_sym, "1")
|
152
|
+
@object_ds.find_by_terms(type.to_sym).count.should == 1
|
153
|
+
@object_ds.remove_node(type.to_sym, "0")
|
154
|
+
@object_ds.find_by_terms(type.to_sym).count.should == 0
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
159
|
+
|
160
|
+
describe "default fields" do
|
161
|
+
|
162
|
+
it "such as media type should be 'Moving image'" do
|
163
|
+
pending "No default fields defined yet"
|
164
|
+
@object_ds.get_values([:media_type]).first.should == "Moving image"
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|
@@ -0,0 +1,189 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe HydraPbcore::Datastream::Document do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@object_ds = HydraPbcore::Datastream::Document.new(nil, nil)
|
7
|
+
end
|
8
|
+
|
9
|
+
describe ".update_indexed_attributes" do
|
10
|
+
it "should update all of the fields in #xml_template and fields not requiring additional inserted nodes" do
|
11
|
+
[
|
12
|
+
[:pbc_id],
|
13
|
+
[:main_title],
|
14
|
+
[:alternative_title],
|
15
|
+
[:chapter],
|
16
|
+
[:episode],
|
17
|
+
[:label],
|
18
|
+
[:segment],
|
19
|
+
[:subtitle],
|
20
|
+
[:track],
|
21
|
+
[:translation],
|
22
|
+
[:summary],
|
23
|
+
[:parts_list],
|
24
|
+
[:lc_subject],
|
25
|
+
[:lc_name],
|
26
|
+
[:rh_subject],
|
27
|
+
[:getty_genre],
|
28
|
+
[:lc_genre],
|
29
|
+
[:lc_subject_genre],
|
30
|
+
[:event_series],
|
31
|
+
[:event_place],
|
32
|
+
[:event_date],
|
33
|
+
[:contributor_name],
|
34
|
+
[:contributor_role],
|
35
|
+
[:publisher_name],
|
36
|
+
[:publisher_role],
|
37
|
+
[:note],
|
38
|
+
[:creation_date],
|
39
|
+
[:barcode],
|
40
|
+
[:repository],
|
41
|
+
[:format],
|
42
|
+
[:standard],
|
43
|
+
[:media_type],
|
44
|
+
[:generation],
|
45
|
+
[:language],
|
46
|
+
[:colors],
|
47
|
+
[:archival_collection],
|
48
|
+
[:archival_series],
|
49
|
+
[:collection_number],
|
50
|
+
[:accession_number],
|
51
|
+
[:usage],
|
52
|
+
[:condition_note],
|
53
|
+
[:cleaning_note]
|
54
|
+
].each do |pointer|
|
55
|
+
test_val = "#{pointer.last.to_s} value"
|
56
|
+
@object_ds.update_values( {pointer=>{"0"=>test_val}} )
|
57
|
+
@object_ds.get_values(pointer).first.should == test_val
|
58
|
+
@object_ds.get_values(pointer).length.should == 1
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should work for fields that require added xml nodes" do
|
63
|
+
@object_ds.insert_node("publisher")
|
64
|
+
@object_ds.insert_node("contributor")
|
65
|
+
[
|
66
|
+
[:publisher_name],
|
67
|
+
[:publisher_role],
|
68
|
+
[:contributor_name],
|
69
|
+
[:contributor_role]
|
70
|
+
].each do |pointer|
|
71
|
+
test_val = "#{pointer.last.to_s} value"
|
72
|
+
@object_ds.update_indexed_attributes( {pointer=>{"0"=>test_val}} )
|
73
|
+
@object_ds.get_values(pointer).first.should == test_val
|
74
|
+
@object_ds.get_values(pointer).length.should == 1
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should differentiate between multiple added nodes" do
|
79
|
+
@object_ds.insert_node(:contributor)
|
80
|
+
@object_ds.insert_node(:contributor)
|
81
|
+
@object_ds.update_indexed_attributes( {[:contributor_name] => { 0 => "first contributor" }} )
|
82
|
+
@object_ds.update_indexed_attributes( {[:contributor_name] => { 1 => "second contributor" }} )
|
83
|
+
@object_ds.update_indexed_attributes( {[:contributor_role] => { 0 => "first contributor role" }} )
|
84
|
+
@object_ds.update_indexed_attributes( {[:contributor_role] => { 1 => "second contributor role" }} )
|
85
|
+
@object_ds.get_values(:contributor).length.should == 2
|
86
|
+
@object_ds.get_values(:contributor_name)[0].should == "first contributor"
|
87
|
+
@object_ds.get_values(:contributor_name)[1].should == "second contributor"
|
88
|
+
@object_ds.get_values(:contributor_role)[0].should == "first contributor role"
|
89
|
+
@object_ds.get_values(:contributor_role)[1].should == "second contributor role"
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
describe "#xml_template" do
|
95
|
+
it "should return an empty xml document matching a valid exmplar" do
|
96
|
+
# insert additional nodes
|
97
|
+
@object_ds.insert_node("publisher")
|
98
|
+
@object_ds.insert_node("contributor")
|
99
|
+
@object_ds.insert_node("publisher")
|
100
|
+
@object_ds.insert_node("contributor")
|
101
|
+
|
102
|
+
# update additional nodes that OM will insert automatically
|
103
|
+
@object_ds.update_indexed_attributes({ [:alternative_title] => { 0 => "inserted" }} )
|
104
|
+
@object_ds.update_indexed_attributes({ [:chapter] => { 0 => "inserted" }} )
|
105
|
+
@object_ds.update_indexed_attributes({ [:episode] => { 0 => "inserted" }} )
|
106
|
+
@object_ds.update_indexed_attributes({ [:label] => { 0 => "inserted" }} )
|
107
|
+
@object_ds.update_indexed_attributes({ [:segment] => { 0 => "inserted" }} )
|
108
|
+
@object_ds.update_indexed_attributes({ [:subtitle] => { 0 => "inserted" }} )
|
109
|
+
@object_ds.update_indexed_attributes({ [:track] => { 0 => "inserted" }} )
|
110
|
+
@object_ds.update_indexed_attributes({ [:translation] => { 0 => "inserted" }} )
|
111
|
+
@object_ds.update_indexed_attributes({ [:lc_subject] => { 0 => "inserted" }} )
|
112
|
+
@object_ds.update_indexed_attributes({ [:lc_name] => { 0 => "inserted" }} )
|
113
|
+
@object_ds.update_indexed_attributes({ [:rh_subject] => { 0 => "inserted" }} )
|
114
|
+
@object_ds.update_indexed_attributes({ [:getty_genre] => { 0 => "inserted" }} )
|
115
|
+
@object_ds.update_indexed_attributes({ [:lc_genre] => { 0 => "inserted" }} )
|
116
|
+
@object_ds.update_indexed_attributes({ [:lc_subject_genre] => { 0 => "inserted" }} )
|
117
|
+
@object_ds.update_indexed_attributes({ [:subject] => { 0 => "inserted" }} )
|
118
|
+
@object_ds.update_indexed_attributes({ [:genre] => { 0 => "inserted" }} )
|
119
|
+
@object_ds.update_indexed_attributes({ [:condition_note] => { 0 => "inserted" }} )
|
120
|
+
@object_ds.update_indexed_attributes({ [:cleaning_note] => { 0 => "inserted" }} )
|
121
|
+
|
122
|
+
# Load example fixture
|
123
|
+
f = fixture "pbcore_document_template.xml"
|
124
|
+
ref_node = Nokogiri::XML(f)
|
125
|
+
f.close
|
126
|
+
|
127
|
+
# Nokogiri-fy our sample document and reorder nodes
|
128
|
+
sample_node = Nokogiri::XML(@object_ds.to_xml)
|
129
|
+
reordered = HydraPbcore::Behaviors.reorder_document(sample_node)
|
130
|
+
|
131
|
+
# Save this for later...
|
132
|
+
out = File.new("tmp/pbcore_document_sample.xml", "w")
|
133
|
+
out.write(reordered.to_s)
|
134
|
+
out.close
|
135
|
+
|
136
|
+
EquivalentXml.equivalent?(ref_node, reordered, opts = { :element_order => false, :normalize_whitespace => true }).should be_true
|
137
|
+
HydraPbcore::Behaviors.validate(reordered).should be_empty
|
138
|
+
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
describe ".insert_node" do
|
143
|
+
it "should return a node and index for a given template type" do
|
144
|
+
["publisher", "contributor"].each do |type|
|
145
|
+
node, index = @object_ds.insert_node(type.to_s)
|
146
|
+
index.should == 0
|
147
|
+
@object_ds.dirty?.should be_true
|
148
|
+
node, index = @object_ds.insert_node(type.to_s)
|
149
|
+
index.should == 1
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
it "should raise an exception for non-exisitent templates" do
|
154
|
+
lambda { @object_ds.insert_node("blarg") }.should raise_error
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
describe ".remove_node" do
|
159
|
+
it "should remove a node a given type and index" do
|
160
|
+
["publisher", "contributor"].each do |type|
|
161
|
+
@object_ds.insert_node(type.to_sym)
|
162
|
+
@object_ds.insert_node(type.to_sym)
|
163
|
+
@object_ds.find_by_terms(type.to_sym).count.should == 2
|
164
|
+
@object_ds.remove_node(type.to_sym, "1")
|
165
|
+
@object_ds.find_by_terms(type.to_sym).count.should == 1
|
166
|
+
@object_ds.remove_node(type.to_sym, "0")
|
167
|
+
@object_ds.find_by_terms(type.to_sym).count.should == 0
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
end
|
172
|
+
|
173
|
+
describe "default fields" do
|
174
|
+
|
175
|
+
it "such as media type should be 'Moving image'" do
|
176
|
+
@object_ds.get_values([:media_type]).first.should == "Moving image"
|
177
|
+
end
|
178
|
+
|
179
|
+
it "such as colors should be 'Color'" do
|
180
|
+
@object_ds.get_values([:colors]).first.should == "Color"
|
181
|
+
end
|
182
|
+
|
183
|
+
it "such as generation should be 'Original'" do
|
184
|
+
@object_ds.get_values([:generation]).first.should == "Original"
|
185
|
+
end
|
186
|
+
|
187
|
+
end
|
188
|
+
|
189
|
+
end
|