I tested this with ruby 2.0.0, rails 4.2.4 and a postgresql database in the development environment only.
Find a live installation at immense-sierra-3941.herokuapp.com/ which works with the rest api installed at tstspace.princeton.edu/rest.
The code consists of two components: the rails application itself and a gem that deals with the rest api interaction, see dspace-rest at github.com/akinom/do-dspace-rest.git. The gem is currently not setup to do https.
Kate reworked Peter Dietz’s rails app to use the active-rest-client gem: github.com/whichdigital/active-rest-client, which works with https. Since Kate and I teamed up late in the process we were not able to rework the do-dspace-rest gem. Her version of Peter’s rails app is available at github.com/ekate/dspace-rest-rails/tree/active-rest-client.
install ruby, www.ruby-lang.org/en/
install bundler, bundler.io/
download the code and change to the source root
edit config/database.yml file and adjust the database settings; as is: the development environment is set up to work with a postgres database named dspace_rails_development that is accessible without credentials
create the development database
The app connects by default to tstspace.princeton.edu/rest. You can set the DSPAPCE_REST environment variable to a different url, or edit the config/application.rb file to adjust for your environment. Again: Please note that the dspace-rest gem works only with http requests.
url = ENV["DSPACE_REST"] || "http://tstspace.princeton.edu/rest"
bundle install bundle exec rake db:migrate
If you wish to trace the rest api calls issued set the RESTCLIENT_LOG environment variable:
export RESTCLIENT_LOG=stdout
Seed the database with a few configuration settings:
bundle exec rake config:seed
If you are interested you can list the generated configuration values:
bunde exec rake config:list
Finally start the server
bundle exec rails server
Visit localhost:3000 in your browser and if everything went according to plan you should see a listing of the top communities.
All pages show a big black block at the bottom which lists request parameters along with the values computed in the action that was triggered by the request. As you will see each request has at least the following three parameters:
* layout - values are: default, sitemap, library, and core * controller, action - these determine which method (action) is called on which controller
layout, controller, and action parameters are derived from the url according to patterns defined in config/routes.rb
Variables that start with c_ are computed and used by the core layout and may be overwritten in derived layouts. For example the default layout always computes ‘explore_communities’ as the list of top level communities. In the #top action of the communities controller it reuses explore_communities to assign to c_top_communities.
The widely used devise gem takes care of creating accounts, logging users in and out, dealing with password reminders, … There are plugins for external authentication systems, …; rubygems.org/search?query=devise
In this app I use devise such that users can self register.
Once logged you’ll see an additional menu that links to pages where users can manipulate configurations. The default layout presents the additional menu to logged in users only; see the line in app/views/layouts/default.html.erb:
<%= render partial: 'default/loggedin_header' if @current_user %>
No rights checking is implemented for configurations.
Whether a user has the right to create, read, update, or delete communities, collections, items,.. is determined with the help of the ability class, app/models/ability.rb in cooperation with can? methods defined for dspace objects. I faked the inclusion of rights properties by the Rest Api on all communities, collections, items. Note in app/models/ability.rb how Item objects make use of the rights array in their can? method. You can see the rights values in the Debug Panel.
A small helper method enables the rendering code to decide whether to include links/forms for certain actions/objects, see for example app/views/communities/top.html.erb
The About page of the life app explains about CSS, booststrap, layouts, … immense-sierra-3941.herokuapp.com/default/about
Conceptually: Configuration Settings have a name, type (aka class), value (serialized to yaml) and a scope; This is implemented by two ActiveRecord, database backed, classes: ConfigValue, app/models/config_value.rb and app/models/config_type.rb. Scopes help to maintain several values for the same configuration such that the appropriate value can be chosen based on ‘scope’. In this demo app we scope on dspace objects, defined by their handles, and the currently logged in user, defined by her email.
You can view all config_types defined in the live application at immense-sierra-3941.herokuapp.com/default/config_types. Each type may have several associated values, each with a different scope. The @c_config variable shown in the debug panel lists the configuration values that are active for the current page.
Types are defined by a name and a class, eg: ‘AppName’ of class ‘String’ or ‘ItemDisplay’ of class ‘Hash’. Values belong to a config type, have a scope, and a value represented by a yaml_string. The live application defines the value ‘RailsSpace’ with scope nil which belongs to the ‘AppName’ type. The Hash value
{:short_metadata_list=>["dc.contributor.author", "dc.contributor.advisor", "dc.title", ...]}
with scope 88435/dsp01td96k251d, which is the handle of the ‘Princeton University Doctoral Dissertations, 2011-2015’ community, belongs to the ‘ItemDisplay’ type.
The application controller computes the configuration values based on the selected dspace object, its parents, and the currently logged in user, such that values with scope ‘nil’ are overwritten by those scoped to the currently active community, collection, and/or item, and last by values scoped to the currently logged in user, see the resolve_configs method in app/controllers/application_controller.rb. If a configuration’s type is Hash, values are merged to allow for partial overwrites. Other scopes might become useful, such as a users’ role, the active layout, … You can view the configuration values computed in the @c_config hash shown in the Debug Panel.
The ‘AppName’ configuration has one value only, with scope nil, It is used in the web site’s title and the navigation bar of the default layout. Thus you can expect to see the same ‘AppName’ value listed by the @c_config hash on all application pages.
The live application defines several ‘CollectionDescription’ values, each scoped to a different community. The default value is the empty string, most top communities have a ‘proper’ description and sub communities, collections, and items inherit the description of their top parent community. All collection pages show the respective description, unless it is empty. This is implemented by the line:
<%= content_tag('p', @c_config[:collection_description]) if @c_config[:collection_description] %>
in app/views/collections/show.html.erb. Again @c_config in the Debug Panel shows the active description value.
‘ItemDisplay’ is another configuration with multiple values. It is used in app/views/items/show.html.erb, app/views/items/_item_list.html.erb. Unlike ‘CollectionDescription’ it has a non empty default value that applies to most items. The overwriting value in the life application redefines only the metadata list for one hash key. You can see the effect on collection pages in any collection in the ‘Princeton University Doctoral Dissertations, 2011-2015’ community.
Currently configurations validate whether a given value is compatible with the expected class. In addition validations should make sure that at most one type with the same name is created and at most one value with a given scope exists for each config_type. The examples above use the core Ruby classes, String and Hash. Since the code is general, any class may be used to define configuration types. Instead of defining ‘ItemDisplay’ as a Hash, it should use a custom class that ensures, only existing metadata keys are used, that metadata values are displayed appropriately as text/names/dates/html/… The configuration editor and custom classes will need to agree on a framework/api/pattern so that editing/updating/validating/and displaying custom values can be conveniently implemented.
There is a gem, see guides.rubyonrails.org/i18n.html
The Blacklight gem (rubygems.org/search?query=blacklight) is popular in the hydra community. It provides a highly configurable UI to solr search indexes. While it likely will not be useful as is, it should provide a good starting point for development.
Thanks to Peter Dietz’s github.com/peterdietz/dspace-rest-rails and github.com/peterdietz/dspace-rest-requests, which both helped me get started on this rails application