active-fedora 3.1.1 → 3.1.2
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.
- data/CONSOLE_GETTING_STARTED.textile +19 -6
- data/Gemfile.lock +1 -1
- data/History.txt +17 -0
- data/NOKOGIRI_DATASTREAMS.textile +185 -1
- data/lib/active_fedora/model.rb +36 -3
- data/lib/active_fedora/nokogiri_datastream.rb +6 -0
- data/lib/active_fedora/rdf_xml_writer.rb +69 -0
- data/lib/active_fedora/rels_ext_datastream.rb +9 -2
- data/lib/active_fedora/rubydora_connection.rb +8 -4
- data/lib/active_fedora/semantic_node.rb +18 -8
- data/lib/active_fedora/solr_service.rb +1 -12
- data/lib/active_fedora/version.rb +1 -1
- data/lib/tasks/active_fedora_dev.rake +0 -12
- data/spec/integration/model_spec.rb +5 -1
- data/spec/integration/nokogiri_datastream_spec.rb +5 -3
- data/spec/integration/solr_service_spec.rb +3 -0
- data/spec/unit/model_spec.rb +2 -1
- data/spec/unit/nokogiri_datastream_spec.rb +4 -2
- data/spec/unit/rdf_xml_writer.rb +63 -0
- data/spec/unit/rels_ext_datastream_spec.rb +11 -3
- data/spec/unit/rubydora_connection_spec.rb +29 -0
- data/spec/unit/semantic_node_spec.rb +8 -0
- metadata +7 -4
@@ -141,7 +141,15 @@ Use the relationships method to list the object's relationships:
|
|
141
141
|
|
142
142
|
<pre>
|
143
143
|
newthing.relationships
|
144
|
-
=>
|
144
|
+
=> #<RDF::Graph:0x83a53088(<>)>
|
145
|
+
|
146
|
+
newthing.relationships.statements.map(&:inspect)
|
147
|
+
=> ["#<RDF::Statement:0x8371a858(<info:fedora/changeme:30> <info:fedora/fedora-system:def/model#hasModel> <info:fedora/hydra-cModel:DisplaySet> .)>",
|
148
|
+
"#<RDF::Statement:0x8371a6f0(<info:fedora/changeme:30> <info:fedora/fedora-system:def/model#hasModel> <info:fedora/hydra-cModel:CommonMetadata> .)>",
|
149
|
+
"#<RDF::Statement:0x8371a3e4(<info:fedora/changeme:30> <info:fedora/fedora-system:def/relations-external#isMemberOf> <info:fedora/changeme:parentSet> .)>"]
|
150
|
+
|
151
|
+
newthing.relationships(:is_member_of)
|
152
|
+
=> ["info:fedora/changeme:parentSet"]
|
145
153
|
</pre>
|
146
154
|
|
147
155
|
The SpecialThing class definition contains these lines:
|
@@ -174,8 +182,17 @@ Now we'll create another Fedora object (using the default ActiveFedora object mo
|
|
174
182
|
newobj = ActiveFedora::Base.new
|
175
183
|
newobj.add_relationship(:has_derivation, newthing)
|
176
184
|
=> true
|
185
|
+
|
177
186
|
newobj.relationships
|
178
|
-
=>
|
187
|
+
=> #<RDF::Graph:0x83a53088(<>)>
|
188
|
+
|
189
|
+
newobj.relationships.statements.map(&:inspect)
|
190
|
+
=> ["#<RDF::Statement:0x8371a3e4(<info:fedora/changeme:30> <info:fedora/fedora-system:def/relations-external#hasDerivation> <info:fedora/changeme:30> .)>"]
|
191
|
+
|
192
|
+
newobj.relationships(:has_derivation)
|
193
|
+
=> ["info:fedora/changeme:30"]
|
194
|
+
|
195
|
+
|
179
196
|
newobj.save
|
180
197
|
=> ...
|
181
198
|
newobj.pid
|
@@ -256,10 +273,6 @@ newthing.pid
|
|
256
273
|
copy_as_base = ActiveFedora::Base.load_instance("changeme:30")
|
257
274
|
copy_as_base.pid
|
258
275
|
=> "changeme:30"
|
259
|
-
newthing.relationships
|
260
|
-
=> {:self=>{:has_model=>["info:fedora/afmodel:SpecialThing"]}}
|
261
|
-
copy_as_base.relationships
|
262
|
-
=> {:self=>{:has_model=>["info:fedora/afmodel:SpecialThing"]}}
|
263
276
|
newthing.datastreams.keys
|
264
277
|
=> ["DS1", "descMetadata", "Foo1", "minivan", "RELS-EXT", "rightsMetadata", "DC", "extraMetadataForFun"]
|
265
278
|
copy_as_base.datastreams.keys
|
data/Gemfile.lock
CHANGED
data/History.txt
CHANGED
@@ -1,3 +1,20 @@
|
|
1
|
+
3.1.2
|
2
|
+
correctly handling non-default pid_namespace (Benjamin Armintor)
|
3
|
+
info uri support; rdf:type predicate compatibility with Fedora(Benjamin Armintor)
|
4
|
+
more flexibility for initializing Rubydora (Michael B. Klein)
|
5
|
+
NokogiriDatastream and RELS-EXT datastream set mimeType (Justin Coyne)
|
6
|
+
|
7
|
+
|
8
|
+
3.1.1
|
9
|
+
adds support for better handling of literal values in the RELS-EXT datastream.
|
10
|
+
adds support for setting the controlGroup via a parameter to has_metadata.
|
11
|
+
ability to pass a predicate as a parameter to AF::Base#relationships to get a list of the matching targets. This reads a bit better than ids_for_outbound().
|
12
|
+
refactoring to support overriding certain sections (ContentModel) by consumers of active-fedora.
|
13
|
+
|
14
|
+
3.1.0
|
15
|
+
Based on rubydora for fedora interface
|
16
|
+
RDF-xml for the relationships
|
17
|
+
|
1
18
|
3.0.4
|
2
19
|
|
3
20
|
HYDRA-663 -- Passing an empty string to a id setter should clear the belongs to association
|
@@ -106,4 +106,188 @@ After calling add_datastream, then everything will be ready to save to Fedora.
|
|
106
106
|
|
107
107
|
<pre>
|
108
108
|
st.datastreams["descMetadata"].save
|
109
|
-
</pre>
|
109
|
+
</pre>
|
110
|
+
|
111
|
+
h2. (Rails3) Using ActiveModel methods and delegate to treat xml nodes like regular ActiveModel attributes
|
112
|
+
|
113
|
+
h3. Handling most xml fields with delegate method
|
114
|
+
|
115
|
+
Say you want to treat a mods title like a regular ActiveModel attribute so that you can use all of the Rails helpers and methods like form_for.
|
116
|
+
|
117
|
+
The Datastream definition:
|
118
|
+
|
119
|
+
<pre>
|
120
|
+
# app/models/mods_generic_content.rb
|
121
|
+
class ModsGenericContent < ObjectMods
|
122
|
+
|
123
|
+
set_terminology do |t|
|
124
|
+
t.root(:path=>"mods", :xmlns=>"http://www.loc.gov/mods/v3", :schema=>"http://www.loc.gov/standards/mods/v3/mods-3-2.xsd")
|
125
|
+
|
126
|
+
t.title_info(:path=>"titleInfo") {
|
127
|
+
t.main_title(:path=>"title", :label=>"title", :index_as=>[:facetable])
|
128
|
+
}
|
129
|
+
|
130
|
+
# Proxy Terms (delegate can only reference root terms, so you have to create a root term "title" that proxies to the correct spot in the Terminology)
|
131
|
+
t.title(:proxy=>[:title_info, :main_title])
|
132
|
+
end
|
133
|
+
end
|
134
|
+
</pre>
|
135
|
+
|
136
|
+
The Model:
|
137
|
+
|
138
|
+
|
139
|
+
<pre>
|
140
|
+
# app/models/generic_content.rb
|
141
|
+
class GenericContent < ActiveFedora::Base
|
142
|
+
|
143
|
+
include Hydra::ModelMethods
|
144
|
+
has_metadata :name => "descMetadata", :label=>"MODS metadata", :type => ModsGenericContent
|
145
|
+
|
146
|
+
delegate :title, :to=>:descMetadata
|
147
|
+
end
|
148
|
+
</pre>
|
149
|
+
|
150
|
+
Example form:
|
151
|
+
|
152
|
+
|
153
|
+
<pre>
|
154
|
+
# app/views/generic_contents.html.erb
|
155
|
+
<%= form_for @generic_content do |f| %>
|
156
|
+
<dl>
|
157
|
+
<dt class="title">
|
158
|
+
<%= f.label "Title:" %>
|
159
|
+
</dt>
|
160
|
+
<dd class="title">
|
161
|
+
<%= f.text_field :title %>
|
162
|
+
</dd>
|
163
|
+
</dl>
|
164
|
+
<%= f.submit "Save Changes" %>
|
165
|
+
<% end %>
|
166
|
+
</pre>
|
167
|
+
|
168
|
+
The Controller that processes updates:
|
169
|
+
|
170
|
+
<pre>
|
171
|
+
# app/controllers/generic_contents_controller.rb
|
172
|
+
class GenericContentsController < ApplicationController
|
173
|
+
|
174
|
+
# This renders the edit form
|
175
|
+
def edit
|
176
|
+
@generic_content = GenericContent.find(params[:id])
|
177
|
+
end
|
178
|
+
|
179
|
+
# This updates the object based on the info submitted by your form, which puts the Hash of new values into params["generic_content"]
|
180
|
+
def update
|
181
|
+
@generic_content = GenericContent.find(params[:id])
|
182
|
+
@generic_content.update_attributes(params[:generic_content])
|
183
|
+
if @generic_content.save
|
184
|
+
flash[:notice] = "Saved changes to #{@generic_content.title}"
|
185
|
+
else
|
186
|
+
flash[:error] = "Failed to save your changes!"
|
187
|
+
end
|
188
|
+
redirect_to edit_generic_content_path(@generic_content)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
</pre>
|
192
|
+
|
193
|
+
h3. Handling complex xml structures in attributes= method
|
194
|
+
|
195
|
+
This approach complements the usage of the delegate method to handle most xml nodes in your datasreams.
|
196
|
+
|
197
|
+
With this approach, you can still create relatively normal Rails forms while updating complex xml structures (ie. MODS name entries) internally without creating a separate controller & model for those structures.
|
198
|
+
|
199
|
+
Example: You want to create/edit xml like this in a descMetadata datastream that uses the GenericContentXml datatstream definition.
|
200
|
+
|
201
|
+
<pre>
|
202
|
+
<subject>
|
203
|
+
<topic>Subject 1</topic>
|
204
|
+
<catgegory>topic</category>
|
205
|
+
</subject>
|
206
|
+
<subject>
|
207
|
+
<topic>Subject 2</topic>
|
208
|
+
<catgegory>geographic</category>
|
209
|
+
</subject>
|
210
|
+
</pre>
|
211
|
+
|
212
|
+
You have a form that submits parameters like this:
|
213
|
+
|
214
|
+
<pre>
|
215
|
+
{
|
216
|
+
"generic_content" => {
|
217
|
+
"subjects" =>[
|
218
|
+
{
|
219
|
+
"topic" => "Subject 1",
|
220
|
+
"category" => "topic"
|
221
|
+
},{
|
222
|
+
"topic" => "Subject 2",
|
223
|
+
"category" => "geographic"
|
224
|
+
}
|
225
|
+
]
|
226
|
+
}}
|
227
|
+
</pre>
|
228
|
+
|
229
|
+
Here's the test:
|
230
|
+
|
231
|
+
<pre>
|
232
|
+
# spec/models/generic_content_spec.rb
|
233
|
+
describe "attributes=" do
|
234
|
+
before do
|
235
|
+
@node = GenericContent.new
|
236
|
+
@sample_post_params = {
|
237
|
+
"generic_content" => {
|
238
|
+
"subjects" =>[
|
239
|
+
{
|
240
|
+
"topic" => "Subject 1",
|
241
|
+
"category" => "topic"
|
242
|
+
},{
|
243
|
+
"topic" => "Subject 2",
|
244
|
+
"category" => "geographic"
|
245
|
+
}
|
246
|
+
]
|
247
|
+
}}
|
248
|
+
|
249
|
+
end
|
250
|
+
it "with subjects" do
|
251
|
+
@node.attributes = @sample_post_params["generic_content"]
|
252
|
+
@node.descMetadata.subject.length.should == 2
|
253
|
+
@node.descMetadata.subject(0).topic.should == ["Subject 1"]
|
254
|
+
@node.descMetadata.subject(0).category.should == ["topic"]
|
255
|
+
@node.descMetadata.subject(1).topic.should == ["Subject 2"]
|
256
|
+
@node.descMetadata.subject(1).category.should == ["geographic"]
|
257
|
+
end
|
258
|
+
end
|
259
|
+
</pre>
|
260
|
+
|
261
|
+
In the OM terminology of the Datasream definition:
|
262
|
+
|
263
|
+
<pre>
|
264
|
+
# app/models/generic_content_xml.rb
|
265
|
+
...
|
266
|
+
t.subject(:path=>"subject", :attributes=>{:authority=>"UoH"}) {
|
267
|
+
t.topic(:index_as=>[:facetable])
|
268
|
+
t.category
|
269
|
+
}
|
270
|
+
...
|
271
|
+
</pre>
|
272
|
+
|
273
|
+
The Model:
|
274
|
+
|
275
|
+
<pre>
|
276
|
+
# app/models/generic_content.rb
|
277
|
+
class GenericContent < ActiveFedora::Base
|
278
|
+
|
279
|
+
include Hydra::ModelMethods
|
280
|
+
has_metadata :name => "descMetadata", :label=>"generic metadata", :type => GenericContentXml
|
281
|
+
|
282
|
+
def attributes=(properties)
|
283
|
+
if (properties["subjects"])
|
284
|
+
self.descMetadata.subject.nodeset.remove # wipe out existing values
|
285
|
+
properties["subjects"].each_with_index do |subject_hash, index|
|
286
|
+
self.descMetadata.subject(index).topic = subject_hash["topic"]
|
287
|
+
self.descMetadata.subject(index).category = subject_hash["category"]
|
288
|
+
end
|
289
|
+
properties.delete("subjects")
|
290
|
+
end
|
291
|
+
super
|
292
|
+
end
|
293
|
+
</pre>
|
data/lib/active_fedora/model.rb
CHANGED
@@ -8,11 +8,36 @@ module ActiveFedora
|
|
8
8
|
# much in the way ActiveRecord does.
|
9
9
|
module Model
|
10
10
|
extend ActiveFedora::FedoraObject
|
11
|
-
|
11
|
+
DEFAULT_NS = 'afmodel'
|
12
12
|
|
13
13
|
def self.included(klass) # :nodoc:
|
14
14
|
klass.extend(ClassMethods)
|
15
15
|
end
|
16
|
+
|
17
|
+
# Takes a Fedora URI for a cModel, and returns a
|
18
|
+
# corresponding Model if available
|
19
|
+
# This method should reverse ClassMethods#to_class_uri
|
20
|
+
def self.from_class_uri(uri)
|
21
|
+
if match_data = /info:fedora\/([a-zA-z0-9\-_]+):(.+)$/.match(uri)
|
22
|
+
pid_ns = match_data[1]
|
23
|
+
model_value = match_data[2]
|
24
|
+
model_value.gsub!('_', '::')
|
25
|
+
else
|
26
|
+
raise "model URI incorrectly formatted: #{uri}"
|
27
|
+
end
|
28
|
+
if model_value.include?("::")
|
29
|
+
result = eval(model_value)
|
30
|
+
else
|
31
|
+
result = Kernel.const_get(model_value)
|
32
|
+
end
|
33
|
+
unless result.nil?
|
34
|
+
model_ns = (result.respond_to? :pid_namespace) ? result.pid_namespace : DEFAULT_NS
|
35
|
+
if model_ns != pid_ns
|
36
|
+
logger.warn "Model class namespace (#{model_ns}) and uri namespace (#{pid_ns}) do not match!"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
result
|
40
|
+
end
|
16
41
|
|
17
42
|
def add_metadata
|
18
43
|
end
|
@@ -52,7 +77,15 @@ module ActiveFedora
|
|
52
77
|
def load_instance(pid)
|
53
78
|
RubydoraConnection.instance.find_model(pid, self)
|
54
79
|
end
|
55
|
-
|
80
|
+
|
81
|
+
# Returns a suitable uri object for :has_model
|
82
|
+
# Should reverse Model#from_class_uri
|
83
|
+
def to_class_uri
|
84
|
+
ns = (self.respond_to? :pid_namespace) ? self.pid_namespace : Model::DEFAULT_NS
|
85
|
+
pid = self.name.gsub(/::/,'_')
|
86
|
+
"info:fedora/#{ns}:#{pid}"
|
87
|
+
end
|
88
|
+
|
56
89
|
# Takes :all or a pid as arguments
|
57
90
|
# Returns an Array of objects of the Class that +find+ is being
|
58
91
|
# called on
|
@@ -62,7 +95,7 @@ module ActiveFedora
|
|
62
95
|
if args == :all
|
63
96
|
return_multiple = true
|
64
97
|
# escaped_class_name = self.name.gsub(/(:)/, '\\:')
|
65
|
-
escaped_class_uri =
|
98
|
+
escaped_class_uri = SolrService.escape_uri_for_query(self.to_class_uri)
|
66
99
|
# q = "#{ActiveFedora::SolrService.solr_name(:active_fedora_model, :symbol)}:#{escaped_class_name}"
|
67
100
|
q = "#{ActiveFedora::SolrService.solr_name(:has_model, :symbol)}:#{escaped_class_uri}"
|
68
101
|
elsif args.class == String
|
@@ -16,6 +16,12 @@ module ActiveFedora
|
|
16
16
|
alias_method(:om_update_values, :update_values) unless method_defined?(:om_update_values)
|
17
17
|
|
18
18
|
attr_accessor :internal_solr_doc
|
19
|
+
|
20
|
+
before_create :add_mime_type
|
21
|
+
|
22
|
+
def add_mime_type
|
23
|
+
self.mimeType= 'text/xml'
|
24
|
+
end
|
19
25
|
|
20
26
|
# Create an instance of this class based on xml content
|
21
27
|
# @param [String, File, Nokogiri::XML::Node] xml the xml content to build from
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'rdf/rdfxml'
|
3
|
+
require 'rdf'
|
4
|
+
|
5
|
+
module ActiveFedora
|
6
|
+
# This class ensures that the RELS-EXT datastream is always serialized
|
7
|
+
# with an rdf:Description container for the properties
|
8
|
+
# the default behavior for RDF:RDFXML::Writer is to change that element if
|
9
|
+
# an rdf:type assertion is present; this is incompatible with Fedora
|
10
|
+
class RDFXMLWriter < RDF::RDFXML::Writer
|
11
|
+
def subject(subject, parent_node)
|
12
|
+
node = nil
|
13
|
+
|
14
|
+
raise RDF::WriterError, "Illegal use of subject #{subject.inspect}, not supported in RDF/XML" unless subject.resource?
|
15
|
+
|
16
|
+
if !is_done?(subject)
|
17
|
+
subject_done(subject)
|
18
|
+
properties = @graph.properties(subject)
|
19
|
+
add_debug {"subject: #{subject.inspect}, props: #{properties.inspect}"}
|
20
|
+
|
21
|
+
@graph.query(:subject => subject).each do |st|
|
22
|
+
raise RDF::WriterError, "Illegal use of predicate #{st.predicate.inspect}, not supported in RDF/XML" unless st.predicate.uri?
|
23
|
+
end
|
24
|
+
|
25
|
+
prop_list = order_properties(properties)
|
26
|
+
add_debug {"=> property order: #{prop_list.to_sentence}"}
|
27
|
+
|
28
|
+
qname = "rdf:Description"
|
29
|
+
prefixes[:rdf] = RDF.to_uri
|
30
|
+
|
31
|
+
node = Nokogiri::XML::Element.new(qname, parent_node.document)
|
32
|
+
|
33
|
+
if subject.is_a?(RDF::Node)
|
34
|
+
# Only need nodeID if it's referenced elsewhere
|
35
|
+
if ref_count(subject) > (@depth == 0 ? 0 : 1)
|
36
|
+
node["rdf:nodeID"] = subject.id
|
37
|
+
else
|
38
|
+
node.add_child(Nokogiri::XML::Comment.new(node.document, "Serialization for #{subject}")) if RDF::RDFXML::debug?
|
39
|
+
end
|
40
|
+
else
|
41
|
+
node["rdf:about"] = relativize(subject)
|
42
|
+
end
|
43
|
+
|
44
|
+
prop_list.each do |prop|
|
45
|
+
prop_ref = RDF::URI.intern(prop)
|
46
|
+
|
47
|
+
properties[prop].each do |object|
|
48
|
+
raise RDF::WriterError, "Illegal use of object #{object.inspect}, not supported in RDF/XML" unless object.resource? || object.literal?
|
49
|
+
|
50
|
+
@depth += 1
|
51
|
+
predicate(prop_ref, object, node, properties[prop].length == 1)
|
52
|
+
@depth -= 1
|
53
|
+
end
|
54
|
+
end
|
55
|
+
elsif @force_RDF_about.include?(subject)
|
56
|
+
add_debug {"subject: #{subject.inspect}, force about"}
|
57
|
+
node = Nokogiri::XML::Element.new("rdf:Description", parent_node.document)
|
58
|
+
if subject.is_a?(RDF::Node)
|
59
|
+
node["rdf:nodeID"] = subject.id
|
60
|
+
else
|
61
|
+
node["rdf:about"] = relativize(subject)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
@force_RDF_about.delete(subject)
|
65
|
+
|
66
|
+
parent_node.add_child(node) if node
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -3,13 +3,20 @@ require 'solrizer/field_name_mapper'
|
|
3
3
|
require 'uri'
|
4
4
|
require 'rdf/rdfxml'
|
5
5
|
require 'rdf'
|
6
|
+
require 'active_fedora/rdf_xml_writer'
|
6
7
|
|
7
8
|
module ActiveFedora
|
8
9
|
class RelsExtDatastream < Datastream
|
9
10
|
|
10
11
|
include Solrizer::FieldNameMapper
|
11
12
|
attr_accessor :model
|
12
|
-
|
13
|
+
|
14
|
+
before_create :add_mime_type
|
15
|
+
|
16
|
+
def add_mime_type
|
17
|
+
self.mimeType= 'application/rdf+xml'
|
18
|
+
end
|
19
|
+
|
13
20
|
def serialize!
|
14
21
|
self.content = to_rels_ext() if model.relationships_are_dirty
|
15
22
|
model.relationships_are_dirty = false
|
@@ -46,7 +53,7 @@ module ActiveFedora
|
|
46
53
|
# @param [Hash] relationships (optional) @default self.relationships
|
47
54
|
# Note: This method is implemented on SemanticNode instead of RelsExtDatastream because SemanticNode contains the relationships array
|
48
55
|
def to_rels_ext()
|
49
|
-
xml =
|
56
|
+
xml = ActiveFedora::RDFXMLWriter.buffer do |writer|
|
50
57
|
model.relationships.each_statement do |statement|
|
51
58
|
writer << statement
|
52
59
|
end
|
@@ -9,6 +9,7 @@ module ActiveFedora
|
|
9
9
|
attr_accessor :options
|
10
10
|
|
11
11
|
def self.connect(params={})
|
12
|
+
params = params.dup
|
12
13
|
if params.kind_of? String
|
13
14
|
u = URI.parse params
|
14
15
|
params = {}
|
@@ -17,14 +18,17 @@ module ActiveFedora
|
|
17
18
|
params[:url] = "#{u.scheme}://#{u.host}:#{u.port}#{u.path}"
|
18
19
|
end
|
19
20
|
instance = self.instance
|
21
|
+
force = params.delete(:force)
|
20
22
|
instance.options = params
|
21
|
-
instance.connect
|
23
|
+
instance.connect force
|
22
24
|
instance
|
23
25
|
end
|
24
26
|
|
25
|
-
def connect()
|
26
|
-
return unless @connection.nil?
|
27
|
-
|
27
|
+
def connect(force=false)
|
28
|
+
return unless @connection.nil? or force
|
29
|
+
allowable_options = [:url, :user, :password, :timeout, :open_timeout, :ssl_client_cert, :ssl_client_key]
|
30
|
+
client_options = options.reject { |k,v| not allowable_options.include?(k) }
|
31
|
+
@connection = Rubydora.connect client_options
|
28
32
|
end
|
29
33
|
|
30
34
|
def nextid(attrs={})
|
@@ -32,21 +32,31 @@ module ActiveFedora
|
|
32
32
|
# @param uri a string represending the subject
|
33
33
|
# @param predicate a predicate symbol
|
34
34
|
# @param target an object to store
|
35
|
-
def build_statement(uri, predicate, target, literal=
|
35
|
+
def build_statement(uri, predicate, target, literal=false)
|
36
36
|
raise "Not allowed anymore" if uri == :self
|
37
37
|
target = target.internal_uri if target.respond_to? :internal_uri
|
38
38
|
subject = RDF::URI.new(uri) #TODO cache
|
39
|
-
|
39
|
+
unless literal or target.is_a? RDF::Resource
|
40
40
|
begin
|
41
|
-
|
41
|
+
target_uri = (target.is_a? URI) ? target : URI.parse(target)
|
42
|
+
if target_uri.scheme.nil?
|
43
|
+
raise ArgumentError, "Invalid target \"#{target}\". Must have namespace."
|
44
|
+
end
|
45
|
+
if target_uri.to_s =~ /\A[\w\-]+:[\w\-]+\Z/
|
46
|
+
raise ArgumentError, "Invalid target \"#{target}\". Target should be a complete URI, and not a pid."
|
47
|
+
end
|
42
48
|
rescue URI::InvalidURIError
|
43
|
-
literal
|
49
|
+
raise ArgumentError, "Invalid target \"#{target}\". Target must be specified as a literal, or be a valid URI."
|
44
50
|
end
|
45
51
|
end
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
52
|
+
if literal
|
53
|
+
object = RDF::Literal.new(target)
|
54
|
+
elsif target.is_a? RDF::Resource
|
55
|
+
object = target
|
56
|
+
else
|
57
|
+
object = RDF::URI.new(target)
|
58
|
+
end
|
59
|
+
RDF::Statement.new(subject, find_graph_predicate(predicate), object)
|
50
60
|
|
51
61
|
end
|
52
62
|
|
@@ -44,18 +44,7 @@ module ActiveFedora
|
|
44
44
|
|
45
45
|
def self.class_from_solr_document(hit)
|
46
46
|
model_value = hit[solr_name("has_model", :symbol)].first
|
47
|
-
|
48
|
-
model_value = match_data[1]
|
49
|
-
model_value.gsub!('_', '::')
|
50
|
-
else
|
51
|
-
raise "has_model assertion incorrectly formatted: #{model_value}"
|
52
|
-
end
|
53
|
-
|
54
|
-
if model_value.include?("::")
|
55
|
-
eval(model_value)
|
56
|
-
else
|
57
|
-
Kernel.const_get(model_value)
|
58
|
-
end
|
47
|
+
Model.from_class_uri(model_value)
|
59
48
|
end
|
60
49
|
|
61
50
|
# Construct a solr query for a list of pids
|
@@ -69,12 +69,6 @@ namespace :active_fedora do
|
|
69
69
|
t.rcov_opts << ['--exclude', 'spec']
|
70
70
|
end
|
71
71
|
|
72
|
-
desc "Refresh test fixtres"
|
73
|
-
task :refresh_fixtures do
|
74
|
-
Rake::Task["active_fedora:clean_jetty"].invoke
|
75
|
-
Rake::Task["active_fedora:load_fixtures"].invoke
|
76
|
-
end
|
77
|
-
|
78
72
|
task :clean_jetty do
|
79
73
|
Dir.chdir("./jetty")
|
80
74
|
system("git clean -f -d")
|
@@ -83,12 +77,6 @@ namespace :active_fedora do
|
|
83
77
|
end
|
84
78
|
|
85
79
|
task :load_fixtures => :environment do
|
86
|
-
# require 'solrizer'
|
87
|
-
# require 'solrizer-fedora'
|
88
|
-
# require 'spec/samples/models/hydrangea_article'
|
89
|
-
# ENV["FEDORA_HOME"] ||= File.expand_path(File.join(File.dirname(__FILE__),'..','..','jetty','fedora','default'))
|
90
|
-
# retval = `$FEDORA_HOME/client/bin/fedora-ingest-demos.sh localhost 8983 fedoraAdmin fedoraAdmin http`
|
91
|
-
# puts "loaded demo objects #{retval}"
|
92
80
|
ActiveFedora.init unless Thread.current[:repo]
|
93
81
|
|
94
82
|
ENV["pid"] = "hydrangea:fixture_mods_article1"
|
@@ -17,6 +17,9 @@ describe ActiveFedora::Model do
|
|
17
17
|
|
18
18
|
class Basic < ActiveFedora::Base
|
19
19
|
include ActiveFedora::Model
|
20
|
+
def self.pid_namespace
|
21
|
+
"foo"
|
22
|
+
end
|
20
23
|
end
|
21
24
|
|
22
25
|
end
|
@@ -34,9 +37,10 @@ describe ActiveFedora::Model do
|
|
34
37
|
|
35
38
|
describe '#find' do
|
36
39
|
it "should return an array of instances of the calling Class" do
|
37
|
-
pending
|
38
40
|
result = ModelIntegrationSpec::Basic.find(:all)
|
39
41
|
result.should be_instance_of(Array)
|
42
|
+
# this test is meaningless if the array length is zero
|
43
|
+
result.length.should > 0
|
40
44
|
result.each do |obj|
|
41
45
|
obj.class.should == ModelIntegrationSpec::Basic
|
42
46
|
end
|
@@ -21,12 +21,14 @@ describe ActiveFedora::NokogiriDatastream do
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
-
@pid = "hydrangea:fixture_mods_article1"
|
25
|
-
@test_solr_object = HydrangeaArticle2.load_instance_from_solr(@pid)
|
26
|
-
@test_object = HydrangeaArticle2.load_instance(@pid)
|
27
24
|
end
|
28
25
|
|
29
26
|
describe '.term_values' do
|
27
|
+
before do
|
28
|
+
@pid = "hydrangea:fixture_mods_article1"
|
29
|
+
@test_solr_object = HydrangeaArticle2.load_instance_from_solr(@pid)
|
30
|
+
@test_object = HydrangeaArticle2.load_instance(@pid)
|
31
|
+
end
|
30
32
|
|
31
33
|
it "should return the same values whether getting from solr or Fedora" do
|
32
34
|
@test_solr_object.datastreams["descMetadata"].term_values(:name,:role,:text).should == ["Creator","Contributor","Funder","Host"]
|
@@ -6,6 +6,9 @@ describe ActiveFedora::SolrService do
|
|
6
6
|
describe "#reify_solr_results" do
|
7
7
|
before(:all) do
|
8
8
|
class FooObject < ActiveFedora::Base
|
9
|
+
def self.pid_namespace
|
10
|
+
"foo"
|
11
|
+
end
|
9
12
|
has_metadata :name => "properties", :type => ActiveFedora::MetadataDatastream do |m|
|
10
13
|
m.field "holding_id", :string
|
11
14
|
end
|
data/spec/unit/model_spec.rb
CHANGED
@@ -103,7 +103,8 @@ describe ActiveFedora::Model do
|
|
103
103
|
mock_solr = mock("SolrConnection")
|
104
104
|
mock_result = mock("MockResult")
|
105
105
|
mock_result.expects(:hits).returns([{"id" => "changeme:30"}, {"id" => "changeme:22"}])
|
106
|
-
mock_solr.expects(:query).with('has_model_s:info\\:fedora/afmodel\\:SpecModel\:\:Basic', :rows=>1001).returns(mock_result)
|
106
|
+
#mock_solr.expects(:query).with('has_model_s:info\\:fedora/afmodel\\:SpecModel\:\:Basic', :rows=>1001).returns(mock_result)
|
107
|
+
mock_solr.expects(:query).with('has_model_s:info\\:fedora/afmodel\\:SpecModel_Basic', :rows=>1001).returns(mock_result)
|
107
108
|
ActiveFedora::SolrService.expects(:instance).returns(mock("SolrService", :conn => mock_solr))
|
108
109
|
ActiveFedora::RubydoraConnection.instance.expects(:find_model).with("changeme:30", SpecModel::Basic).returns("Fake Object1")
|
109
110
|
ActiveFedora::RubydoraConnection.instance.expects(:find_model).with("changeme:22", SpecModel::Basic).returns("Fake Object2")
|
@@ -25,7 +25,7 @@ describe ActiveFedora::NokogiriDatastream do
|
|
25
25
|
|
26
26
|
after(:each) do
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
29
|
it "should include the Solrizer::XML::TerminologyBasedSolrizer for .to_solr support" do
|
30
30
|
ActiveFedora::NokogiriDatastream.included_modules.should include(Solrizer::XML::TerminologyBasedSolrizer)
|
31
31
|
end
|
@@ -171,10 +171,12 @@ describe ActiveFedora::NokogiriDatastream do
|
|
171
171
|
end
|
172
172
|
it "should persist the product of .to_xml in fedora" do
|
173
173
|
@test_ds.expects(:new?).returns(true).twice
|
174
|
-
@mock_repo.expects(:
|
174
|
+
@mock_repo.expects(:datastream).with(:pid => nil, :dsid => 'descMetadata')
|
175
|
+
@mock_repo.expects(:add_datastream).with(:pid => nil, :dsid => 'descMetadata', :checksumType => 'DISABLED', :versionable => true, :content => 'fake xml', :controlGroup => 'M', :dsState => 'A', :mimeType=>'text/xml')
|
175
176
|
@test_ds.expects(:to_xml).returns("fake xml")
|
176
177
|
@test_ds.serialize!
|
177
178
|
@test_ds.save
|
179
|
+
@test_ds.mimeType.should == 'text/xml'
|
178
180
|
end
|
179
181
|
end
|
180
182
|
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require File.join( File.dirname(__FILE__), "../spec_helper" )
|
2
|
+
require File.join( File.dirname(__FILE__), "../../lib/active_fedora/rdf_xml_writer" )
|
3
|
+
|
4
|
+
describe ActiveFedora::RDFXMLWriter do
|
5
|
+
before(:all) do
|
6
|
+
@rdf_xml = <<-EOS
|
7
|
+
<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'>
|
8
|
+
<rdf:Description rdf:about='info:fedora/test:sample_pid'>
|
9
|
+
<isMemberOf rdf:resource='info:fedora/demo:10' xmlns='info:fedora/fedora-system:def/relations-external#'/>
|
10
|
+
<isPartOf rdf:resource='info:fedora/demo:11' xmlns='info:fedora/fedora-system:def/relations-external#'/>
|
11
|
+
<hasPart rdf:resource='info:fedora/demo:12' xmlns='info:fedora/fedora-system:def/relations-external#'/>
|
12
|
+
<hasModel rdf:resource='info:fedora/afmodel:OtherModel' xmlns='info:fedora/fedora-system:def/model#'/>
|
13
|
+
<hasModel rdf:resource='info:fedora/afmodel:SampleModel' xmlns='info:fedora/fedora-system:def/model#'/>
|
14
|
+
</rdf:Description>
|
15
|
+
</rdf:RDF>
|
16
|
+
EOS
|
17
|
+
|
18
|
+
@rdf_xml_with_type = <<-EOS
|
19
|
+
<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'>
|
20
|
+
<rdf:Description rdf:about='info:fedora/test:sample_pid'>
|
21
|
+
<isMemberOf rdf:resource='demo:10' xmlns='info:fedora/fedora-system:def/relations-external#'/>
|
22
|
+
<type rdf:resource='http://purl.org/dc/dcmitype/Collection' xmlns='http://www.w3.org/1999/02/22-rdf-syntax-ns#' />
|
23
|
+
</rdf:Description>
|
24
|
+
</rdf:RDF>
|
25
|
+
EOS
|
26
|
+
|
27
|
+
end
|
28
|
+
it "should serialize graphs using the rdf:Description element despite the presence of rdf:type statements" do
|
29
|
+
graph = RDF::Graph.new
|
30
|
+
subject = RDF::URI.new "info:fedora/test:sample_pid"
|
31
|
+
graph.insert RDF::Statement.new(subject, ActiveFedora::Base.new.find_graph_predicate(:is_member_of), RDF::URI.new('demo:10'))
|
32
|
+
graph.insert RDF::Statement.new(subject, RDF::URI('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'), RDF::URI.new('http://purl.org/dc/dcmitype/Collection'))
|
33
|
+
content = RDF::RDFXML::Writer.buffer do |writer|
|
34
|
+
graph.each_statement do |statement|
|
35
|
+
writer << statement
|
36
|
+
end
|
37
|
+
end
|
38
|
+
EquivalentXml.equivalent?(content, @rdf_xml_with_type).should be_true
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should serialize graphs without rdf:type equivalently to RDF::RDFXML::Writer' do
|
42
|
+
graph = RDF::Graph.new
|
43
|
+
subject = RDF::URI.new "info:fedora/test:sample_pid"
|
44
|
+
graph.insert RDF::Statement.new(subject, ActiveFedora::Base.new.find_graph_predicate(:is_member_of), RDF::URI.new('info:fedora/demo:10'))
|
45
|
+
graph.insert RDF::Statement.new(subject, ActiveFedora::Base.new.find_graph_predicate(:is_part_of), RDF::URI.new('info:fedora/demo:11'))
|
46
|
+
graph.insert RDF::Statement.new(subject, ActiveFedora::Base.new.find_graph_predicate(:has_part), RDF::URI.new('info:fedora/demo:12'))
|
47
|
+
graph.insert RDF::Statement.new(subject, ActiveFedora::Base.new.find_graph_predicate(:has_model), RDF::URI.new("info:fedora/afmodel:OtherModel"))
|
48
|
+
graph.insert RDF::Statement.new(subject, ActiveFedora::Base.new.find_graph_predicate(:has_model), RDF::URI.new("info:fedora/afmodel:SampleModel"))
|
49
|
+
|
50
|
+
local_content = ActiveFedora::RDFXMLWriter.buffer do |writer|
|
51
|
+
graph.each_statement do |statement|
|
52
|
+
writer << statement
|
53
|
+
end
|
54
|
+
end
|
55
|
+
generic_content = RDF::RDFXML::Writer.buffer do |writer|
|
56
|
+
graph.each_statement do |statement|
|
57
|
+
writer << statement
|
58
|
+
end
|
59
|
+
end
|
60
|
+
EquivalentXml.equivalent?(local_content, @rdf_xml).should be_true
|
61
|
+
EquivalentXml.equivalent?(local_content, generic_content).should be_true
|
62
|
+
end
|
63
|
+
end
|
@@ -21,9 +21,17 @@ describe ActiveFedora::RelsExtDatastream do
|
|
21
21
|
mock_inner.stubs(:pid).returns(@pid)
|
22
22
|
@test_ds = ActiveFedora::RelsExtDatastream.new(mock_inner, "RELS-EXT")
|
23
23
|
end
|
24
|
-
|
25
|
-
|
26
|
-
|
24
|
+
|
25
|
+
describe "#save" do
|
26
|
+
before do
|
27
|
+
@mock_repo.expects(:add_datastream).with(:pid => 'test:sample_pid', :dsid => 'RELS-EXT', :checksumType => 'DISABLED', :versionable => true, :content => 'fake xml', :controlGroup => 'M', :dsState => 'A', :mimeType=>'application/rdf+xml')
|
28
|
+
@mock_repo.expects(:datastream).with(:pid => 'test:sample_pid', :dsid => 'RELS-EXT')
|
29
|
+
@test_ds.content = 'fake xml'
|
30
|
+
end
|
31
|
+
it 'should set the mime type' do
|
32
|
+
@test_ds.save
|
33
|
+
@test_ds.mimeType.should == 'application/rdf+xml'
|
34
|
+
end
|
27
35
|
end
|
28
36
|
|
29
37
|
|
@@ -16,6 +16,35 @@ describe ActiveFedora::RubydoraConnection do
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
+
describe 'connect' do
|
20
|
+
before do
|
21
|
+
@instance = ActiveFedora::RubydoraConnection.instance
|
22
|
+
@reconfig = { :force => true, :url => @instance.connection.client.url }.merge(@instance.connection.client.options)
|
23
|
+
end
|
24
|
+
|
25
|
+
after do
|
26
|
+
ActiveFedora::RubydoraConnection.connect @reconfig
|
27
|
+
end
|
28
|
+
|
29
|
+
it "shouldn't reconnect by default" do
|
30
|
+
client_id = @instance.connection.client.object_id
|
31
|
+
ActiveFedora::RubydoraConnection.connect :timeout => 3600
|
32
|
+
@instance.connection.client.object_id.should == client_id
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should reconnect with force" do
|
36
|
+
client_id = @instance.connection.client.object_id
|
37
|
+
ActiveFedora::RubydoraConnection.connect :force => true
|
38
|
+
@instance.connection.client.object_id.should_not == client_id
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should pass through valid options" do
|
42
|
+
ActiveFedora::RubydoraConnection.connect :timeout => 3600, :fake_option => :missing, :force => true
|
43
|
+
@instance.connection.client.options[:timeout].should == 3600
|
44
|
+
@instance.connection.client.options.has_key?(:fake_option).should be_false
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
19
48
|
describe 'find_model' do
|
20
49
|
|
21
50
|
end
|
@@ -26,6 +26,14 @@ describe ActiveFedora::SemanticNode do
|
|
26
26
|
stm = @node.build_statement('info:fedora/spec:9', :is_part_of, 'info:fedora/spec:7')
|
27
27
|
stm.object.to_s.should == "info:fedora/spec:7"
|
28
28
|
end
|
29
|
+
it "should also be happy with non-info URIs" do
|
30
|
+
stm = @node.build_statement('info:fedora/spec:9', :is_annotation_of, 'http://www.w3.org/standards/techs/rdf')
|
31
|
+
stm.object.to_s.should == "http://www.w3.org/standards/techs/rdf"
|
32
|
+
end
|
33
|
+
it "should also be happy with targets that are URI::Generics" do
|
34
|
+
stm = @node.build_statement('info:fedora/spec:9', :is_annotation_of, URI.parse('http://www.w3.org/standards/techs/rdf'))
|
35
|
+
stm.object.to_s.should == "http://www.w3.org/standards/techs/rdf"
|
36
|
+
end
|
29
37
|
end
|
30
38
|
|
31
39
|
describe "with a bunch of objects" do
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active-fedora
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 7
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 3
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 3.1.
|
9
|
+
- 2
|
10
|
+
version: 3.1.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Matt Zumwalt
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2011-11-
|
19
|
+
date: 2011-11-18 00:00:00 -06:00
|
20
20
|
default_executable:
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|
@@ -589,6 +589,7 @@ files:
|
|
589
589
|
- lib/active_fedora/property.rb
|
590
590
|
- lib/active_fedora/qualified_dublin_core_datastream.rb
|
591
591
|
- lib/active_fedora/railtie.rb
|
592
|
+
- lib/active_fedora/rdf_xml_writer.rb
|
592
593
|
- lib/active_fedora/reflection.rb
|
593
594
|
- lib/active_fedora/relationship.rb
|
594
595
|
- lib/active_fedora/relationships_helper.rb
|
@@ -707,6 +708,7 @@ files:
|
|
707
708
|
- spec/unit/nokogiri_datastream_spec.rb
|
708
709
|
- spec/unit/property_spec.rb
|
709
710
|
- spec/unit/qualified_dublin_core_datastream_spec.rb
|
711
|
+
- spec/unit/rdf_xml_writer.rb
|
710
712
|
- spec/unit/relationship_spec.rb
|
711
713
|
- spec/unit/relationships_helper_spec.rb
|
712
714
|
- spec/unit/rels_ext_datastream_spec.rb
|
@@ -843,6 +845,7 @@ test_files:
|
|
843
845
|
- spec/unit/nokogiri_datastream_spec.rb
|
844
846
|
- spec/unit/property_spec.rb
|
845
847
|
- spec/unit/qualified_dublin_core_datastream_spec.rb
|
848
|
+
- spec/unit/rdf_xml_writer.rb
|
846
849
|
- spec/unit/relationship_spec.rb
|
847
850
|
- spec/unit/relationships_helper_spec.rb
|
848
851
|
- spec/unit/rels_ext_datastream_spec.rb
|