active-fedora 4.0.0.rc18 → 4.0.0.rc19
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 +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
|