hydra 6.2.0.rc1 → 6.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +0 -1
- data/CONTRIBUTING.md +3 -0
- data/RELEASE-POLICY.md +40 -0
- data/doc/Configuring-solr-and-fedora.md +16 -0
- data/doc/Content-Type-Example:-Journal-Article.textile +735 -0
- data/doc/Dive-into-Hydra.md +62 -0
- data/doc/Filtering-search-results-with-hydra-access-controls.md +16 -0
- data/doc/For-Developers.md +47 -0
- data/doc/Home.md +33 -0
- data/doc/Lesson:-Define-Relationships-Between-Objects.md +127 -0
- data/doc/Lesson:-Generate-Rails-Scaffolding-for-Creating-and-Editing-Books.md +167 -0
- data/doc/Lesson:-Reading-Hydra-rightsMetadata-XML.md +87 -0
- data/doc/Lesson:-Use-Hydra-Access-Controls-to-Control-Access-to-Blacklight-show-Pages.md +37 -0
- data/doc/Lesson:-Using-Hydra-Access-Controls-and-CanCan-to-conditionally-render-part-of-a-page.md +29 -0
- data/doc/Lesson:-add-the-Hydra-dependencies.md +28 -0
- data/doc/Lesson:-adding-content-datastreams.md +60 -0
- data/doc/Lesson:-build-a-book-model.md +262 -0
- data/doc/Lesson:-create-a-git-repository.md +35 -0
- data/doc/Lesson:-generate-a-rails-application.md +53 -0
- data/doc/Lesson:-install-hydra-jetty.md +57 -0
- data/doc/Lesson:-make-blacklight-return-search-results.md +47 -0
- data/doc/Lesson:-run-the-Hydra-generator.md +39 -0
- data/doc/Lesson:-set-up-your-Rails-Application-to-use-rspec.md +41 -0
- data/doc/Lesson:-start-jetty.md +85 -0
- data/doc/Lesson:-start-the-application-&-search-for-results.md +43 -0
- data/doc/Lesson:-turn-off-access-controls.md +37 -0
- data/doc/Migrating-to-Hydra-6.2.md +12 -0
- data/doc/Migration-Notes.md +2 -0
- data/doc/Models---Defining-a-Custom-Hydra-Model.textile +198 -0
- data/doc/Rake-Tasks-in-Hydra-Head.textile +40 -0
- data/doc/Reference.textile +19 -0
- data/doc/Solr-Schema.rdoc +44 -0
- data/doc/Tools-for-Developing-and-Testing-your-Application.textile +69 -0
- data/doc/YOUR-Hydra-Application---Initial-Modifications.textile +357 -0
- data/lib/hydra/version.rb +1 -1
- metadata +35 -4
@@ -0,0 +1,12 @@
|
|
1
|
+
- `Rubydora::Repository#next_pid` has been superseded by `Rubydora::Repository#mint`.
|
2
|
+
|
3
|
+
Example:
|
4
|
+
|
5
|
+
```ruby
|
6
|
+
Nokogiri::XML(ActiveFedora::Base.connection_for_pid(0).next_pid(pid_opts)).at_xpath('//xmlns:pid').text
|
7
|
+
```
|
8
|
+
should be:
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
ActiveFedora::Base.connection_for_pid('0').mint(pid_opts)
|
12
|
+
```
|
@@ -0,0 +1,198 @@
|
|
1
|
+
h1. Models - Defining a Custom Hydra Model
|
2
|
+
|
3
|
+
h2. General Introduction/Tutorial
|
4
|
+
|
5
|
+
The "Getting Started Building Your Own Hydra Application":https://github.com/projecthydra/hydra-head/wiki/How-to-Get-Started tutorial includes a detailed section on defining a JournalArticle model. Read that to get a sense of how to create a working Hydra Model.
|
6
|
+
|
7
|
+
h2. Steps to Defining Your Model
|
8
|
+
|
9
|
+
These steps assume you have gone through the basic Hydra app setup and are familiar with its general workings. In order to create a custom model, you'll need to know how to create your OM terminology if you have a specific XML schema you want to use, or work with an existing OM terminology if one of the ones included with Hydra is sufficient.
|
10
|
+
|
11
|
+
Additionally, you'll also need to know how to write rspec tests using fixtures, and have a working knowledge of the Fedora object relationship model. For help with rspec tests, it's best use the code found in Hydra-Head as examples. You can copy the tests for Hydra's models into your own application and modify them to test your particular model. For more information about Fedora, see: "Fedora Wiki":https://wiki.duraspace.org/display/FEDORA/Home
|
12
|
+
|
13
|
+
Here is a basic overview of the steps involved:
|
14
|
+
|
15
|
+
# Pick your xml schema(s)
|
16
|
+
# Create "fixtures" in XML for your schema(s)
|
17
|
+
# Define or reuse OM terminologies & datastream classes for your XML
|
18
|
+
# Write rspec tests for your catastream classes
|
19
|
+
# Define the model
|
20
|
+
# Write rspec tests for your model
|
21
|
+
# Decide what relationships your model will have & which predicates to use
|
22
|
+
# Add relationship methods to your model
|
23
|
+
# Define a rightsMetadata datastream for your objects
|
24
|
+
# Setup depositor/owner permissions
|
25
|
+
# Define additional default permissions if needed
|
26
|
+
# Define delegate terms
|
27
|
+
|
28
|
+
h2. rightsMetadata and Depositor/Owner Permissions
|
29
|
+
|
30
|
+
Two steps are necessary in order to ensure that your controllers will be able to set the correct permissions on your assets. If you don't follow these steps, users will be able to create objects but won't be able to edit them.
|
31
|
+
|
32
|
+
Before reading this, make sure to read the page on "Hydra Access Controls":https://github.com/projecthydra/hydra-head/wiki/Access-Controls
|
33
|
+
|
34
|
+
h3. Ensuring objects have a rightsMetadata datastream
|
35
|
+
|
36
|
+
If you are adhering to the formal Hydra commonMetadata cModel which says that you must have a descMetadata datastream and a rightsMetadata datastream, you can put this line in your model:
|
37
|
+
|
38
|
+
<pre>
|
39
|
+
# This model adheres to the formal Hydra commonMetadata cModel, meaning that it has a descMetadata datastream and a rightsMetadata datastream
|
40
|
+
include Hydra::ModelMixins::CommonMetadata
|
41
|
+
</pre>
|
42
|
+
|
43
|
+
If you are not adhering to the formal Hydra commonMetadata cModel and simply want to have a rightsMetadata datastream, declare the datastream directly in your Model
|
44
|
+
|
45
|
+
<pre>
|
46
|
+
# Explicitly declaring rightsMetadata datastream
|
47
|
+
has_metadata :name => "rightsMetadata", :type => Hydra::RightsMetadata
|
48
|
+
</pre>
|
49
|
+
|
50
|
+
h3. Using Hydra::ModelMethods
|
51
|
+
|
52
|
+
{Hydra::ModelMethods} will provide the {Hydra::ModelMethods#apply_depositor_metadata} method to your models. This ensures that any controller operating on your models can grant a user edit permissions on the objects he or she creates. When the user logs into the Hydra application, their login (ie. archivist1@example.com) will be added to the to the rightsMetadata datastream, giving them edit access.
|
53
|
+
|
54
|
+
You might want to override this with a method that including additional tasks more specific to your model. If you decide to do this, the most important behavior to retain is adding +depositor_id+ to the asset's individual edit permissions if the asset has a rightsMetadata datastream.
|
55
|
+
|
56
|
+
To add the method to your model, simply add this code to your model:
|
57
|
+
<pre>
|
58
|
+
include Hydra::ModelMethods
|
59
|
+
</pre>
|
60
|
+
|
61
|
+
h3. Applying other default permissions
|
62
|
+
|
63
|
+
Using Hydra's system of access controls, you can give newly created objects a default set of group permissions. If you are using apply_depositor_metadata correctly, the depositor will have access to the item, but what if you want to grant other people access to the object based on their group membership?
|
64
|
+
|
65
|
+
In that case, you can use the after_create hook in your model to run a method that applies some default permissions to your objects when they are created. Either in the model code itself or in a separate file that you can include later, create a method called apply_default_permissions:
|
66
|
+
|
67
|
+
<pre>
|
68
|
+
def apply_default_permissions
|
69
|
+
self.datastreams["rightsMetadata"].update_permissions( "group"=>{"archivist"=>"edit"} )
|
70
|
+
self.datastreams["rightsMetadata"].update_permissions( "group"=>{"reviewer"=>"edit"} )
|
71
|
+
self.datastreams["rightsMetadata"].update_permissions( "group"=>{"donor"=>"read"} )
|
72
|
+
self.save
|
73
|
+
end
|
74
|
+
</pre>
|
75
|
+
|
76
|
+
This method will grant edit privileges to the archivist and reviewer groups, while anyone in the donor group will have read access. These groups and their members are defined in the config/role_mapper_*.yml files. There will be one role mapper file for each of the Rails environments: development, test and production. For example, if your role_mapper_production.yml file contains:
|
77
|
+
|
78
|
+
<pre>
|
79
|
+
archivist:
|
80
|
+
- archivist1@example.com
|
81
|
+
donor:
|
82
|
+
- donor1@example.com
|
83
|
+
reviewer:
|
84
|
+
- reviewer1@example.com
|
85
|
+
researcher:
|
86
|
+
- researcher1@example.com
|
87
|
+
patron:
|
88
|
+
- patron1@example.com
|
89
|
+
</pre>
|
90
|
+
|
91
|
+
The archivist1 and reviewer1 users will have edit access to all objects, by default, as well as donor1 who will have read access to all objects. The patron1 user will not have any access unless it specifically granted via the Hydra web application.
|
92
|
+
|
93
|
+
h3. Defining delegate terms
|
94
|
+
|
95
|
+
The last step in creating your model will be to define delegate terms to each of the fields you want to use in your model. Delegate terms allow your views and controllers to interact directly with the terms you've defined in OM. You will need to have a delegate defined for every term you want to use in a view. If you have terms in your OM definition that are not needed at the view level, then you won't need to create delegates for them; however, it is advisable to create delegates for any OM term that needs to be displayed or edited in any way.
|
96
|
+
|
97
|
+
h2. Putting it all together
|
98
|
+
|
99
|
+
Using these above examples and expanding upon the JournalArticle model that is used in the "content type example":https://github.com/projecthydra/hydra-head/wiki/Content-Type-Example:-Journal-Article, we can construct a more advanced Hydra model:
|
100
|
+
|
101
|
+
<pre>
|
102
|
+
class JournalArticle < ActiveFedora::Base
|
103
|
+
include Hydra::ModelMethods
|
104
|
+
include Hydra::ModelMixins::CommonMetadata
|
105
|
+
include ActiveFedora::Relationships
|
106
|
+
|
107
|
+
has_relationship "objects", :is_part_of, :inbound => true
|
108
|
+
|
109
|
+
after_create :apply_default_permissions
|
110
|
+
|
111
|
+
has_metadata :name => "descMetadata", :type => JournalArticleModsDatastream
|
112
|
+
has_metadata :name => "properties", :type => MyApp::MyProperties
|
113
|
+
|
114
|
+
delegate :title, :to=> :descMetadata, :unique=>"true"
|
115
|
+
delegate :abstract, :to=> :descMetadata, :unique=>"true"
|
116
|
+
delegate :start_page, :to=> :descMetadata
|
117
|
+
delegate :end_page, :to=> :descMetadata
|
118
|
+
delegate :publication_date, :to=> :descMetadata
|
119
|
+
delegate :journal_title, :to=> :descMetadata
|
120
|
+
delegate :journal_volume, :to=> :descMetadata
|
121
|
+
delegate :journal_issue, :to=> :descMetadata
|
122
|
+
delegate :depositor, :to=> :properties
|
123
|
+
|
124
|
+
def apply_depositor_metadata(depositor_id)
|
125
|
+
self.depositor = depositor_id
|
126
|
+
super
|
127
|
+
end
|
128
|
+
|
129
|
+
def apply_default_permissions
|
130
|
+
self.datastreams["rightsMetadata"].update_permissions( "group"=>{"archivist"=>"edit"} )
|
131
|
+
self.datastreams["rightsMetadata"].update_permissions( "group"=>{"reviewer"=>"edit"} )
|
132
|
+
self.datastreams["rightsMetadata"].update_permissions( "group"=>{"donor"=>"read"} )
|
133
|
+
self.save
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
</pre>
|
138
|
+
|
139
|
+
h3. Explanation
|
140
|
+
|
141
|
+
The first three include statements add in some basic features to our model. Hydra::ModelMethods gives us the apply_depositor_metadata method and Hydra::ModelMixins::CommonMetadata gives us the rightsMetadata dastastream. Remember that since we've included the mixin here, we don't need to define the datastream like we do the others. The last include statement adds in ActiveFedora::Relationships which allows us to assert relationships with other objects. This would be useful in a scenario where we have a JournalPage model defined and each journal page needs to claim it's parent object as a JournalArticle. ActiveFedora lets us do this using the RELS-EXT datastream in Fedora. Note that there is no JournalPage model defined anywhere. If you want a model to assert a relationship to JournalArticle, then you're going to have to create it. Once you have that model defined, then you can add the next line, has_relationship, which defines an inbound relationship where objects can assert a relationship to our JournalArtical model.
|
142
|
+
|
143
|
+
The line after this uses our custom apply_default_permissions method. Note that this is completely optional and not required in order for your Hydra models to work. It's just an example of how you can use Rails hooks to add extra functionality to your models. The apply_default_permissions method is defined at the bottom of the model.
|
144
|
+
|
145
|
+
Next we define our datastreams. We're using two, the JournalArticleModsDatastream that is defined in the "Content-Type-Example:-Journal-Article" example, and a second sample datastream that we're calling MyApp::MyProperties. This assumes we have created an OM definition for this datastream. We could use it here to store additional information about the object that does not belong in descMetadata.
|
146
|
+
|
147
|
+
Following our datastreams is a section with our delegate definitions. These map terms from each of our OM terminologies to fields in our model that will eventually translated to fields that we can interact with our views. As you can see, there is a delegate for each term in descMetadata, which uses our JournalArticleModsDatastream, and one additional delegate for a term called "depositor" which is mapped to our properties datastream using the sample MyApp::MyProperties terminology.
|
148
|
+
|
149
|
+
Finally, there are two methods. The first, apply_depositor_metadata, overrides the method found in Hydra::ModelMethods with one additional step. In this case, we're going to store the depositor_id in our properties datastream for later use. After that, we want everything to proceed as normal and call "super" so that the rest of the method executes as it should according to Hydra's use.
|
150
|
+
|
151
|
+
The last method is called using the after_create hook which applies some default permissions to our objects.
|
152
|
+
|
153
|
+
h2. DRY it up
|
154
|
+
|
155
|
+
One last little tweak. If we wanted to share our custom methods with some of our other yet-to-be-define models, we could break out these methods to a separate file:
|
156
|
+
|
157
|
+
<pre>
|
158
|
+
module MyApp::MyModelMethods
|
159
|
+
|
160
|
+
def apply_depositor_metadata(depositor_id)
|
161
|
+
self.depositor = depositor_id
|
162
|
+
super
|
163
|
+
end
|
164
|
+
|
165
|
+
def apply_default_permissions
|
166
|
+
self.datastreams["rightsMetadata"].update_permissions( "group"=>{"archivist"=>"edit"} )
|
167
|
+
self.datastreams["rightsMetadata"].update_permissions( "group"=>{"reviewer"=>"edit"} )
|
168
|
+
self.datastreams["rightsMetadata"].update_permissions( "group"=>{"donor"=>"read"} )
|
169
|
+
self.save
|
170
|
+
end
|
171
|
+
|
172
|
+
end
|
173
|
+
</pre>
|
174
|
+
|
175
|
+
We then remove the method definitions from our model and our include statement then look like:
|
176
|
+
|
177
|
+
<pre>
|
178
|
+
include Hydra::ModelMethods
|
179
|
+
include Hydra::ModelMixins::CommonMetadata
|
180
|
+
include ActiveFedora::Relationships
|
181
|
+
include MyApp::MyModelMethods
|
182
|
+
</pre>
|
183
|
+
|
184
|
+
We now have a module of code that can be included with our other custom models at will, just like we may include additional Hydra functions by adding additional include statements.
|
185
|
+
|
186
|
+
h2. Other Topics
|
187
|
+
|
188
|
+
h3. OM
|
189
|
+
* namespaces
|
190
|
+
* Indexing
|
191
|
+
** index_as
|
192
|
+
** suppressing fields
|
193
|
+
** advanced indexing with custom solr schemas (:displayable and :searchable)
|
194
|
+
* retrieving Terms & Values
|
195
|
+
|
196
|
+
h2. More Information
|
197
|
+
|
198
|
+
Further questions? Ask the "hydra-tech list":http://groups.google.com/group/hydra-tech or join the freenode #projecthydra IRC channel.
|
@@ -0,0 +1,40 @@
|
|
1
|
+
This guide is known to work with hydra-head _version 6.0.0_.
|
2
|
+
_Please update this wiki to reflect any other versions that have been tested._
|
3
|
+
|
4
|
+
h2. Getting info about the rake tasks from the command line
|
5
|
+
|
6
|
+
<pre>rake -T</pre>
|
7
|
+
|
8
|
+
To narrow down the output, use grep. For example:
|
9
|
+
|
10
|
+
<pre>rake -T | grep hy</pre>
|
11
|
+
|
12
|
+
|
13
|
+
h2. hydra:jetty Tasks
|
14
|
+
|
15
|
+
_Prerequisite:_ You must have the following lines in your Gemfile
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
gem 'hydra-head'
|
19
|
+
gem 'jettywrapper'
|
20
|
+
```
|
21
|
+
|
22
|
+
h3. The main tasks: load, start, stop
|
23
|
+
|
24
|
+
<pre>
|
25
|
+
rake hydra:jetty:load # Copies the default SOLR config files and starts up the fedora instance.
|
26
|
+
</pre>
|
27
|
+
|
28
|
+
<pre>
|
29
|
+
rake jetty:start # Starts the bundled Hydra Testing Server
|
30
|
+
rake jetty:stop # Stops the bundled Hydra Testing Server
|
31
|
+
</pre>
|
32
|
+
|
33
|
+
h3. Subtasks: config, config_fedora, config_solr
|
34
|
+
|
35
|
+
<pre>
|
36
|
+
rake hydra:jetty:config # Copies the default Solr & Fedora configs into the bundled Hydra Testing Server
|
37
|
+
rake hydra:jetty:config_fedora # Copies a custom fedora config for the bundled Hydra Testing Server
|
38
|
+
rake hydra:jetty:config_solr # Copies the default SOLR config for the bundled Hydra Testing Server
|
39
|
+
</pre>
|
40
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
See the github wikis for information targeted to developers: "http://github.com/projecthydra/hydra-head/wiki":http://github.com/projecthydra/hydra-head/wiki
|
2
|
+
See the duraspace hydra wikis for information at the architecture level: "http://github.com/projecthydra/hydra-head/wiki":http://github.com/projecthydra/hydra-head/wiki
|
3
|
+
Additionally, new adopters and potential adopters may find the pages here useful: "http://projecthydra.org/":http://projecthydra.org/
|
4
|
+
|
5
|
+
Further questions? Ask the hydra-tech list or join the freenode #projecthydra IRC channel.
|
6
|
+
|
7
|
+
h2. API Docs
|
8
|
+
|
9
|
+
"ActiveFedora API Docs":http://rdoc.info/github/projecthydra/active_fedora
|
10
|
+
"OM API Docs":http://rdoc.info/github/projecthydra/om
|
11
|
+
"Solrizer-Fedora API Docs":http://rdoc.info/github/projecthydra/solrizer-fedora
|
12
|
+
"Solrizer API Docs":http://rdoc.info/github/projecthydra/solrizer
|
13
|
+
|
14
|
+
h2. Tutorials
|
15
|
+
|
16
|
+
"ActiveFedora Console Tour":https://github.com/projecthydra/active_fedora/wiki/Getting-Started%3A-Console-Tour
|
17
|
+
"OM-based NokogiriDatastreams":https://github.com/projecthydra/active_fedora/wiki/Nokogiri-Datastreams
|
18
|
+
"Hydra-Head wiki pages":https://github.com/projecthydra/hydra-head/wiki/_pages
|
19
|
+
|
@@ -0,0 +1,44 @@
|
|
1
|
+
== Dynamic Field Conventions
|
2
|
+
The solr schema as found in schema.xml uses a convention with dynamic field names to expose the Solr properties of the field. The following abbreviations are concatenated into the suffix:
|
3
|
+
|
4
|
+
* Solr field type abbreviations
|
5
|
+
* t for text (language independent)
|
6
|
+
* te for English text
|
7
|
+
* s for string
|
8
|
+
* i for integer
|
9
|
+
* dt for date
|
10
|
+
* l for long
|
11
|
+
* db for double
|
12
|
+
* f for float
|
13
|
+
* b for boolean
|
14
|
+
* ll for location (think lat-lon)
|
15
|
+
* trie types are for faster range queries. The t follows the solr field type abbreviation
|
16
|
+
* it for trie integer
|
17
|
+
* dtt for trie date
|
18
|
+
* lt for trie long
|
19
|
+
* dbt for trie double
|
20
|
+
* ft for trie float
|
21
|
+
* Solr field properties abbreviations
|
22
|
+
* s if stored
|
23
|
+
* i if indexed
|
24
|
+
* m if multiValued
|
25
|
+
* v if termVectors (with termPositions and termOffsets also set to true)
|
26
|
+
|
27
|
+
Examples:
|
28
|
+
|
29
|
+
<!-- text (_t...) -->
|
30
|
+
<dynamicField name="*_ti" type="text" stored="false" indexed="true" multiValued="false"/>
|
31
|
+
<dynamicField name="*_tim" type="text" stored="false" indexed="true" multiValued="true"/>
|
32
|
+
<dynamicField name="*_ts" type="text" stored="true" indexed="false" multiValued="false"/>
|
33
|
+
<dynamicField name="*_tsm" type="text" stored="true" indexed="false" multiValued="true"/>
|
34
|
+
<dynamicField name="*_tsi" type="text" stored="true" indexed="true" multiValued="false"/>
|
35
|
+
<dynamicField name="*_tsim" type="text" stored="true" indexed="true" multiValued="true"/>
|
36
|
+
<dynamicField name="*_tiv" type="text" stored="false" indexed="true" multiValued="false" termVectors="true" termPositions="true" termOffsets="true"/>
|
37
|
+
<dynamicField name="*_timv" type="text" stored="false" indexed="true" multiValued="true" termVectors="true" termPositions="true" termOffsets="true"/>
|
38
|
+
<dynamicField name="*_tsiv" type="text" stored="true" indexed="true" multiValued="false" termVectors="true" termPositions="true" termOffsets="true"/>
|
39
|
+
<dynamicField name="*_tsimv" type="text" stored="true" indexed="true" multiValued="true" termVectors="true" termPositions="true" termOffsets="true"/>
|
40
|
+
|
41
|
+
<!-- string (_s...) -->
|
42
|
+
<dynamicField name="*_si" type="string" stored="false" indexed="true" multiValued="false"/>
|
43
|
+
<dynamicField name="*_sim" type="string" stored="false" indexed="true" multiValued="true"/>
|
44
|
+
...
|
@@ -0,0 +1,69 @@
|
|
1
|
+
h1. Tools for Developing and Testing your Application
|
2
|
+
|
3
|
+
h2. Hydra-Jetty
|
4
|
+
|
5
|
+
The Hydra project provides a copy of Jetty (a java web server) with Fedora and Solr pre-installed. This is useful for running tests and for running your own code in your sandbox while you're actively working on your hydra head.
|
6
|
+
|
7
|
+
The hydra-head gem provides a rake task for installing hydra-jetty
|
8
|
+
|
9
|
+
<pre>
|
10
|
+
rails g hydra:jetty
|
11
|
+
</pre>
|
12
|
+
|
13
|
+
*Important*: To apply your application's solrconfig.xml and schema.xml to the copy of Solr in hydra-jetty, run this:
|
14
|
+
|
15
|
+
<pre>
|
16
|
+
rake hydra:jetty:config
|
17
|
+
</pre>
|
18
|
+
|
19
|
+
Now you're ready to start jetty. We've written a useful gem that gives you rake tasks for starting and stopping jetty. Make sure you have jettywrapper in your Gemfile, available for both development and test environments:
|
20
|
+
|
21
|
+
<pre>
|
22
|
+
group :development, :test do
|
23
|
+
gem "jettywrapper"
|
24
|
+
end
|
25
|
+
</pre>
|
26
|
+
|
27
|
+
If you just added it, then run <pre>bundle install</pre>
|
28
|
+
|
29
|
+
Jettywrapper is now installed:
|
30
|
+
|
31
|
+
*To start jetty*: <pre>rake jetty:start</pre>
|
32
|
+
*To stop jetty*: <pre>rake jetty:stop</pre>
|
33
|
+
|
34
|
+
For more information about using jettywrapper, see http://hudson.projecthydra.org/job/jettywrapper/Documentation/
|
35
|
+
|
36
|
+
h2. RSpec and Cucumber for Testing
|
37
|
+
|
38
|
+
We STRONGLY recommend that you write tests for every local change you make. This will allow you to ensure that upgrading the core code doesn't break any local changes you have made.
|
39
|
+
|
40
|
+
A common question: when should it be a cucumber feature rather than a spec?
|
41
|
+
very basic rule: if it's testing something created with view, use a cucumber feature to test. If it's not created by view code, use a spec to test.
|
42
|
+
|
43
|
+
h4. RSpec for Functional Tests
|
44
|
+
|
45
|
+
Most Ruby projects use either RSpec or Shoulda to write and run their Functional Tests. We use RSpec for all of the Hydra software.
|
46
|
+
|
47
|
+
To set up all the files you need to use rspec to test your Rails application, simply run the rspec generator. This will create a directory called "spec" and put all of the necessary files into it.
|
48
|
+
|
49
|
+
<pre>
|
50
|
+
rails g rspec:install
|
51
|
+
</pre>
|
52
|
+
|
53
|
+
h4. Cucumber to Test User Experience
|
54
|
+
|
55
|
+
If you will be writing cucumber tests, make sure you have the cucumber gem installed (in your test group in your Gemfile, then bundle install).
|
56
|
+
|
57
|
+
<pre>
|
58
|
+
group :test do
|
59
|
+
gem 'rspec-rails', '>=2.9.0'
|
60
|
+
gem "cucumber-rails"
|
61
|
+
gem "database_cleaner"
|
62
|
+
end
|
63
|
+
</pre>
|
64
|
+
|
65
|
+
(The database_cleaner gem is used by cucumber-rails when a database is involved.)
|
66
|
+
|
67
|
+
Then run the cucumber generator. This will create a directory called "features" and populate it with all the basic parts you need to run Cucumber tests on your Rails application.
|
68
|
+
|
69
|
+
<pre>rails g cucumber:install</pre>
|
@@ -0,0 +1,357 @@
|
|
1
|
+
h1. YOUR Hydra Application - Initial Modifications
|
2
|
+
|
3
|
+
This document explains how to make two basic changes to your hydra rails application and how to write the appropriate tests for them.
|
4
|
+
|
5
|
+
h2. What you will learn from this document:
|
6
|
+
|
7
|
+
# How to Change the Home Page Text for Your Hydra Application
|
8
|
+
# How to Change the Rails Application Name of Your Hydra Application
|
9
|
+
# How to Change the Facets displayed for Limiting your Search
|
10
|
+
# How to Override a Helper Method
|
11
|
+
# How to Write a Simple Spec (an RSpec test)
|
12
|
+
# How to Write a Simple Cucumber Feature
|
13
|
+
|
14
|
+
Terminology note: the Hydra and Blacklight gems are engines plugins for Rails applications.
|
15
|
+
|
16
|
+
h4. The Vanilla, Freshly Created Hydra Application
|
17
|
+
|
18
|
+
By following the instructions of the "README":https://github.com/projecthydra/hydra-head/blob/master/README.textile, "Getting Started":https://github.com/projecthydra/hydra-head/wiki/How-to-Get-Started and so on, you should have gotten to a running rails application, with the default rails home page.
|
19
|
+
|
20
|
+
h2. Making local changes to your Hydra Application
|
21
|
+
|
22
|
+
In order to make it easy to get any new functionality added to the hydra stack (see "README":http://hudson.projecthydra.org/job/hydra-head-rails3-plugin/Documentation/file.README.html), while retaining your Hydra application's localizations, your local hydra application code should be set up to override the upstream Hydra stack code.
|
23
|
+
|
24
|
+
Luckily, rails engines has made this easy - the Hydra code is organized so your localizations are kept separate from the core hydra application code.
|
25
|
+
|
26
|
+
Moreover, to ensure your localizations won't be broken by upgrading the Hydra core code, you should have tests for all your localizations.
|
27
|
+
|
28
|
+
The two key points:
|
29
|
+
|
30
|
+
<b>
|
31
|
+
# always write tests for your local modifications
|
32
|
+
# always change code at the app level, and never change anything in vendor/plugins.
|
33
|
+
</b>
|
34
|
+
|
35
|
+
h3. Easy Changes for Practice.
|
36
|
+
|
37
|
+
h2. Changing the Home Text (also demonstrates Writing a Feature and Overriding a View)
|
38
|
+
|
39
|
+
The home text is set in a view partial, so a cucumber feature is the most appropriate test (rather than an rspec test).
|
40
|
+
|
41
|
+
h4. (1) Write the test.
|
42
|
+
|
43
|
+
Create a file "features/home_page.feature" containing this:
|
44
|
+
|
45
|
+
<pre>
|
46
|
+
Feature: Homepage
|
47
|
+
I want the home page to reflect localizations properly
|
48
|
+
</pre>
|
49
|
+
|
50
|
+
A test for checking the home text might be inserted like so:
|
51
|
+
|
52
|
+
<pre>
|
53
|
+
Feature: Homepage
|
54
|
+
I want the home page to reflect localizations properly
|
55
|
+
|
56
|
+
Scenario: home page text
|
57
|
+
When I am on the home page
|
58
|
+
Then I should not see "override"
|
59
|
+
And I should see "My Local Hydra App"
|
60
|
+
</pre>
|
61
|
+
|
62
|
+
h4. (2) Run the test - it should fail
|
63
|
+
|
64
|
+
When you run this feature, the feature should run, but this test should fail (because you haven't changed anything yet.)
|
65
|
+
|
66
|
+
Mine looked like this:
|
67
|
+
|
68
|
+
<pre>
|
69
|
+
$ rake cucumber:ok
|
70
|
+
SOLRIZER: loading field name mappings from hydra-app/config/solr_mappings.yml
|
71
|
+
resetting mappings for Solrizer::FieldMapper::Default
|
72
|
+
/home/.rvm/rubies/ruby-1.9.3-p0/bin/ruby -S bundle exec cucumber --profile default
|
73
|
+
Using the default profile...
|
74
|
+
Feature: Home page
|
75
|
+
I want the home page to reflect localizations properly
|
76
|
+
|
77
|
+
Scenario: home page text # features/home_page.feature:4
|
78
|
+
When I am on the home page # features/home_page.feature:5
|
79
|
+
Undefined step: "I am on the home page" (Cucumber::Undefined)
|
80
|
+
features/home_page.feature:5:in `When I am on the home page'
|
81
|
+
Then I should not see "override" # features/home_page.feature:6
|
82
|
+
Undefined step: "I should not see "override"" (Cucumber::Undefined)
|
83
|
+
features/home_page.feature:6:in `Then I should not see "override"'
|
84
|
+
And I should see "My Local Hydra App" # features/home_page.feature:7
|
85
|
+
Undefined step: "I should see "My Local Hydra App"" (Cucumber::Undefined)
|
86
|
+
features/home_page.feature:7:in `And I should see "My Local Hydra App"'
|
87
|
+
|
88
|
+
1 scenario (1 undefined)
|
89
|
+
3 steps (3 undefined)
|
90
|
+
0m0.003s
|
91
|
+
|
92
|
+
You can implement step definitions for undefined steps with these snippets:
|
93
|
+
|
94
|
+
When /^I am on the home page$/ do
|
95
|
+
pending # express the regexp above with the code you wish you had
|
96
|
+
end
|
97
|
+
|
98
|
+
Then /^I should not see "([^"]*)"$/ do |arg1|
|
99
|
+
pending # express the regexp above with the code you wish you had
|
100
|
+
end
|
101
|
+
|
102
|
+
Then /^I should see "([^"]*)"$/ do |arg1|
|
103
|
+
pending # express the regexp above with the code you wish you had
|
104
|
+
end
|
105
|
+
|
106
|
+
rake aborted!
|
107
|
+
Command failed with status (1): [/home/.rvm/rubies/ruby-1.9.3-p0/b...]
|
108
|
+
|
109
|
+
Tasks: TOP => cucumber:ok
|
110
|
+
(See full trace by running task with --trace)
|
111
|
+
</pre>
|
112
|
+
|
113
|
+
If steps show as pending, you will need to define them. If you are new to rails3, you might want to look at "http://aslakhellesoy.com/post/11055981222/the-training-wheels-came-off":http://aslakhellesoy.com/post/11055981222/the-training-wheels-came-off and/or "http://net.tutsplus.com/tutorials/ruby/ruby-for-newbies-testing-web-apps-with-capybara-and-cucumber/":http://net.tutsplus.com/tutorials/ruby/ruby-for-newbies-testing-web-apps-with-capybara-and-cucumber/
|
114
|
+
|
115
|
+
Cucumber will load any files in the folder “features/step_definitions” for steps, so let’s create “my_steps.rb” file and add these steps:
|
116
|
+
|
117
|
+
<pre>
|
118
|
+
Given /^I am on the home page$/ do
|
119
|
+
visit "/"
|
120
|
+
end
|
121
|
+
|
122
|
+
Then /^I should not see "([^"]*)"$/ do |text|
|
123
|
+
page.should_not have_content text
|
124
|
+
end
|
125
|
+
|
126
|
+
Then /^I should see "([^"]*)"$/ do |text|
|
127
|
+
page.should have_content text
|
128
|
+
end
|
129
|
+
</pre>
|
130
|
+
|
131
|
+
Now I get the following appropriate failure (as I still haven't changed any code):
|
132
|
+
|
133
|
+
<pre>
|
134
|
+
$ rake cucumber ok
|
135
|
+
SOLRIZER: loading field name mappings from /hydra-app/config/solr_mappings.yml
|
136
|
+
resetting mappings for Solrizer::FieldMapper::Default
|
137
|
+
/home/.rvm/rubies/ruby-1.9.3-p0/bin/ruby -S bundle exec cucumber --profile default
|
138
|
+
Using the default profile...
|
139
|
+
Feature: Home page
|
140
|
+
I want the home page to reflect localizations properly
|
141
|
+
|
142
|
+
Scenario: home page text # features/home_page.feature:4
|
143
|
+
When I am on the home page # features/step_definitions/basic_steps.rb:2
|
144
|
+
Then I should not see "override" # features/step_definitions/basic_steps.rb:6
|
145
|
+
And I should see "My Local Hydra App" # features/step_definitions/basic_steps.rb:10
|
146
|
+
expected there to be content "My Local Hydra App" in "Ruby on Rails: Welcome aboard\n <snip> " (RSpec::Expectations::ExpectationNotMetError)
|
147
|
+
./features/step_definitions/basic_steps.rb:11:in `/^I should see "([^"]*)"$/'
|
148
|
+
features/home_page.feature:7:in `And I should see "My Local Hydra App"'
|
149
|
+
|
150
|
+
Failing Scenarios:
|
151
|
+
cucumber features/home_page.feature:4 # Scenario: home page text
|
152
|
+
|
153
|
+
1 scenario (1 failed)
|
154
|
+
3 steps (1 failed, 2 passed)
|
155
|
+
0m0.199s
|
156
|
+
rake aborted!
|
157
|
+
</pre>
|
158
|
+
|
159
|
+
h4. (3) Change the code
|
160
|
+
|
161
|
+
We want to override the text on the home page locally, keeping our local changes separate from upstream changes to the plugins' code.
|
162
|
+
|
163
|
+
The out-of-the-box default rails home page tells us what to do:
|
164
|
+
|
165
|
+
<pre>
|
166
|
+
"Set up a default route and remove public/index.html
|
167
|
+
</pre>
|
168
|
+
|
169
|
+
We can tell from our app's config/routes.rb file that we already have a default route:
|
170
|
+
|
171
|
+
<pre>
|
172
|
+
MyHydraApp::Application.routes.draw do
|
173
|
+
Blacklight.add_routes(self)
|
174
|
+
HydraHead.add_routes(self)
|
175
|
+
|
176
|
+
root :to => "catalog#index"
|
177
|
+
|
178
|
+
devise_for :users
|
179
|
+
</pre>
|
180
|
+
|
181
|
+
Remove public/index.html from our app ... and we now see the default Blacklight home page. The text of the Blacklight home page informs us that we need to create
|
182
|
+
|
183
|
+
app/views/catalog/_home_text.html.erb
|
184
|
+
|
185
|
+
to override the text in the home page. So create that page,
|
186
|
+
Since the home text is set in @vendor/plugins/hydra-head/app/views/catalog/_home_text.html.erb@, we will override that code by creating a local @app/views/catalog/_home_text.html.erb@ file.
|
187
|
+
|
188
|
+
Our app/views/catalog/_home_text.html.erb might look like this
|
189
|
+
|
190
|
+
<pre>
|
191
|
+
<div class="home_text">
|
192
|
+
<h1>Welcome to My Local Hydra App</h1>
|
193
|
+
</div>
|
194
|
+
</pre>
|
195
|
+
|
196
|
+
h4. (4) Run the test - it should now pass
|
197
|
+
|
198
|
+
Now when you run the feature, it should pass. If it doesn't, iterate until it does.
|
199
|
+
|
200
|
+
<pre>
|
201
|
+
$ rake cucumber:ok
|
202
|
+
Using the default profile...
|
203
|
+
Feature: Home page
|
204
|
+
I want the home page to reflect localizations properly
|
205
|
+
|
206
|
+
Scenario: home page text # features/home_page.feature:4
|
207
|
+
When I am on the home page # features/step_definitions/basic_steps.rb:2
|
208
|
+
Then I should not see "override" # features/step_definitions/basic_steps.rb:6
|
209
|
+
And I should see "My Local Hydra App" # features/step_definitions/basic_steps.rb:10
|
210
|
+
|
211
|
+
1 scenario (1 passed)
|
212
|
+
3 steps (3 passed)
|
213
|
+
</pre>
|
214
|
+
|
215
|
+
|
216
|
+
h2. Changing Application Title (also demonstrates Writing a Spec and Overriding a Helper Method)
|
217
|
+
|
218
|
+
We want to change the application name (what displays as the html page's title). This is set in a plugin's app/helper/application_helper.rb file. Because it is set in a helper file, it is a good candidate for an rspec test (rather than a feature).
|
219
|
+
|
220
|
+
h4. (1) Write the test.
|
221
|
+
|
222
|
+
Since the application name is set in (vendor/plugins/hydra-head/)app/helpers/application_helper.rb, we need a spec to run against the application_helper file.
|
223
|
+
|
224
|
+
Create a file "spec/helpers/application_helper_spec.rb". A test for checking the application name might be inserted like so:
|
225
|
+
|
226
|
+
<pre>
|
227
|
+
require File.expand_path('../../spec_helper', __FILE__)
|
228
|
+
|
229
|
+
describe ApplicationHelper do
|
230
|
+
include ApplicationHelper
|
231
|
+
|
232
|
+
context "overall UI methods" do
|
233
|
+
it "should get the local application name" do
|
234
|
+
application_name.should == "My Hydra"
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
end
|
239
|
+
</pre>
|
240
|
+
|
241
|
+
h4. (2) Run the test - it should fail
|
242
|
+
|
243
|
+
When you run this spec, the spec should run, but this test should fail (because you haven't changed anything yet.) Your output might look like this:
|
244
|
+
|
245
|
+
<pre>
|
246
|
+
$ rspec spec/helpers/application_helper_spec.rb
|
247
|
+
F
|
248
|
+
|
249
|
+
Failures:
|
250
|
+
|
251
|
+
1) ApplicationHelper overall UI methods should get the local application name
|
252
|
+
Failure/Error: application_name.should == "My Hydra"
|
253
|
+
NameError:
|
254
|
+
undefined local variable or method `application_name' for #<RSpec::Core::ExampleGroup::Nested_1::Nested_1:0x007fe26887c6c8>
|
255
|
+
# ./spec/helpers/application_helper_spec.rb:9:in `block (3 levels) in <top (required)>'
|
256
|
+
|
257
|
+
Finished in 0.02426 seconds
|
258
|
+
1 example, 1 failure
|
259
|
+
|
260
|
+
Failed examples:
|
261
|
+
|
262
|
+
rspec ./spec/helpers/application_helper_spec.rb:8 # ApplicationHelper overall UI methods should get the local application name
|
263
|
+
</pre>
|
264
|
+
|
265
|
+
h4. (3) Change the code
|
266
|
+
|
267
|
+
We want to override the application name locally, keeping our local changes separate from upstream changes to the plugins' code.
|
268
|
+
|
269
|
+
Since the application name is set in vendor/plugins/hydra-head/app/helpers/application_helper.rb, we will override that code by putting a method of the same name in app/helpers/application_helper.rb. The current app/helpers/application_helper.rb file may look like this:
|
270
|
+
|
271
|
+
<pre>
|
272
|
+
# Methods added to this helper will be available to all templates in the application.
|
273
|
+
module ApplicationHelper
|
274
|
+
end
|
275
|
+
</pre>
|
276
|
+
|
277
|
+
Code for changing the application name might be inserted like so:
|
278
|
+
|
279
|
+
<pre>
|
280
|
+
# Methods added to this helper will be available to all templates in the application.
|
281
|
+
module ApplicationHelper
|
282
|
+
|
283
|
+
def application_name
|
284
|
+
'My Hydra'
|
285
|
+
end
|
286
|
+
|
287
|
+
end
|
288
|
+
</pre>
|
289
|
+
|
290
|
+
h4. (4) Run the test - it should now pass
|
291
|
+
|
292
|
+
Now when you run the spec, it should pass. If it doesn't, iterate until it does.
|
293
|
+
|
294
|
+
<pre>
|
295
|
+
$ rspec spec/helpers/application_helper_spec.rb
|
296
|
+
.
|
297
|
+
|
298
|
+
Finished in 0.00438 seconds
|
299
|
+
1 example, 0 failures
|
300
|
+
</pre>
|
301
|
+
|
302
|
+
h2. Changing the Facets
|
303
|
+
|
304
|
+
h4. (1) Write the test.
|
305
|
+
|
306
|
+
Write the cucumber tests for the facets you want
|
307
|
+
|
308
|
+
Create a file in your features directory called homepage_facets.feature and put the following feature description in it. Note that this cucumber test is assuming you have imported the Hydra sample/fixture objects. To import sample/fixture objects follow the "Import some Sample Content" instructions in "Out of the Box Tour":https://github.com/projecthydra/hydra-head/wiki/Out-of-the-Box-Tour.
|
309
|
+
|
310
|
+
<pre>
|
311
|
+
Feature: Homepage Facets
|
312
|
+
I want the home page to include the facets I chose
|
313
|
+
|
314
|
+
Scenario: home page facets
|
315
|
+
When I am on the home page
|
316
|
+
Then I should see "Fedora Model"
|
317
|
+
And I should see "info:fedora/afmodel:ModsAsset"
|
318
|
+
Then I should see "Topic"
|
319
|
+
Then I should see "Journal"
|
320
|
+
And I should see "The Journal of Mock Object"
|
321
|
+
And I should see "Pediatric Nursing"
|
322
|
+
Then I should see "Conference"
|
323
|
+
And I should see "some conference Host"
|
324
|
+
</pre>
|
325
|
+
|
326
|
+
h4. (2) Run the test - it should fail
|
327
|
+
|
328
|
+
Now run the test and watch it fail
|
329
|
+
|
330
|
+
<pre>
|
331
|
+
cucumber features
|
332
|
+
</pre>
|
333
|
+
|
334
|
+
h4. (3) Change the code
|
335
|
+
|
336
|
+
Modify app/controllers/catalog_controller.rb to use the facets you want.
|
337
|
+
|
338
|
+
find the section that begins "config.add_facet_field" (around line 42) and replace it with this:
|
339
|
+
|
340
|
+
<pre>
|
341
|
+
config.add_facet_field 'has_model_s', :label => 'Fedora Model'
|
342
|
+
config.add_facet_field 'subject_topic_facet', :label => 'Topic', :limit => 20
|
343
|
+
config.add_facet_field 'journal_title_info_main_title_facet', :label => 'Journal', :limit => true
|
344
|
+
config.add_facet_field 'conference_facet', :label => 'Conference', :limit=>true
|
345
|
+
</pre>
|
346
|
+
|
347
|
+
h4. (4) Run the test - it should now pass
|
348
|
+
|
349
|
+
Now run the test and watch it pass!
|
350
|
+
|
351
|
+
<pre>
|
352
|
+
cucumber features
|
353
|
+
</pre>
|
354
|
+
|
355
|
+
To see the changes for yourself, restart the application.
|
356
|
+
|
357
|
+
|