-
Notifications
You must be signed in to change notification settings - Fork 63
Lesson: Use RDF to Represent Flat Metadata like Dublin Core (AF7)
This lesson is known to work with active-fedora version 7.0.
Please update this wiki to reflect any other versions that have been tested.
- Define a Ruby Class whose instances Create/Manipulate RDF Resources with RDF assertions in them
The real awesomeness of RDF comes when you start building heterogeneous graphs/networks of linked nodes. However, as you will see, even with a homogeneous network where all of the resources are the same RDF Type, you can build rich networks of linked data. For this example, we will create resources with Dublin Core metadata assertions in them.
Note: Within a code base, we prefer to put the RdfResource definitions into a directory called rdf_types
that lives either in the lib
directory or in app/models
.
Create a directory called rdf_types
and
mkdir lib
mkdir lib/rdf_types
Then create a file called lib/rdf_types/dublin_core_asset.rb
and put the following code into it
class DublinCoreAsset < ActiveFedora::Rdf::Resource
property :title, predicate: RDF::DC.title
property :creator, predicate: RDF::DC.creator
property :contributor, predicate: RDF::DC.contributor
property :date, predicate: RDF::DC.date
property :subject, predicate: RDF::DC.subject
property :relation, predicate: RDF::DC.relation
end
On the command line, run bundle console
Within the console, require the class you've just defined.
require "./lib/rdf_types/dublin_core_asset"
=> true
Now create a new DublinCoreAsset resource and inspect its graph.
subject = RDF::URI('http://example.com/1234')
# => #<RDF::URI:0x234f8a8 URI:http://example.com/1234>
asset = DublinCoreAsset.new(subject)
# => #<DublinCoreAsset:0x3f8748eb229c(default)>
asset.dump(:ntriples)
# => ""
We haven't added any assertions into the graph yet, so we got an empty string when we dumped it. Now let's add some assertions.
Add an assertion that the title of your asset is "My title"
asset.title
# => []
asset.title = "My title"
# => "My title"
asset.title
# => ["My title"]
Now look at the graph again
asset.dump(:ntriples)
# => "<http://example.com/1234> <http://purl.org/dc/terms/title> \"My title\" .\n"
Now there's an assertion that our resource (identified by <http://example.com/1234>
in this example) has a dc:title that is the String literal "My title".
Add some more assertions and then look at the graph again.
asset.creator = "Sally Creator"
# => "Sally Creator"
asset.contributor = "Billy Contributor"
# => "Billy Contributor"
asset.contributor << "Sgt Labdirector"
# => nil
# but
asset.contributor
# => ["Billy Contributor", "Sgt Labdirector"]
asset.subject = ["repositories", "small data"]
# => ["repositories", "small data"]
puts asset.dump(:ntriples)
# <http://example.com/1234> <http://purl.org/dc/terms/title> "My title" .
# <http://example.com/1234> <http://purl.org/dc/terms/creator> "Sally Creator" .
# <http://example.com/1234> <http://purl.org/dc/terms/contributor> "Billy Contributor" .
# <http://example.com/1234> <http://purl.org/dc/terms/contributor> "Sgt Labdirector" .
# <http://example.com/1234> <http://purl.org/dc/terms/subject> "repositories" .
# <http://example.com/1234> <http://purl.org/dc/terms/subject> "small data" .
# => nil
Step: Assert association with a Resource as the Subject -- Create a Relationship between two Resource
asset2 = DublinCoreAsset.new
# => #<DublinCoreAsset:0x007fbc128c3248 @graph=#<RDF::Graph:0x3fde09461b54(default)>, @rdf_subject=#<RDF::Node:0x3fde09461910(_:g70222870878480)>>
asset.relation = asset2
# => #<DublinCoreAsset:0x007fc494fcd130 @graph=#<RDF::Graph:0x3fe24a7e6960(default)>, @rdf_subject=#<RDF::Node:0x3fe24a7e6884(_:g70222870878480)>>
asset2.rdf_subject.id
# => "g70222870878480"
puts asset.dump :ntriples
# <http://example.com/1234> <http://purl.org/dc/terms/title> "My title" .
# <http://example.com/1234> <http://purl.org/dc/terms/creator> "Sally Creator" .
# <http://example.com/1234> <http://purl.org/dc/terms/contributor> "Billy Contributor" .
# <http://example.com/1234> <http://purl.org/dc/terms/contributor> "Sgt Labdirector" .
# <http://example.com/1234> <http://purl.org/dc/terms/subject> "repositories" .
# <http://example.com/1234> <http://purl.org/dc/terms/subject> "small data" .
# <http://example.com/1234> <http://purl.org/dc/terms/relation> _:g69850278268800 .
# => nil
asset.relation.first == asset2
# => true
Classes of resources often share common features like a URI prefix or an RDF type assertion. For example, you might want your DublinCoreAssets to share the base URI info:fedora/
and to assert that they are objects of type 'http://www.mydomain.mn/metadata/ontologies/foo#SpecialAsset'. For convenience, it is possible to set these on the class level with the configure
method:
require "active-fedora"
class DublinCoreAsset < ActiveFedora::Rdf::Resource
configure type: RDF::URI('http://www.mydomain.mn/metadata/ontologies/foo#SpecialAsset'), base_uri: 'info:fedora'
property :title, predicate: RDF::DC.title
property :creator, predicate: RDF::DC.creator
property :contributor, predicate: RDF::DC.contributor
property :date, predicate: RDF::DC.date
property :subject, predicate: RDF::DC.subject
property :relation, predicate: RDF::DC.relation
end
Now restart the console and create an asset
require "./lib/rdf_types/dublin_core_asset"
asset = DublinCoreAsset.new('1')
# => #<DublinCoreAsset:0x007faa3ba06580(default)>>
asset.dump :ntriples
# => "<info:fedora/1> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.mydomain.mn/metadata/ontologies/foo#SpecialAsset> .\n"
As you can see, even before we add any assertions our node has an rdf:type assertion pointing to the URI we specified.
Resources can be associated with a Fedora object through an RDFDatastream. Create a new datastream in app/models/datastreams/dublin_core_datastream.rb
:
mkdir -p app/models/datastreams
require 'active-fedora'
class DublinCoreDatastream < ActiveFedora::RDFDatastream
property :title, predicate: RDF::DC.title
property :creator, predicate: RDF::DC.creator
property :contributor, predicate: RDF::DC.contributor
property :date, predicate: RDF::DC.date
property :subject, predicate: RDF::DC.subject
property :relation, predicate: RDF::DC.relation
end
Restart the console, require your class, and create a datastream:
require "./app/models/datastreams/dublin_core_datastream"
# => true
ds = DublinCoreDatastream.new
# => #<DublinCoreDatastream @pid="" @dsid="" @controlGroup="M" changed="false" @mimeType="" >
RDFDatastreams have an underlying Resource of a special class ActiveFedora::Rdf::ObjectResource
which saves its contents to the datastream.
ds.resource
# => #<ActiveFedora::Rdf::ObjectResource:0x3fc9ca1dbb58(default)>
ds.title = "Comet in Moominland"
# => "Comet in Moominland"
ds.title
# => ["Comet in Moominland"]
ds.resource.title
# => ["Comet in Moominland"]
TODO: Add asset stuff here
Go on to Lesson: Define a custom Vocabulary (AF7) or return to the Tame your RDF Metadata with ActiveFedora landing page.