Skip to content

Commit

Permalink
add up to document link header
Browse files Browse the repository at this point in the history
Add `rel="up"` to the document `Link` header. If the fragment is a
single `ref`, then return the `parent` if it exists. If it's a
`start...end` fragment, then return a link with a `start` being the
start fragment's parent and `end` the end fragment's parent.
  • Loading branch information
zfletch committed Oct 18, 2019
1 parent 64893ef commit 34ffca8
Show file tree
Hide file tree
Showing 5 changed files with 192 additions and 17 deletions.
6 changes: 6 additions & 0 deletions app/models/fragment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ def last_range(stop_fragment)
[range.first, range.last]
end

def parent_range(stop_fragment)
return [] unless parent && stop_fragment.parent

[parent, stop_fragment.parent]
end

private

def steps(stop_fragment)
Expand Down
1 change: 1 addition & 0 deletions app/presenters/fragment_presenter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ def links
{
prev: fragment.previous_fragment,
next: fragment.next_fragment,
up: fragment.parent,
first: fragment.first_fragment,
last: fragment.last_fragment,
}.map { |name, fragment| link(name, fragment) }.compact
Expand Down
17 changes: 11 additions & 6 deletions app/presenters/start_stop_fragment_presenter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,7 @@ def xml
end

def links
{
prev: start.previous_range(stop),
next: start.next_range(stop),
first: start.first_range(stop),
last: start.last_range(stop),
}.map { |name, fragments| link(name, fragments) }.compact
link_headers.map { |name, fragments| link(name, fragments) }.compact
end

private
Expand All @@ -40,6 +35,16 @@ def combine_xml_documents(original_xml, xmls)
end.to_xml
end

def link_headers
{
prev: start.previous_range(stop),
next: start.next_range(stop),
up: start.parent_range(stop),
first: start.first_range(stop),
last: start.last_range(stop),
}
end

def link(name, fragments)
return nil if fragments.empty?

Expand Down
10 changes: 10 additions & 0 deletions spec/models/fragment_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -239,5 +239,15 @@
expect(child11.last_range(child13)).to eq([child21, child23])
end
end

describe '#parent_range' do
it 'is empty for a parent fragment' do
expect(parent1.parent_range(parent2)).to be_empty
end

it 'gets the parent range for a child fragment' do
expect(child13.parent_range(child21)).to eq([parent1, parent2])
end
end
end
end
175 changes: 164 additions & 11 deletions spec/requests/documents_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

RSpec.describe '/documents', type: :request do
let!(:collection) do
Collection.create(urn: 'urn', title: 'title', display_type: 'resource', cite_structure: ['book'])
Collection.create(urn: 'urn', title: 'title', display_type: 'resource', cite_structure: %w[book chapter])
end
let!(:document) { Document.create(urn: 'urn', xml: '<entire-document/>', collection: collection) }
let!(:xml1) do
Expand All @@ -11,6 +11,20 @@
<TEI xmlns="http://www.tei-c.org/ns/1.0">
<dts:fragment xmlns:dts="https://w3id.org/dts/api#">
<div type="textpart" subtype="book" n="1">
<div type="textpart" subtype="chapter" n="1">
<l n="1">abc</l>
</div>
</div>
</dts:fragment>
</TEI>
)
end
let!(:xml11) do
%(
<?xml version="1.0" encoding="UTF-8"?>
<TEI xmlns="http://www.tei-c.org/ns/1.0">
<dts:fragment xmlns:dts="https://w3id.org/dts/api#">
<div type="textpart" subtype="chapter" n="1">
<l n="1">abc</l>
</div>
</dts:fragment>
Expand All @@ -23,6 +37,20 @@
<TEI xmlns="http://www.tei-c.org/ns/1.0">
<dts:fragment xmlns:dts="https://w3id.org/dts/api#">
<div type="textpart" subtype="book" n="2">
<div type="textpart" subtype="chapter" n="1">
<l n="1">def</l>
</div>
</div>
</dts:fragment>
</TEI>
)
end
let!(:xml21) do
%(
<?xml version="1.0" encoding="UTF-8"?>
<TEI xmlns="http://www.tei-c.org/ns/1.0">
<dts:fragment xmlns:dts="https://w3id.org/dts/api#">
<div type="textpart" subtype="chapter" n="1">
<l n="1">def</l>
</div>
</dts:fragment>
Expand All @@ -35,6 +63,20 @@
<TEI xmlns="http://www.tei-c.org/ns/1.0">
<dts:fragment xmlns:dts="https://w3id.org/dts/api#">
<div type="textpart" subtype="book" n="3">
<div type="textpart" subtype="chapter" n="1">
<l n="1">ghi</l>
</div>
</div>
</dts:fragment>
</TEI>
)
end
let!(:xml31) do
%(
<?xml version="1.0" encoding="UTF-8"?>
<TEI xmlns="http://www.tei-c.org/ns/1.0">
<dts:fragment xmlns:dts="https://w3id.org/dts/api#">
<div type="textpart" subtype="chapter" n="1">
<l n="1">ghi</l>
</div>
</dts:fragment>
Expand All @@ -47,24 +89,72 @@
<TEI xmlns="http://www.tei-c.org/ns/1.0">
<dts:fragment xmlns:dts="https://w3id.org/dts/api#">
<div type="textpart" subtype="book" n="4">
<div type="textpart" subtype="chapter" n="1">
<l n="1">jkl</l>
</div>
<div type="textpart" subtype="chapter" n="2">
<l n="1">mno</l>
</div>
</div>
</dts:fragment>
</TEI>
)
end
let!(:xml41) do
%(
<?xml version="1.0" encoding="UTF-8"?>
<TEI xmlns="http://www.tei-c.org/ns/1.0">
<dts:fragment xmlns:dts="https://w3id.org/dts/api#">
<div type="textpart" subtype="chapter" n="1">
<l n="1">jkl</l>
</div>
</dts:fragment>
</TEI>
)
end
let!(:book1) { Fragment.create(document: document, ref: '1', level: 1, rank: 0, descendent_rank: 0, xml: xml1) }
let!(:book2) { Fragment.create(document: document, ref: '2', level: 1, rank: 1, descendent_rank: 1, xml: xml2) }
let!(:book3) { Fragment.create(document: document, ref: '3', level: 1, rank: 2, descendent_rank: 2, xml: xml3) }
let!(:book4) { Fragment.create(document: document, ref: '4', level: 1, rank: 3, descendent_rank: 3, xml: xml4) }
let!(:xml42) do
%(
<?xml version="1.0" encoding="UTF-8"?>
<TEI xmlns="http://www.tei-c.org/ns/1.0">
<dts:fragment xmlns:dts="https://w3id.org/dts/api#">
<div type="textpart" subtype="chapter" n="2">
<l n="1">mno</l>
</div>
</dts:fragment>
</TEI>
)
end
let!(:book1) { Fragment.create(document: document, ref: '1', level: 1, rank: 0, descendent_rank: 1, xml: xml1) }
let!(:chapter11) do
Fragment.create(document: document, parent: book1, ref: '1.1', level: 2, rank: 1, descendent_rank: 1, xml: xml11)
end

let!(:book2) { Fragment.create(document: document, ref: '2', level: 1, rank: 2, descendent_rank: 3, xml: xml2) }
let!(:chapter21) do
Fragment.create(document: document, parent: book2, ref: '2.1', level: 2, rank: 3, descendent_rank: 3, xml: xml21)
end

let!(:book3) { Fragment.create(document: document, ref: '3', level: 1, rank: 4, descendent_rank: 5, xml: xml3) }
let!(:chapter31) do
Fragment.create(document: document, parent: book3, ref: '3.1', level: 2, rank: 5, descendent_rank: 5, xml: xml31)
end

let!(:book4) { Fragment.create(document: document, ref: '4', level: 1, rank: 6, descendent_rank: 8, xml: xml4) }
let!(:chapter41) do
Fragment.create(document: document, parent: book4, ref: '4.1', level: 2, rank: 7, descendent_rank: 7, xml: xml41)
end
let!(:chapter42) do
Fragment.create(document: document, parent: book4, ref: '4.2', level: 2, rank: 8, descendent_rank: 8, xml: xml42)
end

specify 'Retrieve a passage using ref' do
get '/documents/?id=urn&ref=1'
get '/documents/?id=urn&ref=2'

expect(response.content_type).to eq('application/tei+xml; charset=utf-8')
expect(response).to have_http_status(:ok)
expect(response.headers['Link']).to eq(%(
</documents?id=urn&ref=2>; rel="next",
</documents?id=urn&ref=1>; rel="prev",
</documents?id=urn&ref=3>; rel="next",
</documents?id=urn&ref=1>; rel="first",
</documents?id=urn&ref=4>; rel="last",
</navigation?id=urn>; rel="contents",
Expand All @@ -74,8 +164,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<TEI xmlns="http://www.tei-c.org/ns/1.0">
<dts:fragment xmlns:dts="https://w3id.org/dts/api#">
<div type="textpart" subtype="book" n="1">
<l n="1">abc</l>
<div type="textpart" subtype="book" n="2">
<div type="textpart" subtype="chapter" n="1">
<l n="1">def</l>
</div>
</div>
</dts:fragment>
</TEI>
))
end

specify 'Retrieve a passage with a parent using ref' do
get '/documents/?id=urn&ref=3.1'

expect(response.content_type).to eq('application/tei+xml; charset=utf-8')
expect(response).to have_http_status(:ok)
expect(response.headers['Link']).to eq(%(
</documents?id=urn&ref=2.1>; rel="prev",
</documents?id=urn&ref=4.1>; rel="next",
</documents?id=urn&ref=3>; rel="up",
</documents?id=urn&ref=1.1>; rel="first",
</documents?id=urn&ref=4.2>; rel="last",
</navigation?id=urn>; rel="contents",
</collections?id=urn>; rel="collection"
).squish)
expect(response.body).to be_equivalent_to(%(
<?xml version="1.0" encoding="UTF-8"?>
<TEI xmlns="http://www.tei-c.org/ns/1.0">
<dts:fragment xmlns:dts="https://w3id.org/dts/api#">
<div type="textpart" subtype="chapter" n="1">
<l n="1">ghi</l>
</div>
</dts:fragment>
</TEI>
Expand All @@ -99,10 +217,45 @@
<TEI xmlns="http://www.tei-c.org/ns/1.0">
<dts:fragment xmlns:dts="https://w3id.org/dts/api#">
<div type="textpart" subtype="book" n="3">
<l n="1">ghi</l>
<div type="textpart" subtype="chapter" n="1">
<l n="1">ghi</l>
</div>
</div>
<div type="textpart" subtype="book" n="4">
<l n="1">jkl</l>
<div type="textpart" subtype="chapter" n="1">
<l n="1">jkl</l>
</div>
<div type="textpart" subtype="chapter" n="2">
<l n="1">mno</l>
</div>
</div>
</dts:fragment>
</TEI>
))
end

specify 'Retrieve a passage using start and end across books' do
get '/documents/?id=urn&start=1.1&end=2.1'

expect(response.content_type).to eq('application/tei+xml; charset=utf-8')
expect(response).to have_http_status(:ok)
expect(response.headers['Link']).to eq(%(
</documents?end=4.1&id=urn&start=3.1>; rel="next",
</documents?end=2&id=urn&start=1>; rel="up",
</documents?end=2.1&id=urn&start=1.1>; rel="first",
</documents?end=4.2&id=urn&start=4.1>; rel="last",
</navigation?id=urn>; rel="contents",
</collections?id=urn>; rel="collection"
).squish)
expect(response.body).to be_equivalent_to(%(
<?xml version="1.0" encoding="UTF-8"?>
<TEI xmlns="http://www.tei-c.org/ns/1.0">
<dts:fragment xmlns:dts="https://w3id.org/dts/api#">
<div type="textpart" subtype="chapter" n="1">
<l n="1">abc</l>
</div>
<div type="textpart" subtype="chapter" n="1">
<l n="1">def</l>
</div>
</dts:fragment>
</TEI>
Expand Down

0 comments on commit 34ffca8

Please sign in to comment.