active-fedora 4.0.0.rc18 → 4.0.0.rc19
Sign up to get free protection for your applications and to get access to all the features.
- data/CONSOLE_GETTING_STARTED.textile +1 -1
- data/Gemfile.lock +1 -1
- data/History.txt +2 -1
- data/NOKOGIRI_DATASTREAMS.textile +1 -293
- data/README.textile +5 -5
- data/TODO +1 -0
- data/lib/active_fedora/associations.rb +7 -1
- data/lib/active_fedora/associations/association_collection.rb +5 -0
- data/lib/active_fedora/metadata_datastream.rb +5 -4
- data/lib/active_fedora/version.rb +1 -1
- data/spec/integration/associations_spec.rb +26 -0
- metadata +4 -4
@@ -1 +1 @@
|
|
1
|
-
Moved to "https://github.com/
|
1
|
+
Moved to "https://github.com/projecthydra/active_fedora/wiki/Getting-Started:-Console-Tour":https://github.com/projecthydra/active_fedora/wiki/Getting-Started:-Console-Tour
|
data/Gemfile.lock
CHANGED
data/History.txt
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
4.0.0.
|
1
|
+
4.0.0.rc19
|
2
2
|
Removed deprecations
|
3
3
|
* allowing :fedora level in fedora.yml
|
4
4
|
* automatic includes of Relationships and FileMethods is removed
|
@@ -25,6 +25,7 @@ HYDRA-766 Model#classname_from_uri singularizes terms, but it shouldn't change t
|
|
25
25
|
HYDRA-767 Remove Model::DEFAULT_NS
|
26
26
|
Upgrade Om to 1.6.0
|
27
27
|
QualifiedDublinCore now extends immediately from NokogiriDatastream
|
28
|
+
Deprecated MetadataDatastream
|
28
29
|
|
29
30
|
3.3.2
|
30
31
|
HYDRA-745 No need to require :url be present on external datastreams
|
@@ -1,293 +1 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
This document is about working with (Active)Fedora datastreams with XML content. Nokogiri is a ruby gem for working with xml, and OM (Opinionated Metadata) allows you to define a “terminology” to ease translation between XML and ruby objects.
|
4
|
-
|
5
|
-
h3. Learning More about OM (Opinionated Metadata)
|
6
|
-
|
7
|
-
For deeper exposure to what you can do with OM, see the "OM documentation":http://hudson.projecthydra.org/job/om/Documentation/ for "Getting Started":http://hudson.projecthydra.org/job/om/Documentation/file.GETTING_STARTED.html, "Querying Documents":http://hudson.projecthydra.org/job/om/Documentation/file.QUERYING_DOCUMENTS.html, and "Updating Documents":http://hudson.projecthydra.org/job/om/Documentation/file.UPDATING_DOCUMENTS.html. There is also information in the "solrizer":http://github.com/projecthydra/solrizer documentation about Solrizing documents.
|
8
|
-
|
9
|
-
You can run most of the examples from those tutorials against the descMetadata datastream you've created here.
|
10
|
-
|
11
|
-
<pre>
|
12
|
-
doc = st.datastreams["descMetadata"] # the datastream is the OM Document
|
13
|
-
...
|
14
|
-
doc.class
|
15
|
-
=> Hydra::ModsArticleDatastream # Hydra::ModsArticleDatastream is the Document Class
|
16
|
-
terminology = doc.class.terminology # The terminology is attached to the Document Class
|
17
|
-
</pre>
|
18
|
-
|
19
|
-
h2. Setup
|
20
|
-
|
21
|
-
This tutorial assumes that you've run script/console from the root of ActiveFedora and have imported the hydrangea:fixture_mods_article1 object. If you haven't done that, see "CONSOLE_GETTING_STARTED":http://hudson.projecthydra.org/job/active_fedora/Documentation/file.CONSOLE_GETTING_STARTED.html for instructions.
|
22
|
-
|
23
|
-
The model definition we're using in this tutorial is SpecialThing ( "see the code":https://github.com/mediashelf/active_fedora/blob/master/spec/samples/special_thing.rb )
|
24
|
-
|
25
|
-
|
26
|
-
Look in these datastream definitions to see the OM Terminologies they define. They have extra comments in the code:
|
27
|
-
* Hydra::ModsArticleDatastream ( "see the code":https://github.com/mediashelf/active_fedora/blob/master/spec/samples/hydra-mods_article_datastream.rb )
|
28
|
-
* Hydra::RightsMetadataDatastream ( "see the code":https://github.com/mediashelf/active_fedora/blob/master/spec/samples/hydra-rights_metadata_datastream.rb }
|
29
|
-
* Marpa::DcDatastream ( "see the code":https://github.com/mediashelf/active_fedora/blob/master/spec/samples/marpa-dc_datastream.rb )
|
30
|
-
|
31
|
-
|
32
|
-
h2. Using Existing OM Terminology
|
33
|
-
|
34
|
-
First, load the Fedora object as an instance of the SpecialThing ActiveFedora Model
|
35
|
-
|
36
|
-
<pre>
|
37
|
-
st = SpecialThing.load_instance("hydrangea:fixture_mods_article1")
|
38
|
-
</pre>
|
39
|
-
|
40
|
-
Take a look at the datastreams in the object.
|
41
|
-
|
42
|
-
<pre>
|
43
|
-
st.datastreams.keys
|
44
|
-
</pre>
|
45
|
-
|
46
|
-
Each datastream is associated with a class that is aware of its content. These classes are specified in the model.
|
47
|
-
|
48
|
-
<pre>
|
49
|
-
st.datastreams["rightsMetadata"].class
|
50
|
-
st.datastreams["descMetadata"].class
|
51
|
-
</pre>
|
52
|
-
|
53
|
-
You can retrieve the xml from the object as xml (string) using to_xml, or you can access it as a Nokogiri::XML::Document using .ng_xml
|
54
|
-
|
55
|
-
<pre>
|
56
|
-
st.datastreams["rightsMetadata"].to_xml
|
57
|
-
st.datastreams["rightsMetadata"].ng_xml.class
|
58
|
-
</pre>
|
59
|
-
|
60
|
-
An OM terminology is attached to the datastream's class. OM's convenience methods use the terminology to look up nodes and values for you.
|
61
|
-
|
62
|
-
<pre>
|
63
|
-
st.datastreams["rightsMetadata"].class.terminology
|
64
|
-
Hydra::RightsMetadataDatastream.terminology
|
65
|
-
</pre>
|
66
|
-
|
67
|
-
The Terminology in Hydra::ModsArticleDatastream lets you retrieve values from the descMetadata datastream's MODS content.
|
68
|
-
|
69
|
-
<pre>
|
70
|
-
mods_ds = st.datastreams["descMetadata"]
|
71
|
-
mods_ds.term_values(:person, :first_name)
|
72
|
-
mods_ds.term_values(:person, :last_name)
|
73
|
-
</pre>
|
74
|
-
|
75
|
-
You can use OM's find_by_terms method to retrieve xml nodes from the datastream. It returns Nokogiri::XML::Node objects.
|
76
|
-
|
77
|
-
<pre>
|
78
|
-
mods_ds.find_by_terms(:person)
|
79
|
-
mods_ds.find_by_terms(:person).length
|
80
|
-
mods_ds.find_by_terms(:person).each {|n| puts n.to_xml}
|
81
|
-
</pre>
|
82
|
-
|
83
|
-
Hydra::ModsArticleDatastream has all of the behaviors of an OM::Document.
|
84
|
-
|
85
|
-
h1. Setting the XML in a NokogiriDatastream from a file
|
86
|
-
|
87
|
-
h2. Creating a new Datastream using from_xml
|
88
|
-
|
89
|
-
<pre>
|
90
|
-
my_path = "spec/fixtures/mods_articles/hydrangea_article1.xml"
|
91
|
-
f = File.new(my_path)
|
92
|
-
mods_ds = Hydra::ModsArticleDatastream.from_xml(f)
|
93
|
-
</pre>
|
94
|
-
|
95
|
-
If you want to add that datastream to an object, set the datastream's dsid and then pass the datastream into the object's add_datastream method.
|
96
|
-
|
97
|
-
<pre>
|
98
|
-
mods_ds.dsid = "descMetadata"
|
99
|
-
st.add_datastream(mods_ds)
|
100
|
-
</pre>
|
101
|
-
|
102
|
-
|
103
|
-
h2. Saving the Datastream
|
104
|
-
|
105
|
-
After calling add_datastream, then everything will be ready to save to Fedora. In order to make sure that your updated datastream is actually saved to fedora, call .save _on the datastream_. If you call .save on the _object_, the changes you've made to the datastream might not be saved.
|
106
|
-
|
107
|
-
<pre>
|
108
|
-
st.datastreams["descMetadata"].save
|
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>
|
1
|
+
Moved to "https://github.com/projecthydra/active_fedora/wiki/Nokogiri-Datastreams":https://github.com/projecthydra/active_fedora/wiki/Nokogiri-Datastreams
|
data/README.textile
CHANGED
@@ -4,8 +4,8 @@ RubyFedora and ActiveFedora provide a set of Ruby gems for creating and managing
|
|
4
4
|
|
5
5
|
h2. Getting Help
|
6
6
|
|
7
|
-
* Project Homepage: "http://yourmediashelf.com/activefedora":http://yourmediashelf.com/activefedora
|
8
7
|
* Community Discussions & Mailing List are located at "http://groups.google.com/group/active-fedora":http://groups.google.com/group/active-fedora
|
8
|
+
* Developers hang out on IRC in #projecthydra on freenet.
|
9
9
|
|
10
10
|
h2. Installation
|
11
11
|
|
@@ -15,14 +15,14 @@ The gem is hosted on gemcutter.
|
|
15
15
|
|
16
16
|
h2. Getting Started
|
17
17
|
|
18
|
-
The "ActiveFedora Console Tour":
|
18
|
+
The "ActiveFedora Console Tour":https://github.com/projecthydra/active_fedora/wiki/Getting-Started:-Console-Tour gives you a brief tour through ActiveFedora's features on the command line.
|
19
19
|
|
20
20
|
h2. Testing (this Gem)
|
21
21
|
|
22
22
|
In order to run the RSpec tests, you need to have a copy of the ActiveFedora source code, and then run bundle install in the source directory.
|
23
23
|
|
24
24
|
<pre>
|
25
|
-
git clone https://github.com/
|
25
|
+
git clone https://github.com/projecthydra/active_fedora.git
|
26
26
|
cd /wherever/active_fedora/is
|
27
27
|
bundle install
|
28
28
|
git submodule init
|
@@ -84,11 +84,11 @@ h2. Acknowledgements
|
|
84
84
|
Creator: Matt Zumwalt ("MediaShelf":http://yourmediashelf.com)
|
85
85
|
|
86
86
|
Developers:
|
87
|
-
McClain Looney & Eddie Shin ("MediaShelf":http://yourmediashelf.com), Rick Johnson (Notre Dame)
|
87
|
+
Justin Coyne, McClain Looney & Eddie Shin ("MediaShelf":http://yourmediashelf.com), Rick Johnson (Notre Dame)
|
88
88
|
|
89
89
|
h2. LICENSE:
|
90
90
|
|
91
|
-
Copyright (c) 2009-
|
91
|
+
Copyright (c) 2009-2012 Matt Zumwalt & MediaShelf, LLC
|
92
92
|
|
93
93
|
This program is free software: you can redistribute it and/or modify
|
94
94
|
it under the terms of the GNU Lesser General Public License (LGPL) as
|
data/TODO
CHANGED
@@ -219,7 +219,12 @@ module ActiveFedora
|
|
219
219
|
def collection_reader_method(reflection, association_proxy_class)
|
220
220
|
redefine_method(reflection.name) do |*params|
|
221
221
|
|
222
|
-
|
222
|
+
if (params.first.is_a?(Hash) && params.first[:response_format] == :solr)
|
223
|
+
load_from_solr = true
|
224
|
+
force_reload = false
|
225
|
+
else
|
226
|
+
force_reload = params.first unless params.empty?
|
227
|
+
end
|
223
228
|
association = association_instance_get(reflection.name)
|
224
229
|
unless association
|
225
230
|
association = association_proxy_class.new(self, reflection)
|
@@ -227,6 +232,7 @@ module ActiveFedora
|
|
227
232
|
end
|
228
233
|
|
229
234
|
association.reload if force_reload
|
235
|
+
return association.load_from_solr if load_from_solr
|
230
236
|
|
231
237
|
association
|
232
238
|
end
|
@@ -136,6 +136,11 @@ module ActiveFedora
|
|
136
136
|
return ActiveFedora::SolrService.reify_solr_results(solr_result)
|
137
137
|
end
|
138
138
|
|
139
|
+
def load_from_solr
|
140
|
+
return [] if @finder_query.empty?
|
141
|
+
SolrService.query(@finder_query, :rows=>1000)
|
142
|
+
end
|
143
|
+
|
139
144
|
|
140
145
|
def add_record_to_target_with_callbacks(record)
|
141
146
|
# callback(:before_add, record)
|
@@ -11,10 +11,11 @@ module ActiveFedora
|
|
11
11
|
# .to_solr (among other things) is provided by ActiveFedora::MetadataDatastreamHelper
|
12
12
|
include ActiveFedora::MetadataDatastreamHelper
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
14
|
+
def initialize(digital_object, dsid)
|
15
|
+
ActiveSupport::Deprecation.warn("MetadataDatastream is deprecated and will be removed in a future release. Create a NokogiriDatastream to structure your data")
|
16
|
+
super
|
17
|
+
end
|
18
|
+
|
18
19
|
def to_solr(solr_doc = Hash.new) # :nodoc:
|
19
20
|
fields.each do |field_key, field_info|
|
20
21
|
if field_info.has_key?(:values) && !field_info[:values].nil?
|
@@ -60,6 +60,32 @@ describe ActiveFedora::Base do
|
|
60
60
|
|
61
61
|
end
|
62
62
|
|
63
|
+
it "saving the parent should save the relationships on the children" do
|
64
|
+
@library.save
|
65
|
+
@library.books = [@book, @book2]
|
66
|
+
@library.save
|
67
|
+
@library = Library.find(@library.pid)
|
68
|
+
@library.books.to_a.should == [@book, @book2]
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
it "should let you lookup an array of objects with solr" do
|
73
|
+
@library.save
|
74
|
+
@book.library = @library
|
75
|
+
@book2.library = @library
|
76
|
+
@book.save
|
77
|
+
@book2.save
|
78
|
+
|
79
|
+
@library = Library.find(@library.pid)
|
80
|
+
@library.books.to_a.should == [@book, @book2]
|
81
|
+
|
82
|
+
solr_resp = @library.books(:response_format=>:solr)
|
83
|
+
solr_resp.size.should == 2
|
84
|
+
solr_resp[0]['id'].should == @book.pid
|
85
|
+
solr_resp[1]['id'].should == @book2.pid
|
86
|
+
|
87
|
+
end
|
88
|
+
|
63
89
|
|
64
90
|
|
65
91
|
after do
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active-fedora
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 15424179
|
5
5
|
prerelease: 6
|
6
6
|
segments:
|
7
7
|
- 4
|
8
8
|
- 0
|
9
9
|
- 0
|
10
10
|
- rc
|
11
|
-
-
|
12
|
-
version: 4.0.0.
|
11
|
+
- 19
|
12
|
+
version: 4.0.0.rc19
|
13
13
|
platform: ruby
|
14
14
|
authors:
|
15
15
|
- Matt Zumwalt
|
@@ -19,7 +19,7 @@ autorequire:
|
|
19
19
|
bindir: bin
|
20
20
|
cert_chain: []
|
21
21
|
|
22
|
-
date: 2012-03-
|
22
|
+
date: 2012-03-30 00:00:00 Z
|
23
23
|
dependencies:
|
24
24
|
- !ruby/object:Gem::Dependency
|
25
25
|
prerelease: false
|