Skip to content
IIIF Presentation API for Ruby
Branch: development
Clone or download
ConorSheehan1 and jcoyne fix specs, priceton moved loris to https
* fix specs, priceton moved loris to https, faraday not redirecting on 301, change url
update spec to expect regionSquare in supports

* revert back to url encoded slashes in spec
revert change to hash_behaviours_spec

* missed one set of slashes

* remove redundant comment
Latest commit d659b73 Oct 4, 2018
Type Name Latest commit message Commit time
Failed to load latest commit information.
gemfiles Span activesupport 3.x AND 4.x Jan 21, 2015
lib/iiif IIIF ImageResources should use the @type dctypes:Image Jan 6, 2017
spec fix specs, priceton moved loris to https Oct 4, 2018
.gitignore Tinkering to get gem to install properly Nov 12, 2014
.rspec Ran git init. Structure and many Hash API methods implemented. Oct 26, 2014
.travis.yml Ignore singleton classes for descendants. Aug 18, 2016
Gemfile Tinkering to get gem to install properly Nov 12, 2014
LICENSE adds license Nov 11, 2014 New coverage badge Oct 27, 2016
Rakefile Tinkering to get gem to install properly Nov 12, 2014
iiif-presentation.gemspec Relax faraday dependency pinning Jan 6, 2017

O'Sullivan: A Ruby API for working with IIIF Presentation manifests

Build Status Coverage Status


From the source code do rake install, or get the latest release from RubyGems.

Building New Objects

There is (or will be) a class for all types in IIIF Presentation API Spec.

require 'iiif/presentation'

seed = {
    '@id' => '',
    'label' => 'My Manifest'
# Any options you add are added to the object
manifest =

canvas =
# All classes act like `ActiveSupport::OrderedHash`es, for the most part.
# Use `[]=` to set JSON-LD properties...
canvas['@id'] = ''
# ...but there are also accessors and mutators for the properties mentioned in 
# the spec
canvas.width = 10
canvas.height = 20
canvas.label = 'My Canvas'

oc ='@id' => '')
canvas.other_content << oc

manifest.sequences << canvas

puts manifest.to_json(pretty: true)

Methods are generated dynamically, which means #methods is your friend:

manifest =
puts manifest.methods(false)
> label=
> label
> description=
> description
> thumbnail=
> thumbnail
> attribution=
> attribution
> viewing_hint=
> viewingHint=
> viewing_hint
> viewingHint

Note that multi-word properties are implemented as snake_case (because this is Ruby), but is serialized as camelCase. There are camelCase aliases for these.

manifest =
manifest.viewing_hint = 'paged'
puts manifest.to_json(pretty: true, force: true) # force: true skips validations

> {
>   "@context": "",
>   "@type": "sc:Manifest",
>   "viewingHint": "paged"
> }

Parsing Existing Objects

Use IIIF::Service#parse. It will figure out what the object should be, based on @type, and fall back to ActiveSupport::OrderedHash when it can't e.g.:

seed = '{
  "@context": "",
  "@id": "",
  "@type": "sc:Manifest",
  "label": "My Manifest",
  "service": {
    "@context": "",
  "seeAlso": {
    "@id": "",
    "format": "application/marc"
  "sequences": [
      "label":"Current Page Order",
      "startCanvas": "",
      "canvases": [
          "@id": "",
          "@type": "sc:Canvas",
          "width": 10,
          "height": 20,
          "label": "My Canvas",
          "otherContent": [
              "@id": "",
              "motivation": "sc:painting"

obj = IIIF::Service.parse(seed) # can also be a file path or a Hash
puts obj.class
puts obj.see_also.class

> IIIF::Presentation::Manifest
> ActiveSupport::OrderedHash

Validation and Exceptions

This is work in progress. Right now exceptions are generally raised when you try to set something to a type it should never be:

manifest =
manifest.sequences = 'quux'

> [...] sequences must be an Array. (IIIF::Presentation::IllegalValueError)

and also if any required properties are missing when calling to_json

canvas ='@id' => '')
puts canvas.to_json(pretty: true)

> A(n) width is required for each IIIF::Presentation::Canvas (IIIF::Presentation::MissingRequiredKeyError)

but you can skip this validation by adding force: true:

canvas ='@id' => '')
puts canvas.to_json(pretty: true, force: true)

> {
>   "@context": "",
>   "@id": "",
>   "@type": "sc:Canvas"
> }

This all needs a bit of tidying up, finishing, and refactoring, so expect it to change.

You can’t perform that action at this time.