Skip to content

Add Metadata to Views, Presenter, and Solr

Bess Sadler edited this page Sep 6, 2019 · 13 revisions

Goals:

Setup

(OPTIONAL) Save your current changes

If you have changes in your current branch -- you can check on this via git status -- you'll want to save those before starting this lesson (which uses a separate branch):

  • git checkout -b metadata_lesson_2_start
  • git add .
  • git commit -m 'checkpoint before beginning second metadata lesson'

Check out working branch

git checkout add_new_metadata_field_1

NOTE: If you make experimental changes and want to get back to the minimal code state necessary to run this lesson, you can check the starting code out again using:
git checkout add_new_metadata_field_1

Start up test servers

Same as in part one of this tutorial.

Add the field to the show view

In part one of this tutorial, we added functionality for new fields when creating a new Image. For part two, we're going focus on displaying an Image.

Add a Show feature test

  1. Create a new file at spec/features/show_image_spec.rb.
require 'rails_helper'

RSpec.feature 'Display an Image' do
  let(:title)      { ['Journey to Skull Island'] }
  let(:creator)    { ['Quest, Jane'] }
  let(:keyword)    { ['Pirates', 'Adventure'] }
  let(:visibility) { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC }
  let(:user)       { '[email protected]' }

  let :image do
    Image.create(title:      title,
                creator:    creator,
                keyword:    keyword,
                visibility: visibility,
                depositor:  user)
  end

  scenario "Show a public Image" do
    visit("/concern/images/#{image.id}")

    expect(page).to have_content image.title.first
    expect(page).to have_content image.creator.first
    expect(page).to have_content image.keyword.first
    expect(page).to have_content image.keyword.last
  end
end
  1. Run your test suite (docker-compose run web rspec spec or docker-compose run web rspec spec/features/show_image_spec.rb). Everything should pass.

Add the new metadata field to your show feature

  1. Add your new metadata field to the show spec you just created. You'll need to add it in three places:
    1. As a let statement, where you define the value: let(:year) { ['2010'] }
    2. In the Image.create block: year: year
    3. In the expectations: expect(page).to have_content image.year.first
  2. Run your test again (docker-compose run web rspec spec/features/show_image_spec.rb). It should fail with the message Failure/Error: expect(page).to have_content image.year.first.

This tells us that our test setup ran successfully (an Image was created with a year field) but the show page doesn't display that field yet.

Modify the presenter for our Image class

Recall that Rails uses an "MVC" or "model-view-controller" pattern. In addition to models, views, and controllers, we also have presenters, sometimes also referred to as a "Decorator" or "View-Model." The presenter is responsible for translating values from the model to a presentable form.

Example:

class BookPresenter
  def initialize(book)
    @book = book
  end

  delegate :title, :creator, to: :@book

  def glitter_title
    '★' + @book.title + '☆'
  end
end

Customize our image-specific presenter

As always, we want to write our test first.

  1. Hyrax generated app/presenters/hyrax/image_presenter.rb and spec/presenters/hyrax/image_presenter_spec.rb for you when you created your Image work type. Open these files and take a look.
  2. Edit spec/presenters/hyrax/image_presenter_spec.rb. It is only a stubbed spec right now.
require 'rails_helper'

RSpec.describe Hyrax::ImagePresenter do
subject { presenter }

let(:title) { ['Journey to Skull Island'] }
let(:creator) { ['Quest, Jane'] }
let(:keyword) { ['Pirates', 'Adventure'] }
let(:degree) { ['Master of Pirate Studies'] }
let(:year) { ['2010'] }
let(:visibility) { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC }
let :image do
  Image.new(
    title: title,
    creator: creator,
    keyword: keyword,
    year: year,
    visibility: visibility
  )
end

let(:ability) { Ability.new(user) }

let(:solr_document) { SolrDocument.new(image.to_solr) }

let(:presenter) do
  described_class.new(solr_document, nil)
end

it "delegates year to solr document" do
  expect(solr_document).to receive(:year)
  presenter.year
end
end
  1. Run your test (docker-compose run web rspec spec/presenters/hyrax/image_presenter_spec.rb). It will fail with the message Failure/Error: it { is_expected.to delegate_method(:year).to(:solr_document) }
  2. Add this line to your app/presenters/hyrax/image_presenter.rb file:
  delegate :year, to: :solr_document

Use our custom presenter

In order to use our custom presenter, our Image class has to know about it. Normally, you would have to manually add the custom presenter to the relevant controller, in this case app/controllers/hyrax/images_controller.rb. However, Hyrax did this for you when you ran the work type generator. Open the app/controllers/hyrax/images_controller.rb file and note that it is configured to use Hyrax::ImagePresenter.

  self.show_presenter = Hyrax::ImagePresenter

Hurray! Failure! Just what we wanted!

     Failure/Error: delegate :year, to: :solr_document

     NoMethodError:
       undefined method `year' for #<SolrDocument:0x000000000c855028>

Discussion

  • Where does the presenter get its data?
  • What does it mean that we "delegate" to solr_document?
  • What advantages are there to our "presenter" pattern vs. using Work throughout?

Check out working branch

git checkout add_new_metadata_field_2_mid

NOTE: If you make experimental changes and want to get back to the minimal code state necessary to run this lesson, you can check the starting code out again using:
git checkout add_new_metadata_field_2_mid

Add a field to view partial and solr

Add your field to the solr index

  1. Edit app/models/image.rb and add instructions for how the year field should be indexed:
  property :year, predicate: "http://www.europeana.eu/schemas/edm/year" do |index|
    index.as :stored_searchable
  end

Add the field to solr_document

  1. Edit app/models/solr_document.rb and add this method:
  def year
    self[Solrizer.solr_name('year')]
  end

Now docker-compose run web rspec spec/presenters/hyrax/image_presenter_spec.rb should pass.

Add the field to the view partial

  1. Copy Hyrax's app/views/hyrax/base/_attribute_rows.html.erb to the same directory structure in your app
  2. Edit your newly created local copy of _attribute_rows.html.erb to include your metadata field:
  <%= presenter.attribute_to_html(:year) %>
  1. Run your test suite again (docker-compose run web rspec) and your feature test should now pass (docker-compose run web rspec spec/features/show_image_spec.rb)

Note: You can see all the changes made during this exercise on the github repo beginning to midpoint and midpoint to end.

Pair exercise

We added one metadata field here: year. Choose either extent or references and add a second metadata field. Or, define your own metadata field, as long as you pick something that can be a simple string.