hydra 10.0.0 → 10.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/doc/Dive-into-Hydra.md +60 -57
- data/doc/For-Developers.md +0 -1
- data/doc/Hackfest-ideas.md +18 -0
- data/doc/Home.md +3 -1
- data/doc/Hydra-Recipes.md +5 -1
- data/doc/LDP-Containers-for-the-perplexed.md +119 -0
- data/doc/Lesson---Adding-attached-files.md +83 -0
- data/doc/Lesson---Build-a-Codex-model-with-XML.md +272 -0
- data/doc/Lesson---Build-a-book-model-with-RDF.md +250 -0
- data/doc/Lesson---Define-Relationships-Between-Objects.md +125 -0
- data/doc/{Lesson:-Generate-Rails-Scaffolding-for-Creating-and-Editing-Books.md → Lesson---Generate-Rails-Scaffolding-for-Creating-and-Editing-Books.md} +57 -50
- data/doc/Lesson---Start-FCRepo-and-Solr.md +76 -0
- data/doc/{Lesson:-add-the-Hydra-dependencies.md → Lesson---add-the-Hydra-dependencies.md} +3 -3
- data/doc/{Lesson:-generate-a-rails-application.md → Lesson---generate-a-rails-application.md} +78 -91
- data/doc/Lesson---make-blacklight-return-search-results.md +71 -0
- data/doc/Lesson---start-the-application-&-search-for-results.md +55 -0
- data/doc/Recipe:-Add-full-text-indexing-to-your-app.md +27 -0
- data/doc/Using-rdf:resource-within-your-models.md +43 -0
- data/hydra.gemspec +1 -1
- data/lib/hydra/version.rb +1 -1
- data/script/grant_revoke_gem_authority.rb +1 -1
- metadata +18 -17
- data/doc/Lesson:-Define-Relationships-Between-Objects.md +0 -131
- data/doc/Lesson:-Reading-Hydra-rightsMetadata-XML.md +0 -87
- data/doc/Lesson:-Use-Hydra-Access-Controls-to-Control-Access-to-Blacklight-show-Pages.md +0 -37
- data/doc/Lesson:-Using-Hydra-Access-Controls-and-CanCan-to-conditionally-render-part-of-a-page.md +0 -29
- data/doc/Lesson:-adding-content-datastreams.md +0 -57
- data/doc/Lesson:-build-a-book-model.md +0 -265
- data/doc/Lesson:-install-hydra-jetty.md +0 -148
- data/doc/Lesson:-make-blacklight-return-search-results.md +0 -69
- data/doc/Lesson:-set-up-your-Rails-Application-to-use-rspec.md +0 -41
- data/doc/Lesson:-start-the-application-&-search-for-results.md +0 -29
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aed1dcdbcdfcda7120bdbdff2cd4f07b4f590c4c
|
4
|
+
data.tar.gz: 25983f2c12bdf3e5732a141d2cb1647996d1c03c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c3b32bb400ea408755552f468494588495a115762a85cb6849aecdccf749fc6edc1ea9be1981b2ab2078bb4b5961c50d2c14855e41add850ac0c4262ee19aeaa
|
7
|
+
data.tar.gz: fe7e6dcaf71c37ad11cf5f6ee2fb73793fd079a6c20da6ede157d7e857f60311c2b2e0b0381eb5738a8184c2e2bfa85480d62855a6029cc0698f26d0106a3e8a
|
data/doc/Dive-into-Hydra.md
CHANGED
@@ -1,57 +1,60 @@
|
|
1
|
-
This tutorial is tested to work with [hydra](http://rubygems.org/gems/hydra) release version
|
2
|
-
_Please update this wiki to reflect any other versions that have been tested._
|
3
|
-
|
4
|
-
# Prerequisites
|
5
|
-
|
6
|
-
This tutorial assumes that you have some basic familiarity with Ruby and Rails. If you are new to Rails, we recommend going through the [RailsBridge Tutorial](http://curriculum.railsbridge.org/intro-to-rails/) first.
|
7
|
-
|
8
|
-
A fun way to learn about the basic Rails syntax and patterns is the [Rails for Zombies](http://railsforzombies.org/) tutorial.
|
9
|
-
|
10
|
-
The tutorial also mentions using [Ruby Version Manager](http://rvm.io), a.k.a RVM. Before starting this tutorial, visit the [RVM website](http://rvm.io/) to learn about how that tool is used. RVM is not required in order to do the tutorial, but you will probably find it useful.
|
11
|
-
|
12
|
-
# System Requirements
|
13
|
-
Your system should have the following installed
|
14
|
-
+ [
|
15
|
-
+ [
|
16
|
-
+ [
|
17
|
-
+ [
|
18
|
-
|
19
|
-
|
20
|
-
*
|
21
|
-
|
22
|
-
|
23
|
-
*
|
24
|
-
*
|
25
|
-
*
|
26
|
-
*
|
27
|
-
*
|
28
|
-
*
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
1. [[Lesson
|
34
|
-
1. [[Lesson
|
35
|
-
1. [[Lesson
|
36
|
-
1. [[Lesson
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
1
|
+
This tutorial is tested to work with [hydra](http://rubygems.org/gems/hydra) release version 9.1.0
|
2
|
+
_Please update this wiki to reflect any other versions that have been tested._
|
3
|
+
|
4
|
+
# Prerequisites
|
5
|
+
|
6
|
+
This tutorial assumes that you have some basic familiarity with Ruby and Rails. If you are new to Rails, we recommend going through the [RailsBridge Tutorial](http://curriculum.railsbridge.org/intro-to-rails/) first.
|
7
|
+
|
8
|
+
A fun way to learn about the basic Rails syntax and patterns is the [Rails for Zombies](http://railsforzombies.org/) tutorial.
|
9
|
+
|
10
|
+
The tutorial also mentions using [Ruby Version Manager](http://rvm.io), a.k.a RVM. Before starting this tutorial, visit the [RVM website](http://rvm.io/) to learn about how that tool is used. RVM is not required in order to do the tutorial, but you will probably find it useful.
|
11
|
+
|
12
|
+
# System Requirements
|
13
|
+
Your system should have the following installed to successfully complete this tutorial:
|
14
|
+
+ [Ruby](http://www.ruby-lang.org/en/) >= 2.1
|
15
|
+
+ [Rubygems](http://rubygems.org/) >= 2.5.2
|
16
|
+
+ [Rails](http://rubyonrails.org/) ~> 4.2
|
17
|
+
+ [git](http://git-scm.com/)
|
18
|
+
+ [Java](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html) Development Kit >= 8
|
19
|
+
|
20
|
+
> *Note:* these requirements are specific to this tutorial, please check the Hydra README.md for additional version compatibility information.
|
21
|
+
|
22
|
+
# Goals
|
23
|
+
* Create a working Hydra Head
|
24
|
+
* Get development instances of Solr & Fedora installed and running
|
25
|
+
* Start & Stop the development instance of the Application
|
26
|
+
* Define Models for Content to put into your Hydra Head (in this case Books, Manuscripts and Pages)
|
27
|
+
* Use your Models to Create objects in Fedora and Solr
|
28
|
+
* See where content is persisted in Fedora and indexed in Solr
|
29
|
+
* Modify how metadata is indexed in Solr
|
30
|
+
* Start Using Git to Track Code Changes
|
31
|
+
|
32
|
+
# Steps/Lessons
|
33
|
+
1. [[Lesson - Generate a Rails Application]]
|
34
|
+
1. [[Lesson - Add the Hydra Dependencies]]
|
35
|
+
1. [[Lesson - Start FCRepo and Solr]]
|
36
|
+
1. [[Lesson - Start the Application & Search for Results]]
|
37
|
+
1. [[Lesson - Build a Book model with RDF]]
|
38
|
+
1. [[Lesson - Build a Codex model with XML]]
|
39
|
+
1. [[Lesson - Make Blacklight Return Search Results]]
|
40
|
+
|
41
|
+
## Bonus
|
42
|
+
You've completed the main tutorial, the following lessons can be completed in any order based on your interests:
|
43
|
+
|
44
|
+
1. [[Lesson - Define Relationships Between Objects]]
|
45
|
+
1. [[Lesson - Adding attached Files]]
|
46
|
+
1. [[Lesson - Generate Rails Scaffolding for Creating and Editing Books]]
|
47
|
+
|
48
|
+
# Next Steps
|
49
|
+
You've finished the initial Hydra tutorial and learned about setting up the basic hydra framework, building basic data models, establishing relationships between models, and modifying the basic user interface provided in a default hydra install. There is still lots more to learn. At this point, you can explore the ideas in this tutorial further by spending some time building out your models to support more complex metadata, further customizing your application views, and/or adding tests to make your applications more robust and easy to maintain.
|
50
|
+
|
51
|
+
There's lots more Hydra though, so you may want to check out the following tutorials
|
52
|
+
- [Tame Your XML With OM](https://github.com/projecthydra/om/wiki/Tame-your-XML-with-OM) shows you how to configure Hydra to parse metadata from source XML documents
|
53
|
+
- [Access Controls with Hydra](https://github.com/projecthydra/hydra-head/wiki/Access-Controls-with-Hydra) teaches you to configure roles and access rights that determine which content can be viewed by various user roles assigned to users of your repository
|
54
|
+
- Even though the information there is not specific to Hydra, [Getting Started with Rails](http://guides.rubyonrails.org/getting_started.html) is a great place to learn more about Model, View, and Controller conventions within Rails that can be applied to building your own Hydra-based repository.
|
55
|
+
|
56
|
+
You should also say hello on the [hydra-tech mailing list](https://groups.google.com/forum/?fromgroups#!forum/hydra-tech) and let us know what you're using Hydra for.
|
57
|
+
|
58
|
+
Check out the Hydra Project Website at [http://projecthydra.org](http://projecthydra.org)
|
59
|
+
|
60
|
+
![Project Hydra Logo](https://avatars3.githubusercontent.com/u/109426?v=3&s=200)
|
data/doc/For-Developers.md
CHANGED
@@ -27,7 +27,6 @@ All of our code is hosted on Github in the [projecthydra](https://github.com/pro
|
|
27
27
|
* [Steps to Defining a new Model for your Hydra Applications](https://wiki.duraspace.org/display/hydra/Steps+to+Defining+a+new+Model+for+your+Hydra+Applications)
|
28
28
|
* [ActiveFedora Console Tour] (https://github.com/projecthydra/active_fedora/wiki/Getting-Started:-Console-Tour)
|
29
29
|
* [OM documentation](https://github.com/projecthydra/om/blob/master/README.textile)
|
30
|
-
* Recommended Code Commenting Practices: think about using [YARD](http://rubydoc.info/docs/yard/file/docs/GettingStarted.md), at least provide comments that can illuminate [RDoc](http://rdoc.rubyforge.org) generated documentation
|
31
30
|
* Hydra's Bundled Jetty https://github.com/projecthydra/hydra-jetty
|
32
31
|
* [OM Terminologies in the Wild](https://wiki.duraspace.org/display/hydra/OM+Terminologies+in+the+Wild)
|
33
32
|
|
@@ -0,0 +1,18 @@
|
|
1
|
+
Here are some projects we the community could get started if we had some time to hack:
|
2
|
+
|
3
|
+
- Memory adapter for active fedora.
|
4
|
+
- AngularJS editor (replacement/substitute for hydra-editor)
|
5
|
+
- Put [Oargun](https://github.com/curationexperts/oargun) metadata into a plugin/add-on for Sufia
|
6
|
+
- Linked Data Caching - Explore Apache Stanbol maybe?
|
7
|
+
- A recipe for deploying the stack with Docker
|
8
|
+
- Service wrapper for that can startup multiple services (e.g. Solr 5, Fedora 4, Marmotta?) with one command
|
9
|
+
- Port the LDP gem to Hurley (from Faraday) https://github.com/lostisland/hurley
|
10
|
+
- Bring sufia's various metadata forms into a state of consistency / uniformity (post-upload form, single file edit, batch edit all have different UX and present fields in different orders)
|
11
|
+
- Use Raptor (https://ruby-rdf.github.io/rdf-raptor/) to speed up ActiveFedora
|
12
|
+
- Store ACLs as hash code resources. This should reduce the number of LDP requests.
|
13
|
+
|
14
|
+
|
15
|
+
Past projects:
|
16
|
+
- Extract the shared methods out of ActiveFedora::Base (Core) and ActiveFedora::File. Several commits around 24 June 2015 https://github.com/projecthydra/active_fedora/commit/bc551d68f81d9dc10f45f652cd01dba36a158897
|
17
|
+
- Replace Sufia's queuing with ActiveJob (done for Sufia 7 / CurationConcerns)
|
18
|
+
- Replace jetty_wrapper with solr_wrapper and fcrepo_wrapper (Spring 2016 dev retreat)
|
data/doc/Home.md
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# Hydra Developer Wiki
|
2
|
+
(Please feel free to edit this wiki and help make it better - if you're not sure about changes, propose them on hydra-tech@googlegroups.com first)
|
2
3
|
|
3
4
|
The projecthydra gem is a container gem which locks major version dependencies for a complete release of the hydra framework. Requiring this gem or including it in your Gemfile will load or install a coherent set of hydra gems developed and tested for interoperability. Developers requiring the most current functionality may choose to omit this gem and build their gem dependencies manually.
|
4
5
|
|
@@ -21,13 +22,14 @@ This wiki is targeted towards developers who are implementing Hydra Heads. The [
|
|
21
22
|
- [Filtering Search Results With Hydra Access Controls](https://github.com/projecthydra/hydra-head/wiki/Filtering-search-results-with-hydra-access-controls)
|
22
23
|
- [File Uploads](https://github.com/projecthydra/hydra-head/wiki/File-uploads)
|
23
24
|
- [File Downloads](https://github.com/projecthydra/hydra-head/wiki/File-downloads)
|
24
|
-
- [[Configuring Solr and Fedora]]
|
25
25
|
- [Deployment Hardware](https://wiki.duraspace.org/display/hydra/Deployment+Hardware+Information)
|
26
26
|
- [[Migration Notes]]
|
27
27
|
- [[Hydra Recipes]] - short how-to articles
|
28
|
+
- [[LDP Containers for the perplexed]]
|
28
29
|
|
29
30
|
### Reference for Hydra Contributors/Committers
|
30
31
|
|
31
32
|
If you are making changes to the hydra-head code itself, you will want to read
|
32
33
|
|
33
34
|
- [How to Contribute](https://github.com/projecthydra/hydra/blob/master/CONTRIBUTING.md)
|
35
|
+
- [[Hackfest ideas]]
|
data/doc/Hydra-Recipes.md
CHANGED
@@ -6,4 +6,8 @@
|
|
6
6
|
|
7
7
|
[[Indexing non English content]] - if you are indexing non English content into Hydra, you may want to update your Solr config to take advantage of Solr's language specific stemming capabilities.
|
8
8
|
|
9
|
-
[Uniqueness validator for ActiveFedora](https://gist.github.com/dchandekstark/f969ad21bf518c7cd3c5) - Inspired by the ActiveRecord uniqueness validator, with some limitations.
|
9
|
+
[Uniqueness validator for ActiveFedora](https://gist.github.com/dchandekstark/f969ad21bf518c7cd3c5) - Inspired by the ActiveRecord uniqueness validator, with some limitations.
|
10
|
+
|
11
|
+
[[Using rdf:resource within your models]]
|
12
|
+
|
13
|
+
[[Recipe: Add full text indexing to your app]]
|
@@ -0,0 +1,119 @@
|
|
1
|
+
This document is a summary of the basic differences between the different kind of containers that Linked Data Platform (LDP) supports.
|
2
|
+
|
3
|
+
LDP specifies three types of containers:
|
4
|
+
1. Basic Container
|
5
|
+
2. Direct Container
|
6
|
+
3. Indirect Container.
|
7
|
+
|
8
|
+
This document describes the differences between the three types of containers by showing what triples are added by an LDP Server when adding a new element to each kind of container.
|
9
|
+
|
10
|
+
In particular we assume we have a fictitious blog entry (`/blog/entry1/`) and we want to add a comment to it. We start by showing what happens if the blog entry is a Basic Container, then we show what happens if the blog entry was instead a Direct Container, and lastly if it was an Indirect Container.
|
11
|
+
|
12
|
+
This document assumes familiarity with concepts described in the LDP Spec (http://www.w3.org/TR/ldp/#ldpdc) and the examples described in the LDP Primer (http://www.w3.org/TR/ldp-primer/). If you haven't read those documents this document might not make much sense. However, if you read those documents and still have some doubts about the differences between the different kind of containers this document should help to clarify them.
|
13
|
+
|
14
|
+
|
15
|
+
## Basic Container
|
16
|
+
Assuming we have a **Basic Container** issuing an `HTTP GET /blog/entry1/` will return something like this:
|
17
|
+
|
18
|
+
</blog/entry1/> a ldp:Container .
|
19
|
+
</blog/entry1/> dc:title "First blog entry" .
|
20
|
+
|
21
|
+
To add an object to this container (for example, a comment to this blog entry) we would issue an `HTTP POST /blog/entry1` with `Slug: comment1` which will result in
|
22
|
+
|
23
|
+
1. A new resource created at `/blog/entry1/comment1`
|
24
|
+
2. A new triple (with predicate `ldp:contains`) added to `/blog/entry1/`
|
25
|
+
|
26
|
+
Issuing an `HTTP GET /blog/entry1/comment1` will return the new resource created, something like this:
|
27
|
+
|
28
|
+
</blog/entry1/comment1/> a ldp:RDFSource .
|
29
|
+
</blog/entry1/comment1/> dc:title "this is a new comment" .
|
30
|
+
|
31
|
+
Because `/blog/entry1/` is a Basic Container the LDP Server will also automatically add a new triple to it. Issuing an `HTTP GET /blog/entry1/` now returns:
|
32
|
+
|
33
|
+
</blog/entry1/> a ldp:Container .
|
34
|
+
</blog/entry1/> dc:title "First blog entry" .
|
35
|
+
</blog/entry1/> ldp:contains </blog/entry1/comments1> .
|
36
|
+
|
37
|
+
The important thing to notice is that by posting to a Basic Container, the LDP server automatically adds a triple with `ldp:contains` predicate pointing to the new resource created.
|
38
|
+
|
39
|
+
|
40
|
+
## Direct Container
|
41
|
+
An Direct Container behaves a lot like a Basic Container but with some additional features. In a Direct Container we get to specify two additional attributes that the LDP Server will use to automatically add triples to *another resource* when posting new elements to the container. The *membershipResource* attribute will let the LDP Server know the URI of this other resource and the *hasMemberRelation* will indicate the predicate these new triples will have.
|
42
|
+
|
43
|
+
Assuming `/blog/entry1/` is a **Direct Container** created with *membershipResource* `/blog/comments` and *hasMemberRelation* `hasComment`
|
44
|
+
|
45
|
+
Issuing an `HTTP GET /blog/entry1/` returns
|
46
|
+
|
47
|
+
</blog/entry1/> a ldp:DirectContainer .
|
48
|
+
</blog/entry1/> ldp:membershipResource </blog/comments> .
|
49
|
+
</blog/entry1/> ldp:hasMemberRelation hasComment .
|
50
|
+
</blog/entry1/> dc:title "First blog entry" .
|
51
|
+
|
52
|
+
Issuing an `HTTP POST /blog/entry1/` with `Slug: comment1` will result in
|
53
|
+
|
54
|
+
1. A new resource created at `/blog/entry1/comment1`
|
55
|
+
2. A new triple (predicate `ldp:contains`) added to `/blog/entry1/`
|
56
|
+
3. A new triple (predicate `hasComment`) added to `/blog/comments`
|
57
|
+
|
58
|
+
The first two items are identical to what we saw in the Basic Container example. Issuing an `HTTP GET /blog/entry1/comment1` will return the new resource created, something like this:
|
59
|
+
|
60
|
+
</blog/entry1/comment1/> a ldp:RDFSource .
|
61
|
+
</blog/entry1/comment1/> dc:title "this is a new comment" .
|
62
|
+
|
63
|
+
Issuing an `HTTP GET /blog/entry1/` will show the new triple with `ldp:contains` predicate, just like in the Basic Container example:
|
64
|
+
|
65
|
+
</blog/entry1/> a ldp:DirectContainer .
|
66
|
+
</blog/entry1/> ldp:membershipResource </blog/comments> .
|
67
|
+
</blog/entry1/> ldp:hasMemberRelation hasComment .
|
68
|
+
</blog/entry1/> ldp:contains </blog/entry1/comments1> .
|
69
|
+
|
70
|
+
The third item is what sets the Direct Container appart from the Basic Container. Issuing an `HTTP GET /blog/comments` will show also a new triple in this resource but this one with predicate `hasComment` as indicated by the `hasMembershipRelation` triple on the container:
|
71
|
+
|
72
|
+
</blog/comments> hasComment </blog/entry1/comment1>
|
73
|
+
|
74
|
+
Notice how a new triple was added to *a totally different resource*. In this case the triple was added to `/blog/comments` with predicate `hasComment` because that's what the *membershipResource* and *hasMemberRelationship* of the Direct Container specify.
|
75
|
+
|
76
|
+
One thing to notice is that the resource added to `/blog/comments` will always be the URI of the newly created resource. In our example `/blog/comments` will get a new triple pointing to `/blog/entry1/comment1`. In other words, in a Direct Container we can configure the subject and the predicate of the new triple, but not the object. [Technically speaking this is not accurate, it is possible to revert the relationship by using is predicate *isMemberOfRelation* in the Direct Container instead of *hasMemberRelation* but for the sake of simplicity I am not going to dive into that scenario in this document.]
|
77
|
+
|
78
|
+
|
79
|
+
## Indirect Container
|
80
|
+
The Indirect Container is a bit like the Direct Container but with an extra twist. In an Indirect Container we can specify the subject, predicate, *and the object* of the new triple what will be added.
|
81
|
+
|
82
|
+
Assumming `/blog/entry1/` is an **Indirect Container** created with *membershipResource* `/blog/comments`, *hasMemberRelation* `hasComment`, and *insertedContentRelation* `theComment`.
|
83
|
+
|
84
|
+
Issuing an `HTTP GET /blog/entry1/` returns
|
85
|
+
|
86
|
+
</blog/entry1/> a ldp:IndirectContainer .
|
87
|
+
</blog/entry1/> ldp:membershipResource </blog/comments> .
|
88
|
+
</blog/entry1/> ldp:hasMemberRelation hasComment .
|
89
|
+
</blog/entry1/> ldp:insertedContentRelation theComment .
|
90
|
+
</blog/entry1/> dc:title "First blog entry" .
|
91
|
+
|
92
|
+
When issuing an `HTTP POST` to an Indirect Container we need to specify some additional information for the LDP Server to be able to determine the *object* that will be used when adding the new triple to the `ldp:membershipResource`. In our particular example the body must contain an RDF triple with predicate `theComment`. For example, let's assume that we issue an `HTTP POST /blog/entry1/` with `Slug: comment1` and the following triple in the body of the POST request:
|
93
|
+
|
94
|
+
<> theComment </blog/extras/first/text> .
|
95
|
+
|
96
|
+
The result of this HTTP will be
|
97
|
+
|
98
|
+
1. A new resource created at `/blog/entry1/comment1`
|
99
|
+
2. A new triple (predicate `ldp:contains`) added to `/blog/entry1/`
|
100
|
+
3. A new triple (predicate `hasComment`, object `</blog/extras/first/text>`) added to `/blog/comments`
|
101
|
+
|
102
|
+
The first two actions are identical to what we saw in Basic Container and Direct Container so I will not elaborate on them.
|
103
|
+
|
104
|
+
The third action is what is interesting in Indirect Containers. If we issue an `HTTP GET /blog/comments` we will see that a new triple has been added to it, and it will look as follows:
|
105
|
+
|
106
|
+
</blog/comments> hasComment </blog/extras/first/text>
|
107
|
+
|
108
|
+
The subject of this triple (`/blog/comments`) and the predicate (`hasComment`) is what the *membershipResource* and the *hasMemberRelation* properties of the container indicated, similar to what we saw for Direct Containers.
|
109
|
+
|
110
|
+
However, the object of this new triple (`/blog/extras/first/text`) **is not the newly created `/blog/entry1/commment1` resource**. Instead, the object of this new triple is the object indicated in the triple with predicate `theComment` in the body of the request: `/blog/extras/first/text`.
|
111
|
+
|
112
|
+
When adding a new resource to an Indirect Container, the LDP Server looks at the body of the request for a triple with the same predicate as the *insertedContentRelation* property and picks from that triple the value to use as the object in the new triple.
|
113
|
+
|
114
|
+
## LDP PDCM In Action
|
115
|
+
Andrew Woods has posted a great tutorial that goes in more detail on how LDP containers can be used in a real life example. On [LDP-PCDM-F4 In Action](https://wiki.duraspace.org/display/FEDORA4x/LDP-PCDM-F4+In+Action) he shows how to represent the Portland Common Data Model (PCDM) using LDP in Fedora 4. His tutorial not only shows the differences between each of the containers but also provides cURL commands to create them in Fedora 4.
|
116
|
+
|
117
|
+
Andrew's tutorial also addresses reversing the triples that are created in a Direct Container (by using `ldp:isMemberOfRelation` as opposed to `ldp:hasMemberRelation`) which is something that I explicitly skipped on this document.
|
118
|
+
|
119
|
+
If you follow Andrew's tutorial with a plain-vanilla installation of Fedora 4 you might also find useful [Adam Wead scripts](https://github.com/awead/ldp-pcdm). However, if you are using an installation of Fedora via Hydra Jetty you will need to tweak the URLs provided by Andrew. You can find [here](https://github.com/hectorcorrea/ldp_pcdm_f4_in_action) the commands that I used to run his tutorial on a Fedora 4 installed via Hydra Jetty.
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# Goals
|
2
|
+
* Attaching file sub-resources to models
|
3
|
+
* See where files are stored in Fedora objects and how to retrieve them
|
4
|
+
|
5
|
+
# Explanation
|
6
|
+
|
7
|
+
So far, we've only added metadata to our objects. Let's attach a file that has some content to it. For example, for our Book model, this could be a image of the book's cover, or for the Page model, an image or pdf of the actual page.
|
8
|
+
|
9
|
+
In this case, we'll add a file where we can store a pdf of a page.
|
10
|
+
|
11
|
+
# Steps
|
12
|
+
|
13
|
+
### Step 1: Add a "pageContent" file resource to the Page model
|
14
|
+
|
15
|
+
In our Page model `app/models/page.rb`, we'll add the following line before the end of the class definition:
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
contains "pageContent"
|
19
|
+
```
|
20
|
+
|
21
|
+
Now we have a resource called "pageContent" that can hold any kind of file we wish to add to it.
|
22
|
+
|
23
|
+
**NOTE:** The order of the property, relationship, and attachment (contains) statements within the class definition is not significant. The edited version of `app/models/page.rb` should look something like the version below, but the _title_, _number_, _belongs-to-book_, and _pageContent_ statements can come in any order. We've jumbled things up for demonstration purposes - in real life, we'd probably have some convention that made the code easier to read.
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
class Page < ActiveFedora::Base
|
27
|
+
contains "pageContent"
|
28
|
+
property :text, predicate: ::RDF::URI.new('http://opaquenamespace.org/hydra/pageText'), multiple: false do |index|
|
29
|
+
index.as :stored_searchable
|
30
|
+
end
|
31
|
+
belongs_to :book, predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isPartOf
|
32
|
+
property :number, predicate: ::RDF::URI.new('http://opaquenamespace.org/hydra/pageNumber'), multiple: false do |index|
|
33
|
+
index.as :stored_searchable
|
34
|
+
index.type :integer
|
35
|
+
end
|
36
|
+
end
|
37
|
+
```
|
38
|
+
|
39
|
+
### Step 2: In the console, add a file to a Page object and save it
|
40
|
+
|
41
|
+
>*Note:* you can grab a copy of the sample file for this step by running `curl https://raw.githubusercontent.com/mark-dce/camper/master/sample-assets/AK-Page-4.pdf -o AK-Page-4.pdf` from the command line.
|
42
|
+
|
43
|
+
To add the file to one of our page objects, open up the console again:
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
> p = Page.find("test-3")
|
47
|
+
=> #<Page id: "test-3", number: 1, text: "Happy families are all alike; every unhappy family is unhappy in its own way.", book_id: "test-1">
|
48
|
+
> p.attached_files.keys
|
49
|
+
=> [:pageContent]
|
50
|
+
```
|
51
|
+
|
52
|
+
Now you're ready to add the file. Choose a file on your computer that you want to add as the "pageContent". In the lines below we're assuming that you have a file named "AK-Page-4.pdf" in the parent directory where you started the tutorial. Replace this with the correct local path for the file you want to use.
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
> p.pageContent.content = File.open("AK-Page-4.pdf")
|
56
|
+
=> #<File:../AK-Page-4.pdf>
|
57
|
+
> p.pageContent.mime_type = "application/pdf"
|
58
|
+
=> "application/pdf"
|
59
|
+
> p.pageContent.original_name = "AK-Page-4.pdf"
|
60
|
+
=> "AK-Page-4.pdf"
|
61
|
+
> p.save
|
62
|
+
=> true
|
63
|
+
> p.pageContent.uri
|
64
|
+
=> #<RDF::URI:0x3ff1d58f9bb4 URI:http://127.0.0.1:8984/rest/dev/test-3/pageContent>
|
65
|
+
```
|
66
|
+
|
67
|
+
### Step 3: See where the file was saved in Fedora
|
68
|
+
|
69
|
+
Now if you go to [[http://127.0.0.1:8984/rest/dev/test-3]], you'll see the pageContent sub-resource listed in the "children" section.
|
70
|
+
|
71
|
+
Following the links to it will allow us to view or download the file we've added.
|
72
|
+
|
73
|
+
### Step 4: Commit your changes
|
74
|
+
|
75
|
+
Now that we've added a file, it's a great time to commit to git:
|
76
|
+
|
77
|
+
```bash
|
78
|
+
git add .
|
79
|
+
git commit -m "Created a content resource"
|
80
|
+
```
|
81
|
+
|
82
|
+
# Next Step
|
83
|
+
Proceed to **BONUS** [[Lesson - Generate Rails Scaffolding for Creating and Editing Books]] or explore other [Dive into Hydra](Dive into Hydra#bonus) tutorial bonus lessons.
|
@@ -0,0 +1,272 @@
|
|
1
|
+
# Goals
|
2
|
+
* Define a simple OM (Opinionated Metadata) Terminology for Codex Metadata that will be saved as an XML file attachment to our object (formerly known as a Datastream)
|
3
|
+
* Start the Rails console and run code interactively in the console
|
4
|
+
* Create Datastream objects that use your OM Terminology
|
5
|
+
* Define an ActiveFedora Model for Codex objects
|
6
|
+
* Declare a Datastream called descMetadata on your Codex model and make it use your Codex Metadata Terminology
|
7
|
+
* Delegate methods from Codex objects to their descMetadata Datastream
|
8
|
+
* Create Codex objects that use your Codex Model
|
9
|
+
* See how an object has been indexed into Solr
|
10
|
+
* See how & where objects and metadata are stored in Fedora
|
11
|
+
* Define how your Metadata is indexed in Solr
|
12
|
+
* Re-index objects into Solr (update Solr based on any changes to an object or its Model)
|
13
|
+
|
14
|
+
# Explanation
|
15
|
+
In Fedora 4 an object can have many attachments. Fedora 4 attachments work very similarly to Fedora 3 datastreams, but are generalized to support any type of binary attachment. In this lesson, we are going to create a 'codex' object. This object will have metadata stored as an XML attachment that describes the properties of the codex. We'll call this attachment 'descMetadata'. You are free to call it whatever you like, but 'descMetadata' is a loose convention that stands for 'descriptive metadata'.
|
16
|
+
|
17
|
+
Once you've created an object and saved it in Fedora, you also want to be able to search for it in Solr. ActiveFedora and OM make it easy to get your metadata into Solr and manage if/when/how your metadata is indexed.
|
18
|
+
|
19
|
+
# Steps
|
20
|
+
|
21
|
+
### Step 1: Create an OM Terminology for Codex Metadata
|
22
|
+
|
23
|
+
First we'll create a Ruby class that represents this descriptive metadata. Make a new directory for our datastreams by typing in
|
24
|
+
```bash
|
25
|
+
$> mkdir app/models/datastreams
|
26
|
+
```
|
27
|
+
|
28
|
+
Now we'll create a file called `app/models/datastreams/codex_metadata.rb`
|
29
|
+
|
30
|
+
Paste the following code into that file:
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
class CodexMetadata < ActiveFedora::OmDatastream
|
34
|
+
|
35
|
+
set_terminology do |t|
|
36
|
+
t.root(path: "fields")
|
37
|
+
t.title
|
38
|
+
t.author
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.xml_template
|
42
|
+
Nokogiri::XML.parse("<fields/>")
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
```
|
47
|
+
|
48
|
+
This class extends from OmDatastream. OM is a gem that allows us to describe the format of an xml file and access properties. We are using OM by calling the `set_terminology` method. The xml_template method tells OM how to create a new xml document for this class.
|
49
|
+
|
50
|
+
**Tip:** If you want to learn about OM Terminologies and how they work, visit the [Tame your XML with OM](https://github.com/projecthydra/om/wiki/Tame-your-XML-with-OM) Tutorial.
|
51
|
+
|
52
|
+
### Step 2: Start the Rails console
|
53
|
+
|
54
|
+
Let's take a look at how this class works. We'll start the rails console by typing
|
55
|
+
|
56
|
+
```bash
|
57
|
+
$> rails console
|
58
|
+
```
|
59
|
+
|
60
|
+
(Or you can abbreviate this as ```rails c```.)
|
61
|
+
|
62
|
+
You should see something like `Loading development environment (Rails 4.2.0)`. Now you're in a "[REPL](http://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop)", or *interactive ruby console* that has all of your Rails application's code and configuration loaded.
|
63
|
+
|
64
|
+
### Step 3: In the console, create Datastream objects that use your OM Terminology
|
65
|
+
|
66
|
+
Let's create a new CodexMetadata instance. I've shown the expected output after each command:
|
67
|
+
|
68
|
+
```text
|
69
|
+
d = CodexMetadata.new
|
70
|
+
=> #<CodexMetadata uri="" >
|
71
|
+
d.title = "ZOIA! Memoirs of Zoia Horn, Battler for the People's Right to Know."
|
72
|
+
=> "ZOIA! Memoirs of Zoia Horn, Battler for the People's Right to Know."
|
73
|
+
d.author = "Horn, Zoia"
|
74
|
+
=> "Horn, Zoia"
|
75
|
+
puts d.to_xml
|
76
|
+
<?xml version="1.0"?>
|
77
|
+
<fields>
|
78
|
+
<title>ZOIA! Memoirs of Zoia Horn, Battler for the People's Right to Know.</title>
|
79
|
+
<author>Horn, Zoia</author>
|
80
|
+
</fields>
|
81
|
+
=> nil
|
82
|
+
```
|
83
|
+
|
84
|
+
Once you're done, exit the console by typing ```exit```
|
85
|
+
|
86
|
+
|
87
|
+
### Step 4: Define a Codex Object Model
|
88
|
+
|
89
|
+
Now let's create a model that uses this datastream. Create a new file at `app/models/codex.rb`. We'll paste in this code:
|
90
|
+
|
91
|
+
```ruby
|
92
|
+
class Codex < ActiveFedora::Base
|
93
|
+
contains 'descMetadata', class_name: 'CodexMetadata'
|
94
|
+
|
95
|
+
property :title, delegate_to: 'descMetadata', multiple: false
|
96
|
+
property :author, delegate_to: 'descMetadata', multiple: false
|
97
|
+
|
98
|
+
end
|
99
|
+
```
|
100
|
+
|
101
|
+
We've instructed our Codex model to use the CodexMetadata class to interpret XML metadata stored in a file attachment called 'descMetadata'. We're telling the model to use the descMetadata as the delegate for the properties 'title' and 'author'. We are also telling Active Fedora to treat these attributes as single values rather than as multi-valued arrays.
|
102
|
+
|
103
|
+
### Step 5: In the console, add metadata terms to your object using your OM Terminology.
|
104
|
+
|
105
|
+
Now we'll open the `rails console` again and see how to work with our codex.
|
106
|
+
|
107
|
+
```text
|
108
|
+
c = Codex.create(id: 'test-2', title: 'On the Equilibrium of Planes', author: 'Archimedes of Syracuse')
|
109
|
+
=> #<Codex id: "test-2", title: "On the Equilibrium of Planes", author: "Archimedes of Syracuse">
|
110
|
+
```
|
111
|
+
|
112
|
+
We've created a new Codex object in the repository. Because you set title and author to delegate to the descMetadata datastream, they are stored in that datastream's XML and can be accessed either through the delegated methods on the Book, or by going specifically to the datastream.
|
113
|
+
|
114
|
+
|
115
|
+
```text
|
116
|
+
c.descMetadata
|
117
|
+
=> #<CodexMetadata uri="http://127.0.0.1:8984/rest/dev/test-1/descMetadata" >
|
118
|
+
c.title
|
119
|
+
=> "On the Equilibrium of Planes"
|
120
|
+
c.author
|
121
|
+
=> "Archimedes of Syracuse"
|
122
|
+
c.descMetadata.title
|
123
|
+
=> ["On the Equilibrium of Planes"]
|
124
|
+
c.descMetadata.author
|
125
|
+
=> ["Archimedes of Syracuse"]
|
126
|
+
```
|
127
|
+
|
128
|
+
Note, because we used the `.create` method the new object was automatically saved to fedora. In general, you either need to use the `.new` method followed at some point by the `.save` OR the `.create` method to both build and save a new object. Any time you make changes to an object, you need to call `.save` on the object to make your changes persistent.
|
129
|
+
|
130
|
+
### Step 6: See what your Codex objects look like in Fedora and Solr
|
131
|
+
|
132
|
+
If we go to [[http://localhost:8984/rest/dev/test-2]] we should see what it looks like in fedora. If you followed the example and used test-2 for your codex's ID, the solr page will be [[http://localhost:8983/solr/hydra-development/select?q=test-2]] - the generic pattern looks like this: http://localhost:8983/solr/hydra-development/select?q=XXX and replace the XXX with the id from your console session. The page should look like the sample below. Note that, at this point, the `title` and `author` have not been indexed in solr. You only get fields like `system_create_dtsi`, `system_modified_dtsi`, `id`, `object_profile_ssm`, and `has_model_ssim`. In the next step we will modify our codex model to add the codex metadata to the solr document.
|
133
|
+
|
134
|
+
```xml
|
135
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
136
|
+
<response>
|
137
|
+
<lst name="responseHeader">
|
138
|
+
<int name="status">0</int>
|
139
|
+
<int name="QTime">2</int>
|
140
|
+
<lst name="params">
|
141
|
+
<str name="q">test-2</str>
|
142
|
+
</lst>
|
143
|
+
</lst>
|
144
|
+
<result name="response" numFound="1" start="0" maxScore="0.029457245">
|
145
|
+
<doc>
|
146
|
+
<date name="system_create_dtsi">2015-03-28T03:11:45Z</date>
|
147
|
+
<date name="system_modified_dtsi">2015-03-28T03:11:45Z</date>
|
148
|
+
<str name="active_fedora_model_ssi">Codex</str>
|
149
|
+
<arr name="has_model_ssim">
|
150
|
+
<str>Codex</str>
|
151
|
+
</arr>
|
152
|
+
<str name="id">test-2</str>
|
153
|
+
<arr name="object_profile_ssm">
|
154
|
+
<str>{"id":"test-2","title":"On the Equilibrium of Planes","author":"Archimedes of Syracuse"}</str>
|
155
|
+
</arr>
|
156
|
+
<long name="_version_">1496855143638892544</long>
|
157
|
+
<date name="timestamp">2015-03-28T03:11:45.868Z</date>
|
158
|
+
<float name="score">0.029457245</float>
|
159
|
+
</doc>
|
160
|
+
</result>
|
161
|
+
<lst name="facet_counts">
|
162
|
+
<lst name="facet_queries"/>
|
163
|
+
<lst name="facet_fields">
|
164
|
+
<lst name="active_fedora_model_ssi">
|
165
|
+
<int name="Codex">1</int>
|
166
|
+
</lst>
|
167
|
+
<lst name="object_type_si"/>
|
168
|
+
</lst>
|
169
|
+
<lst name="facet_dates"/>
|
170
|
+
<lst name="facet_ranges"/>
|
171
|
+
<lst name="facet_intervals"/>
|
172
|
+
</lst>
|
173
|
+
<lst name="spellcheck">
|
174
|
+
<lst name="suggestions">
|
175
|
+
<bool name="correctlySpelled">true</bool>
|
176
|
+
</lst>
|
177
|
+
</lst>
|
178
|
+
</response>
|
179
|
+
```
|
180
|
+
|
181
|
+
If you completed the RDF modeling lesson, you can see that other than the object model name, the Solr output looks identical regardless of whether we use XML or RDF to store our metadata. In the next step we will modify our CodexMetadata datastream to add the codex metadata to the solr document.
|
182
|
+
|
183
|
+
### Step 7: See how your Codex metadata are indexed into Solr
|
184
|
+
|
185
|
+
|
186
|
+
The to_solr method is what generates the solr document for your objects and their datastreams. The solr document represents the terms that will be indexed in solr for each object. To see the full solr document for the codex we created, call
|
187
|
+
|
188
|
+
```text
|
189
|
+
c.to_solr
|
190
|
+
=> {"system_create_dtsi"=>"2015-03-28T03:11:45Z", "system_modified_dtsi"=>"2015-03-28T03:11:45Z", "active_fedora_model_ssi"=>"Codex", "has_model_ssim"=>["Codex"], :id=>"test-2", "object_profile_ssm"=>"{\"id\":\"test-2\",\"title\":\"On the Equilibrium of Planes\",\"author\":\"Archimedes of Syracuse\"}"}
|
191
|
+
```
|
192
|
+
|
193
|
+
As you can see, the author and title values are included in the object profile, but they aren't being indexed as individual terms.
|
194
|
+
|
195
|
+
### Step 8: Change how your Codex metadata are indexed into Solr
|
196
|
+
|
197
|
+
To make your codex object the author and title fields, you need to reopen `app/models/codex.rb` and specify which terms you would like indexed and how:
|
198
|
+
|
199
|
+
```ruby
|
200
|
+
class Codex < ActiveFedora::Base
|
201
|
+
contains 'descMetadata', class_name: 'CodexMetadata'
|
202
|
+
|
203
|
+
property :title, delegate_to: 'descMetadata', multiple: false do |index|
|
204
|
+
index.as :stored_searchable
|
205
|
+
end
|
206
|
+
property :author, delegate_to: 'descMetadata', multiple: false do |index|
|
207
|
+
index.as :stored_searchable
|
208
|
+
end
|
209
|
+
|
210
|
+
end
|
211
|
+
```
|
212
|
+
|
213
|
+
**Note:** Because we have made changes to our Ruby code that we want to use, we need to reload all of the code, including our latest changes. There are two methods to do this:
|
214
|
+
* Exit and restart the rails console: `exit` the rails console followed by `rails c` from the shell prompt
|
215
|
+
* Reload the application code by calling `reload!` from within the rails console itself.
|
216
|
+
|
217
|
+
So, **restart the rails console** using either method and we can load the object we previously created:
|
218
|
+
|
219
|
+
```text
|
220
|
+
c = Codex.find('test-2')
|
221
|
+
=> #<Codex id: "test-2", title: "On the Equilibrium of Planes", author: "Archimedes of Syracuse">
|
222
|
+
```
|
223
|
+
|
224
|
+
Check and see that to_solr includes the title and author fields.
|
225
|
+
|
226
|
+
```text
|
227
|
+
c.to_solr
|
228
|
+
=> {"system_create_dtsi"=>"2015-03-28T03:11:45Z", "system_modified_dtsi"=>"2015-03-28T03:11:45Z", "active_fedora_model_ssi"=>"Codex", "has_model_ssim"=>["Codex"], :id=>"test-2", "object_profile_ssm"=>"{\"id\":\"test-2\",\"title\":\"On the Equilibrium of Planes\",\"author\":\"Archimedes of Syracuse\"}", "title_tesim"=>["On the Equilibrium of Planes"], "author_tesim"=>["Archimedes of Syracuse"]}
|
229
|
+
```
|
230
|
+
Now when you call `.to_solr` on a codex it returns a solr document with fields named `title_tesim` and `author_tesim` that contain your title and author values. Those are the field names that we will add to Blacklight's queries in [[Lesson - Make Blacklight Return Search Results]].
|
231
|
+
|
232
|
+
|
233
|
+
### Step 9: Re-index an object in Solr
|
234
|
+
|
235
|
+
Now we'll call the `update_index` method, which republishes the Solr document using the changes we've made.
|
236
|
+
|
237
|
+
```text
|
238
|
+
c.update_index
|
239
|
+
=> {"responseHeader"=>{"status"=>0, "QTime"=>44}}
|
240
|
+
```
|
241
|
+
|
242
|
+
If you refresh the document result from solr ([[http://localhost:8983/solr/hydra-development/select?q=test-2]]) you should see that these fields have been added to the solr_document:
|
243
|
+
|
244
|
+
```xml
|
245
|
+
<arr name="title_tesim">
|
246
|
+
<str>On the Equilibrium of Planes</str>
|
247
|
+
</arr>
|
248
|
+
<arr name="author_tesim">
|
249
|
+
<str>Archimedes of Syracuse</str>
|
250
|
+
</arr>
|
251
|
+
|
252
|
+
```
|
253
|
+
|
254
|
+
**Aside:** The strange suffixes on the field names are provided by [solrizer](http://github.com/projecthydra/solrizer). You can read about them in the [solrizer documentaton](https://github.com/projecthydra/hydra-head/wiki/Solr-Schema). In short, the **_tesim** suffix tells Solr to treat the values as _**t**ext_ in the _**e**nglish_ language that should be _**s**tored_, _**i**ndexed_ and allowed to be _**m**ultivalued_. This _tesim suffix is a useful catch-all that gets your searches working predictably with minimal fuss. As you encounter cases where you need to index your content in more nuanced ways, there are ways to change these suffixes in order to achieve different results in Solr.
|
255
|
+
|
256
|
+
#### Why doesn't the Book show up in Blacklight?
|
257
|
+
|
258
|
+
Now your object is indexed properly, but it **still won't show up in Blacklight's search results** until you've turned off access controls and added the appropriate fields to Blacklight's queries. We cover those in the next lesson.
|
259
|
+
|
260
|
+
### Step 10: Commit your changes
|
261
|
+
|
262
|
+
Now that we've got our model working, it's a great time to commit to git:
|
263
|
+
|
264
|
+
```text
|
265
|
+
git add .
|
266
|
+
git commit -m "Create a codex model and a datastream"
|
267
|
+
```
|
268
|
+
|
269
|
+
# Next Step
|
270
|
+
Go on to [[Lesson - Make Blacklight Return Search Results]] or return to the [[Dive into Hydra]] page.
|
271
|
+
|
272
|
+
If you want to learn about OM Terminologies and how they work, visit the [Tame your XML with OM](https://github.com/projecthydra/om/wiki/Tame-your-XML-with-OM) Tutorial.
|