-
Notifications
You must be signed in to change notification settings - Fork 4
Add Metadata to Views, Presenter, and Solr
If your continuing immediately from a previous exercise and the application is already running at http://localhost:3000, you're good to go; otherwise, restart the services that run your application. Use the same steps as in part one of this tutorial
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 work_in_progress_2
git add .
git commit -m 'checkpoint before beginning second metadata lesson'
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 reset --hard origin/add_new_metadata_field_1
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 the new fields when viewing an Image.
- 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
- Run your test suite (
rspec spec
orrspec spec/features/show_image_spec.rb
). Everything should pass.
- Add your new metadata field to the show spec you just created. You'll need to add it in three places:
- As a let statement, where you define the value:
let(:year) { ['2010'] }
- In the Image.create block:
year: year,
make sure each item in the list is separated with a comma - In the expectations:
expect(page).to have_content image.year.first
- As a let statement, where you define the value:
- Run your test again (
rspec spec/features/show_image_spec.rb
).
It should fail with the messageFailure/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.
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." You may also be familiar with "View Helpers"; the limitation of view helper methods is that they are only available in the view portions of your code. Presenters work very much like view helpers but can be invoked anywhere in your code, this is useful for example if you might want to use the same logic to reformat a field in an export method (not tied to a browser view) that you use in your web views. 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
def title_case_title
@book.title.titleize
end
def initial_caps_title
@book.humanize
end
end
As always, we want to write our test first.
- Hyrax generated
app/presenters/hyrax/image_presenter.rb
andspec/presenters/hyrax/image_presenter_spec.rb
for you when you created your Image work type. Open these files and take a look. - Edit
spec/presenters/hyrax/image_presenter_spec.rb
. Hyrax initally generates an empty stubbed spec for us. Replace that empty test with the test code here:
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
- Run your test (
rspec spec/presenters/hyrax/image_presenter_spec.rb
). It will fail with the messageFailure/Error: it { is_expected.to delegate_method(:year).to(:solr_document) }
- Add this line to your app/presenters/hyrax/image_presenter.rb file:
delegate :year, to: :solr_document
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 already configured to use Hyrax::ImagePresenter.
self.show_presenter = Hyrax::ImagePresenter
Run your test again (rspec spec/presenters/hyrax/image_presenter_spec.rb
)
Failure/Error: expect(solr_document).to receive(:year)
#<SolrDocument:0x0000565405bc6470 ...> does not implement: year
- 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?
NOTE: If you've make experimental changes and want to get back to the code used at this point in the lesson, you can check the starting code out again using:
git reset --hard origin/add_new_metadata_field_2_mid
- Edit
app/models/image.rb
and add instructions for how theyear
field should be indexed:
property :year, predicate: "http://www.europeana.eu/schemas/edm/year" do |index|
index.as :stored_searchable
end
- Edit
app/models/solr_document.rb
and add this method:
def year
self[Solrizer.solr_name('year')]
end
Now rspec spec/presenters/hyrax/image_presenter_spec.rb
should pass.
- Copy Hyrax's
app/views/hyrax/base/_attribute_rows.html.erb
to the same directory structure in your app - Edit your newly created local copy of
_attribute_rows.html.erb
to include your metadata field:
<%= presenter.attribute_to_html(:year) %>
- Run your test suite again (
rspec
) and your feature test should now pass (i.e.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.
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.