Skip to content

Commit b45b1ff

Browse files
committed
Fix based_near/Location for resource models
Access location service via Hyrax config to allow easier mock responses in specs Add form (pre)populator to handle the data sent/received from the controlled vocabulary input Auto-include any properly named form field behaviors
1 parent 49d5625 commit b45b1ff

File tree

10 files changed

+143
-8
lines changed

10 files changed

+143
-8
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# frozen_string_literal: true
2+
module Hyrax
3+
module BasicMetadataFormFieldsBehavior
4+
# Provides compatibility with the behavior of the based_near (location) controlled vocabulary form field.
5+
# The form expects a ControlledVocabularies::Location object as input and produces a hash like those
6+
# used with accepts_nested_attributes_for.
7+
def self.included(descendant)
8+
descendant.property :based_near_attributes, virtual: true, populator: :based_near_populator, prepopulator: :based_near_prepopulator
9+
end
10+
11+
private
12+
13+
def based_near_populator(fragment:, **_options)
14+
adds = []
15+
deletes = []
16+
fragment.each do |_, h|
17+
uri = RDF::URI.parse(h["id"]).to_s
18+
if h["_destroy"] == "true"
19+
deletes << uri
20+
else
21+
adds << uri
22+
end
23+
end
24+
self.based_near = ((model.based_near + adds) - deletes).uniq
25+
end
26+
27+
def based_near_prepopulator
28+
self.based_near = based_near.map do |loc|
29+
uri = RDF::URI.parse(loc)
30+
if uri
31+
Hyrax::ControlledVocabularies::Location.new(uri)
32+
else
33+
loc
34+
end
35+
end
36+
end
37+
end
38+
end
+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# frozen_string_literal: true
2+
3+
module Hyrax
4+
##
5+
# Indexes properties common to Hyrax::Resource types
6+
module LocationIndexer
7+
def to_solr
8+
super.tap do |index_document|
9+
index_document[:based_near_label_tesim] = based_near_label_lookup(resource.based_near) if resource.respond_to? :based_near
10+
end
11+
end
12+
13+
private
14+
15+
def based_near_label_lookup(locations)
16+
locations.map do |loc|
17+
if URI.parse(loc)
18+
location_service.full_label(loc)
19+
else
20+
loc
21+
end
22+
end
23+
end
24+
25+
def location_service
26+
Hyrax.config.location_service
27+
end
28+
end
29+
end

app/indexers/hyrax/valkyrie_work_indexer.rb

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ class ValkyrieWorkIndexer < Hyrax::ValkyrieIndexer
77
include Hyrax::ResourceIndexer
88
include Hyrax::PermissionIndexer
99
include Hyrax::VisibilityIndexer
10+
include Hyrax::LocationIndexer
1011
include Hyrax::ThumbnailIndexer
1112
include Hyrax::Indexer(:core_metadata)
1213

app/inputs/controlled_vocabulary_input.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def destroy_widget(attribute_name, index)
4444
def hidden_id_field(value, index)
4545
name = name_for(attribute_name, index, 'id')
4646
id = id_for(attribute_name, index, 'id')
47-
hidden_value = value.node? ? '' : value.rdf_subject
47+
hidden_value = value.try(:node?) ? '' : value.rdf_subject
4848
@builder.hidden_field(attribute_name, name: name, id: id, value: hidden_value, data: { id: 'remote' })
4949
end
5050

lib/hyrax/configuration.rb

+5
Original file line numberDiff line numberDiff line change
@@ -778,6 +778,11 @@ def geonames_username=(username)
778778
Qa::Authorities::Geonames.username = username
779779
end
780780

781+
def location_service
782+
@location_service ||= Hyrax::LocationService.new
783+
end
784+
attr_writer :location_service
785+
781786
attr_writer :active_deposit_agreement_acceptance
782787
def active_deposit_agreement_acceptance?
783788
return true if @active_deposit_agreement_acceptance.nil?

lib/hyrax/controlled_vocabularies/location.rb

+7-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,13 @@ def solrize
1414
end
1515

1616
def full_label
17-
Hyrax::LocationService.new.full_label(rdf_subject.to_s)
17+
location_service.full_label(rdf_subject.to_s)
18+
end
19+
20+
private
21+
22+
def location_service
23+
Hyrax.config.location_service
1824
end
1925
end
2026
end

lib/hyrax/form_fields.rb

+6
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@ def included(descendant)
5151
descendant.property field_name.to_sym, options.merge(display: true, default: [])
5252
descendant.validates field_name.to_sym, presence: true if options.fetch(:required, false)
5353
end
54+
55+
# Auto include any matching FormFieldBehaviors
56+
schema_name = name.to_s.camelcase
57+
behavior = "#{schema_name}FormFieldsBehavior".safe_constantize ||
58+
"Hyrax::#{schema_name}FormFieldsBehavior".safe_constantize
59+
descendant.include(behavior) if behavior
5460
end
5561
end
5662
end

lib/hyrax/specs/shared_specs/indexers.rb

+24-6
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,6 @@
8989
before do
9090
raise 'indexer_class must be set with `let(:indexer_class)`' unless defined? indexer_class
9191
raise 'resource must be set with `let(:resource)` and is expected to be a kind of Hyrax::Resource' unless defined?(resource) && resource.kind_of?(Hyrax::Resource)
92-
# optionally can pass in default_visibility by setting it with a let statement if your application changes the default; Hyrax defines this as 'restricted'
93-
# See samvera/hyrda-head hydra-access-controls/app/models/concerns/hydra/access_controls/access_rights.rb for possible VISIBILITY_TEXT_VALUE_...'
9492
end
9593
subject(:indexer) { indexer_class.new(resource: resource) }
9694
let(:thumbnail_path) { '/downloads/foo12345?file=thumbnail' }
@@ -106,6 +104,27 @@
106104
end
107105
end
108106

107+
RSpec.shared_examples 'a location indexer' do
108+
before do
109+
raise 'indexer_class must be set with `let(:indexer_class)`' unless defined? indexer_class
110+
raise 'resource must be set with `let(:resource)` and is expected to be a kind of Hyrax::Resource' unless defined?(resource) && resource.kind_of?(Hyrax::Resource)
111+
resource.based_near = based_near
112+
end
113+
subject(:indexer) { indexer_class.new(resource: resource) }
114+
let(:based_near) { ["https://sws.geonames.org/4254679/"] }
115+
let(:based_near_label) { ["Bloomington, Indiana, United States"] }
116+
117+
before do
118+
allow(Hyrax.config.location_service).to receive(:full_label).with(based_near[0]).and_return(based_near_label[0])
119+
end
120+
121+
describe '#to_solr' do
122+
it 'indexes locations' do
123+
expect(indexer.to_solr).to include(based_near_tesim: based_near, based_near_label_tesim: based_near_label)
124+
end
125+
end
126+
end
127+
109128
RSpec.shared_examples 'a Core metadata indexer' do
110129
before do
111130
raise 'indexer_class must be set with `let(:indexer_class)`' unless defined? indexer_class
@@ -138,9 +157,10 @@
138157
end
139158
subject(:indexer) { indexer_class.new(resource: resource) }
140159

160+
it_behaves_like 'a location indexer'
161+
141162
let(:attributes) do
142163
{
143-
based_near: ['helsinki', 'finland'],
144164
date_created: ['tuesday'],
145165
keyword: ['comic strip'],
146166
related_url: ['http://example.com/moomin'],
@@ -152,9 +172,7 @@
152172
describe '#to_solr' do
153173
it 'indexes basic metadata' do
154174
expect(indexer.to_solr)
155-
.to include(based_near_tesim: a_collection_containing_exactly(*attributes[:based_near]),
156-
based_near_sim: a_collection_containing_exactly(*attributes[:based_near]),
157-
date_created_tesim: a_collection_containing_exactly(*attributes[:date_created]),
175+
.to include(date_created_tesim: a_collection_containing_exactly(*attributes[:date_created]),
158176
keyword_sim: a_collection_containing_exactly(*attributes[:keyword]),
159177
related_url_tesim: a_collection_containing_exactly(*attributes[:related_url]),
160178
resource_type_tesim: a_collection_containing_exactly(*attributes[:resource_type]),

spec/forms/hyrax/forms/resource_batch_edit_form_spec.rb

+4
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@
3838
# let(:ability) { Ability.new(user) }
3939
let(:user) { build(:user, display_name: 'Jill Z. User') }
4040

41+
before do
42+
allow(Hyrax.config.location_service).to receive(:full_label) # Avoid external request to geonames
43+
end
44+
4145
describe "#terms" do
4246
subject { form.terms }
4347

spec/forms/hyrax/forms/resource_form_spec.rb

+28
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,34 @@
8686
end
8787
end
8888

89+
describe '#based_near' do
90+
subject(:form) { form_class.new(work) }
91+
92+
let(:work) { build(:monograph) }
93+
let(:geonames_uri) { "https://sws.geonames.org/4254679/" }
94+
95+
let(:form_class) do
96+
Class.new(Hyrax::Forms::ResourceForm(work.class)) do
97+
include Hyrax::FormFields(:basic_metadata)
98+
end
99+
end
100+
101+
it 'runs the based_near prepopulator' do
102+
work.based_near = [geonames_uri]
103+
form.prepopulate!
104+
expect(form.based_near)
105+
.to contain_exactly(an_instance_of(Hyrax::ControlledVocabularies::Location))
106+
end
107+
108+
it 'runs the based_near populator' do
109+
form.validate(based_near_attributes: { "0" => { "hidden_label" => geonames_uri,
110+
"id" => geonames_uri,
111+
"_destroy" => "" } })
112+
expect(form.based_near)
113+
.to contain_exactly(geonames_uri)
114+
end
115+
end
116+
89117
describe '#embargo_release_date' do
90118
context 'without an embargo' do
91119
it 'is nil' do

0 commit comments

Comments
 (0)