-
Notifications
You must be signed in to change notification settings - Fork 254
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1690 from projectblacklight/json-api
Improve the catalog JSON API by adopting JSON-API practices
- Loading branch information
Showing
7 changed files
with
155 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,67 @@ | ||
json.response do | ||
json.docs @presenter.documents | ||
json.facets @presenter.search_facets_as_json | ||
json.links do | ||
json.self url_for(search_state.to_h.merge(only_path: false)) | ||
json.prev url_for(search_state.to_h.merge(only_path: false, page: @response.prev_page.to_s)) if @response.prev_page | ||
json.next url_for(search_state.to_h.merge(only_path: false, page: @response.next_page.to_s)) if @response.next_page | ||
json.last url_for(search_state.to_h.merge(only_path: false, page: @response.total_pages.to_s)) | ||
end | ||
|
||
json.meta do | ||
json.pages @presenter.pagination_info | ||
end | ||
|
||
json.data do | ||
json.array! @presenter.documents do |document| | ||
json.id document.id | ||
json.attributes document | ||
json.links do | ||
json.self polymorphic_url(url_for_document(document)) | ||
end | ||
end | ||
end | ||
|
||
json.included do | ||
json.array! @presenter.search_facets_as_json do |facet| | ||
json.type 'facet' | ||
json.id facet['name'] | ||
json.attributes do | ||
json.items do | ||
json.array! facet['items'] do |item| | ||
json.id | ||
json.attributes do | ||
json.label item['label'] | ||
json.value item['value'] | ||
json.hits item['hits'] | ||
end | ||
json.links do | ||
json.self path_for_facet(facet['name'], item['value'], only_path: false) | ||
end | ||
end | ||
end | ||
end | ||
json.links do | ||
json.self search_facet_path(id: facet['name'], only_path: false) | ||
end | ||
end | ||
|
||
json.array! search_fields do |(label, key)| | ||
json.type 'search_field' | ||
json.id key | ||
json.attributes do | ||
json.label label | ||
end | ||
json.links do | ||
json.self url_for(search_state.to_h.merge(search_field: key, only_path: false)) | ||
end | ||
end | ||
|
||
json.array! active_sort_fields do |key, field| | ||
json.type 'sort' | ||
json.id key | ||
json.attributes do | ||
json.label field.label | ||
end | ||
json.links do | ||
json.self url_for(search_state.to_h.merge(sort: key, only_path: false)) | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -116,4 +116,3 @@ | |
expect(page).to have_content "No results found for your search" | ||
end | ||
end | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,30 +1,75 @@ | ||
# frozen_string_literal: true | ||
RSpec.describe "catalog/index.json" do | ||
let(:response) { instance_double(Blacklight::Solr::Response, documents: docs) } | ||
let(:docs) { [{ id: '123', title_t: 'Book1' }, { id: '456', title_t: 'Book2' }] } | ||
let(:response) { instance_double(Blacklight::Solr::Response, documents: docs, prev_page: nil, next_page: 2, total_pages: 3) } | ||
let(:docs) { [SolrDocument.new(id: '123', title_t: 'Book1'), SolrDocument.new(id: '456', title_t: 'Book2')] } | ||
let(:facets) { double("facets") } | ||
let(:config) { instance_double(Blacklight::Configuration) } | ||
let(:config) { Blacklight::Configuration.new } | ||
let(:presenter) { Blacklight::JsonPresenter.new(response, facets, config) } | ||
|
||
it "renders index json" do | ||
let(:hash) do | ||
render template: "catalog/index.json", format: :json | ||
JSON.parse(rendered).with_indifferent_access | ||
end | ||
|
||
before do | ||
allow(view).to receive(:blacklight_config).and_return(config) | ||
allow(view).to receive(:search_action_path).and_return('http://test.host/some/search/url') | ||
allow(view).to receive(:search_facet_path).and_return('http://test.host/some/facet/url') | ||
allow(presenter).to receive(:pagination_info).and_return({ current_page: 1, next_page: 2, | ||
prev_page: nil }) | ||
allow(presenter).to receive(:search_facets_as_json).and_return( | ||
[{ name: "format", label: "Format", | ||
items: [{ value: 'Book', hits: 30, label: 'Book' }] }]) | ||
[{ 'name' => "format", 'label' => "Format", | ||
'items' => [{ 'value' => 'Book', 'hits' => 30, 'label' => 'Book' }] }]) | ||
assign :presenter, presenter | ||
render template: "catalog/index.json", format: :json | ||
hash = JSON.parse(rendered) | ||
expect(hash).to eq('response' => { 'docs' => [{ 'id' => '123', 'title_t' => 'Book1' }, | ||
{ 'id' => '456', 'title_t' => 'Book2' }], | ||
'facets' => [{ 'name' => "format", 'label' => "Format", | ||
'items' => [ | ||
{ 'value' => 'Book', | ||
'hits' => 30, | ||
'label' => 'Book' }] }], | ||
'pages' => { 'current_page' => 1, | ||
'next_page' => 2, | ||
'prev_page' => nil } } | ||
) | ||
assign :response, response | ||
end | ||
|
||
it "has pagination links" do | ||
expect(hash).to include(links: hash_including( | ||
self: 'http://test.host/', | ||
next: 'http://test.host/?page=2', | ||
last: 'http://test.host/?page=3')) | ||
end | ||
|
||
it "has pagination information" do | ||
expect(hash).to include(meta: hash_including(pages: | ||
{ | ||
'current_page' => 1, | ||
'next_page' => 2, | ||
'prev_page' => nil | ||
})) | ||
end | ||
|
||
it "includes documents, links, and their attributes" do | ||
expect(hash).to include(data: [ | ||
{ | ||
id: '123', | ||
attributes: { 'id' => '123', 'title_t' => 'Book1' }, | ||
links: { self: 'http://test.host/catalog/123' } | ||
}, | ||
{ | ||
id: '456', | ||
attributes: { 'id' => '456', 'title_t' => 'Book2' }, | ||
links: { self: 'http://test.host/catalog/456' } | ||
}, | ||
]) | ||
end | ||
|
||
it "has facet information and links" do | ||
expect(hash).to include(:included) | ||
|
||
facets = hash[:included].select { |x| x['type'] == 'facet' } | ||
expect(facets).to be_present | ||
|
||
expect(facets.map { |x| x['id'] }).to include 'format' | ||
|
||
format = facets.find { |x| x['id'] == 'format' } | ||
|
||
expect(format['links']).to include self: 'http://test.host/some/facet/url' | ||
expect(format['attributes']).to include :items | ||
|
||
format_items = format['attributes']['items'].map { |x| x['attributes'] } | ||
|
||
expect(format_items).to match_array [{value: 'Book', hits: 30, label: 'Book'}] | ||
end | ||
end |