From a390e194e0a553693854303bab48bf5674d3965f Mon Sep 17 00:00:00 2001 From: Sarah Proctor Date: Tue, 16 Dec 2025 16:06:54 -0800 Subject: [PATCH 01/11] =?UTF-8?q?=F0=9F=90=9B=20Map=20render=5Fas=20to=20h?= =?UTF-8?q?elper=5Fmethod=20for=20index=20fields?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit adds mappings for flexible metadata properties with `render_as`` view options to Blacklight helper methods that add links in the catalog index view. - Map `render_as: 'linked'` to helper_method: :index_field_link - This method requires the field_name as an argument - Map `render_as: 'external_link'` to helper_method: :iconify_auto_link This ensures that flexible metadata fields with render_as configurations are properly displayed on the catalog index page using the appropriate helper methods. Ref: - https://github.com/notch8/wvu_knapsack/issues/102 --- .../concerns/hyrax/flexible_catalog_behavior.rb | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/app/controllers/concerns/hyrax/flexible_catalog_behavior.rb b/app/controllers/concerns/hyrax/flexible_catalog_behavior.rb index c74b1fb64a..4e6e5317c4 100644 --- a/app/controllers/concerns/hyrax/flexible_catalog_behavior.rb +++ b/app/controllers/concerns/hyrax/flexible_catalog_behavior.rb @@ -14,6 +14,7 @@ def load_flexible_schema properties_hash = current_profile['properties'] properties_hash.each do |itemprop, prop| label = display_label_for(itemprop, prop) + view_options = view_options(itemprop, prop) indexing = prop['indexing'] next if indexing.nil? @@ -28,6 +29,16 @@ def load_flexible_schema index_args[:link_to_facet] = "#{itemprop}_sim" end + # Add helper_method for render_as if it exists in the view options + render_as = view_options&.dig('render_as') + case render_as + when 'linked' + index_args[:helper_method] = :index_field_link + index_args[:field_name] = itemprop + when 'external_link' + index_args[:helper_method] = :iconify_auto_link + end + name = blacklight_config.index_fields.keys.detect { |key| key.start_with?(itemprop) } name ||= "#{itemprop}_tesim" @@ -38,6 +49,7 @@ def load_flexible_schema end blacklight_config.index_fields[name].itemprop = itemprop else + # if a field doesn't exist in the config, add it blacklight_config.add_index_field(name, index_args) end @@ -63,6 +75,10 @@ def load_flexible_schema private + def view_options(_itemprop, prop) + prop.fetch('view', {})&.with_indifferent_access || {} + end + def display_label_for(field_name, config) display_label = config.fetch('display_label', {})&.with_indifferent_access || {} display_label = { default: display_label } if display_label.is_a?(String) From 46381c040987fa5941f2ce5e249008099b8673e0 Mon Sep 17 00:00:00 2001 From: Sarah Proctor Date: Wed, 17 Dec 2025 15:53:41 -0800 Subject: [PATCH 02/11] =?UTF-8?q?=F0=9F=90=9B=20Metadata=20view.render=5Fa?= =?UTF-8?q?s=20links=20on=20catalog=20index?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit adds helper methods from Hyrax::HyraxHelperBehavior to the flexible metadata properties that have a `view.render_as` value of `linked`, `external_link`, or `rights_statement`. Prior to this change, the properties were receiving their view rendering behavior from the CatalogController. Any new metadata properties had no view rendering behavior and would only display plain text. Properties that were already defined in the CatalogController could not have their view rendering behavior changed via flexible metadata profile. This commit also adds `if: :render_in_tenant?` to all metadata properties that are not defined in the CatalogController. This ensures the properties can be excluded from the catalog index view via tenant configuration in the admin dashboard > Settings > Accounts > Hidden index fields. NOTE: This approach to hiding catalog index fields will likely be deprecated in favor of handling it via the flexible metadata profile. Ref: - https://github.com/samvera/hyku/issues/2860 --- .../hyrax/flexible_catalog_behavior.rb | 51 ++++++++++++++----- 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/app/controllers/concerns/hyrax/flexible_catalog_behavior.rb b/app/controllers/concerns/hyrax/flexible_catalog_behavior.rb index 4e6e5317c4..7bfa31da4a 100644 --- a/app/controllers/concerns/hyrax/flexible_catalog_behavior.rb +++ b/app/controllers/concerns/hyrax/flexible_catalog_behavior.rb @@ -14,7 +14,8 @@ def load_flexible_schema properties_hash = current_profile['properties'] properties_hash.each do |itemprop, prop| label = display_label_for(itemprop, prop) - view_options = view_options(itemprop, prop) + + view_options = prop['view'] indexing = prop['indexing'] next if indexing.nil? @@ -29,16 +30,6 @@ def load_flexible_schema index_args[:link_to_facet] = "#{itemprop}_sim" end - # Add helper_method for render_as if it exists in the view options - render_as = view_options&.dig('render_as') - case render_as - when 'linked' - index_args[:helper_method] = :index_field_link - index_args[:field_name] = itemprop - when 'external_link' - index_args[:helper_method] = :iconify_auto_link - end - name = blacklight_config.index_fields.keys.detect { |key| key.start_with?(itemprop) } name ||= "#{itemprop}_tesim" @@ -48,9 +39,28 @@ def load_flexible_schema blacklight_config.index_fields[name].custom_label = true end blacklight_config.index_fields[name].itemprop = itemprop + # for properties that DO exist in the CatalogController + if require_view_helper_method?(view_options) + # add or update the helper method so linked fields will render correctly in the index view + blacklight_config.index_fields[name].helper_method = view_option_for_helper_method(view_options) + # the helper method for index_field_link needs the field name + blacklight_config.index_fields[name].field_name = itemprop + end else - # if a field doesn't exist in the config, add it + # for properties that DO NOT exist in the catalog controller + if require_view_helper_method?(view_options) + # add the view helper method to the arguments hash when creating a property + index_args[:helper_method] = view_option_for_helper_method(view_options) + # the helper method for index_field_link needs the field name + index_args[:field_name] = itemprop + end + # if a property in the metadata profile doesn't exist in the CatalogController, add it blacklight_config.add_index_field(name, index_args) + + # all index fields get this property so an admin can hide a property from the catalog search results + # by adding the name of the property via admin dashboard > Settings > Accounts > Hidden index fields + # NOTE: it is likely this will be handled by the metadata profile in the future + blacklight_config.index_fields[name].if = :render_in_tenant? end qf = blacklight_config.search_fields['all_fields'].solr_parameters[:qf] @@ -75,8 +85,21 @@ def load_flexible_schema private - def view_options(_itemprop, prop) - prop.fetch('view', {})&.with_indifferent_access || {} + # Returns true if the view options require a helper method to render the linked field correctly in the index view + # @param view_options [Hash] the view options ex: {"render_as"=>"linked", "html_dl"=>true} + # @return [Boolean] to determine if the view_option_for_helper_method should be called + def require_view_helper_method?(view_options) + view_options.present? && %w[external_link linked rights_statement].include?(view_options.dig('render_as')) + end + + # Returns the helper method that will render the linked field correctly in the index view + # @param view_options [Hash] the view options ex: {"render_as"=>"linked", "html_dl"=>true} + # @return [Symbol] helper method from Hyrax::HyraxHelperBehavior + def view_option_for_helper_method(view_options) + render_as = view_options.dig('render_as') + return :iconify_auto_link if render_as == 'external_link' + return :index_field_link if render_as == 'linked' + return :rights_statement_links if render_as == 'rights_statement' end def display_label_for(field_name, config) From 07e4b7d8d3e78612f327e976007126507693c5d4 Mon Sep 17 00:00:00 2001 From: Sarah Proctor Date: Mon, 22 Dec 2025 13:51:40 -0800 Subject: [PATCH 03/11] =?UTF-8?q?=F0=9F=9A=A7=20WIP:=20Adds=20specs=20for?= =?UTF-8?q?=20loading=20flexible=20schema?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hyrax/flexible_catalog_behavior.rb | 5 +- .../hyrax/flexible_catalog_behavior_spec.rb | 371 ++++++++++++++++++ 2 files changed, 375 insertions(+), 1 deletion(-) create mode 100644 spec/controllers/concerns/hyrax/flexible_catalog_behavior_spec.rb diff --git a/app/controllers/concerns/hyrax/flexible_catalog_behavior.rb b/app/controllers/concerns/hyrax/flexible_catalog_behavior.rb index 7bfa31da4a..31ba47b1b4 100644 --- a/app/controllers/concerns/hyrax/flexible_catalog_behavior.rb +++ b/app/controllers/concerns/hyrax/flexible_catalog_behavior.rb @@ -32,7 +32,9 @@ def load_flexible_schema name = blacklight_config.index_fields.keys.detect { |key| key.start_with?(itemprop) } name ||= "#{itemprop}_tesim" - + # blacklight_config.index_fields.keys + # ["all_text_timv", "all_text_tsimv", "title_tesim", "description_tesim", "keyword_tesim", "subject_tesim", "creator_tesim", "date_tesim", "contributor_tesim", "proxy_depositor_ssim", "depositor_tesim", "publisher_tesim", "based_near_label_tesim", "language_tesim", "date_uploaded_dtsi", "date_modified_dtsi", "date_created_tesim", "rights_statement_tesim", "license_tesim", "resource_type_tesim", "file_format_tesim", "identifier_tesim", "related_url_tesim", "embargo_release_date_dtsi", "lease_expiration_date_dtsi", "learning_resource_type_tesim", "education_level_tesim", "audience_tesim", "discipline_tesim"] +# debugger if blacklight_config.index_fields[name].present? if label blacklight_config.index_fields[name].label = I18n.t(label, default: label) @@ -56,6 +58,7 @@ def load_flexible_schema end # if a property in the metadata profile doesn't exist in the CatalogController, add it blacklight_config.add_index_field(name, index_args) +# RuntimeError Exception: A index_field with the key depositor_tesim already exists. # all index fields get this property so an admin can hide a property from the catalog search results # by adding the name of the property via admin dashboard > Settings > Accounts > Hidden index fields diff --git a/spec/controllers/concerns/hyrax/flexible_catalog_behavior_spec.rb b/spec/controllers/concerns/hyrax/flexible_catalog_behavior_spec.rb new file mode 100644 index 0000000000..c0b4e1fc03 --- /dev/null +++ b/spec/controllers/concerns/hyrax/flexible_catalog_behavior_spec.rb @@ -0,0 +1,371 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe Hyrax::FlexibleCatalogBehavior, type: :controller do + let(:base_profile) { YAML.safe_load_file(Hyrax::Engine.root.join('spec', 'fixtures', 'files', 'm3_profile.yaml')) } + + let(:custom_properties) do + YAML.safe_load(<<-YAML) + properties: + publication_date: + available_on: + class: + - GenericWork + - Monograph + display_label: + default: Publication Date + indexing: + - stored_searchable + - facetable + property_uri: http://purl.org/dc/terms/date + range: http://www.w3.org/2001/XMLSchema#string + department: + available_on: + class: + - GenericWork + display_label: + default: Department + indexing: + - department_tesim + - department_sim + - facetable + property_uri: http://example.org/department + range: http://www.w3.org/2001/XMLSchema#string + view: + html_dl: true + external_link: + available_on: + class: + - GenericWork + - Monograph + display_label: + default: External Link + indexing: + - external_link_tesim + - external_link_sim + property_uri: http://example.org/external_link + range: http://www.w3.org/2001/XMLSchema#string + view: + render_as: external_link + html_dl: true + related_resource: + available_on: + class: + - GenericWork + - Monograph + display_label: + default: Related Resource + indexing: + - related_resource_tesim + - related_resource_sim + property_uri: http://purl.org/dc/terms/relation + range: http://www.w3.org/2001/XMLSchema#string + view: + render_as: linked + html_dl: true + YAML + end + + before do + # Clean up any existing schemas + Hyrax::FlexibleSchema.destroy_all + + # Enable flexible metadata + allow(Hyrax.config).to receive(:flexible?).and_return(true) + end + + after do + Hyrax::FlexibleSchema.destroy_all + end + + controller(ApplicationController) do + include Blacklight::Configurable + include Blacklight::SearchContext + include Hyrax::FlexibleCatalogBehavior # rubocop:disable RSpec/DescribedClass + + configure_blacklight do |config| + config.search_builder_class = Hyrax::CatalogSearchBuilder + config.default_solr_params = { qt: 'search', rows: 10 } + + # Start with a clean blacklight config - no pre-existing index fields + # This tests the scenario where all properties need to be added dynamically + config.add_search_field('all_fields') do |field| + field.solr_parameters = { qf: String.new('') } + end + end + + def index + @response = Blacklight::Solr::Response.new({}, {}) + render plain: 'OK' + end + end + + describe 'loading flexible metadata profile' do + before do + routes.draw { get 'index' => 'anonymous#index' } + end + + before do + # Create the schema in the database by merging base profile with custom properties + Hyrax::FlexibleSchema.create!(profile: base_profile.deep_merge(custom_properties)) + + # Manually trigger load_flexible_schema since it's a class method that runs once + # We need to call it after the schema is created + controller.class.load_flexible_schema + + get :index + blacklight_config = controller.blacklight_config + end + + + # title - has indexing: title_sim, title_tesim (facetable) + # date_modified - no indexing defined + # date_uploaded - no indexing defined + # depositor - has indexing: depositor_tesim, depositor_ssim + # creator - has indexing: creator_sim, creator_tesim (facetable) + # label - has indexing: label_sim, label_tesim (facetable) + # keyword - has indexing: keyword_sim, keyword_tesim (facetable), has view: render_as: "faceted" + # abstract - has indexing: abstract_sim, abstract_tesim (facetable) + # publication_date - has indexing: publication_date_tesim, publication_date_sim (facetable) + # department - has indexing: department_tesim, department_sim (facetable) + # external_link - has indexing: external_link_tesim, external_link_sim + # related_resource - has indexing: related_resource_tesim, related_resource_sim + + + + it 'loads flexible schema properties into blacklight config' do +# +# + + + expect(blacklight_config.index_fields).to have_key('title_tesim') + expect(blacklight_config.index_fields).to have_key('depositor_tesim') + expect(blacklight_config.index_fields).to have_key('creator_tesim') + expect(blacklight_config.index_fields).to have_key('label_tesim') + expect(blacklight_config.index_fields).to have_key('keyword_tesim') + expect(blacklight_config.index_fields).to have_key('abstract_tesim') + expect(blacklight_config.index_fields).to have_key('publication_date_tesim') + expect(blacklight_config.index_fields).to have_key('department_tesim') + expect(blacklight_config.index_fields).to have_key('external_link_tesim') + expect(blacklight_config.index_fields).to have_key('related_resource_tesim') + end + + it 'sets correct labels for index fields' do + get :index + + blacklight_config = controller.blacklight_config + + expect(blacklight_config.index_fields['title_tesim'].label).to eq('Title') + expect(blacklight_config.index_fields['depositor_tesim'].label).to eq('Depositor') + expect(blacklight_config.index_fields['creator_tesim'].label).to eq('Creator') + expect(blacklight_config.index_fields['label_tesim'].label).to eq('Label') + expect(blacklight_config.index_fields['keyword_tesim'].label).to eq('Keyword') + expect(blacklight_config.index_fields['abstract_tesim'].label).to eq('Abstract') + expect(blacklight_config.index_fields['publication_date_tesim'].label).to eq('Publication Date') + expect(blacklight_config.index_fields['department_tesim'].label).to eq('Department') + expect(blacklight_config.index_fields['external_link_tesim'].label).to eq('External Link') + expect(blacklight_config.index_fields['publication_date_tesim'].label).to eq('Publication Date') + expect(blacklight_config.index_fields['department_tesim'].label).to eq('Department') + expect(blacklight_config.index_fields['external_link_tesim'].label).to eq('External Link') + expect(blacklight_config.index_fields['related_resource_tesim'].label).to eq('Related Resource') + end + + it 'sets itemprop for index fields' do + get :index + + blacklight_config = controller.blacklight_config + + expect(blacklight_config.index_fields['title_tesim'].itemprop).to eq('title') + expect(blacklight_config.index_fields['author_name_tesim'].itemprop).to eq('author_name') + expect(blacklight_config.index_fields['publication_date_tesim'].itemprop).to eq('publication_date') + end + + it 'adds facet fields for facetable properties' do + get :index + + blacklight_config = controller.blacklight_config + + # Verify facet fields are added for facetable properties + expect(blacklight_config.facet_fields).to have_key('title_sim') + expect(blacklight_config.facet_fields).to have_key('publication_date_sim') + expect(blacklight_config.facet_fields).to have_key('department_sim') + + # Verify non-facetable properties don't have facet fields + expect(blacklight_config.facet_fields).not_to have_key('author_name_sim') + expect(blacklight_config.facet_fields).not_to have_key('external_link_sim') + end + + it 'sets link_to_facet for facetable index fields' do + get :index + + blacklight_config = controller.blacklight_config + + expect(blacklight_config.index_fields['title_tesim'].link_to_facet).to eq('title_sim') + expect(blacklight_config.index_fields['publication_date_tesim'].link_to_facet).to eq('publication_date_sim') + expect(blacklight_config.index_fields['department_tesim'].link_to_facet).to eq('department_sim') + end + + it 'adds properties to search qf parameter' do + get :index + + blacklight_config = controller.blacklight_config + qf = blacklight_config.search_fields['all_fields'].solr_parameters[:qf] + + # Verify all 6 custom properties are added to the search query fields + expect(qf).to include('title_tesim') + expect(qf).to include('author_name_tesim') + expect(qf).to include('publication_date_tesim') + expect(qf).to include('department_tesim') + expect(qf).to include('external_link_tesim') + expect(qf).to include('related_resource_tesim') + end + + it 'sets helper methods for fields with render_as view options' do + get :index + + blacklight_config = controller.blacklight_config + + # External link should have iconify_auto_link helper + expect(blacklight_config.index_fields['external_link_tesim'].helper_method).to eq(:iconify_auto_link) + expect(blacklight_config.index_fields['external_link_tesim'].field_name).to eq('external_link') + + # Related resource should have index_field_link helper + expect(blacklight_config.index_fields['related_resource_tesim'].helper_method).to eq(:index_field_link) + expect(blacklight_config.index_fields['related_resource_tesim'].field_name).to eq('related_resource') + + # Regular fields should not have helper methods + expect(blacklight_config.index_fields['author_name_tesim'].helper_method).to be_nil + end + + it 'sets render_in_tenant? condition for all dynamically added index fields' do + get :index + + blacklight_config = controller.blacklight_config + + # All dynamically added fields should have the render_in_tenant? condition + # This allows admins to hide properties from catalog search results + expect(blacklight_config.index_fields['title_tesim'].if).to eq(:render_in_tenant?) + expect(blacklight_config.index_fields['author_name_tesim'].if).to eq(:render_in_tenant?) + expect(blacklight_config.index_fields['publication_date_tesim'].if).to eq(:render_in_tenant?) + expect(blacklight_config.index_fields['department_tesim'].if).to eq(:render_in_tenant?) + expect(blacklight_config.index_fields['external_link_tesim'].if).to eq(:render_in_tenant?) + expect(blacklight_config.index_fields['related_resource_tesim'].if).to eq(:render_in_tenant?) + end + end + + describe '.display_label_for' do + it 'returns the display label from the config' do + label = controller.class.send(:display_label_for, 'test_field', + { 'display_label' => { 'default' => 'Test Label' } }) + expect(label).to eq('Test Label') + end + + it 'returns humanized field name when display_label is blank' do + label = controller.class.send(:display_label_for, 'test_field', {}) + expect(label).to eq('Test field') + end + + it 'uses locale-specific label when available' do + I18n.with_locale(:es) do + label = controller.class.send(:display_label_for, 'test_field', + { 'display_label' => { 'default' => 'Test Label', 'es' => 'Etiqueta de prueba' } }) + expect(label).to eq('Etiqueta de prueba') + end + end + + it 'falls back to default when locale-specific label is not available' do + I18n.with_locale(:fr) do + label = controller.class.send(:display_label_for, 'test_field', + { 'display_label' => { 'default' => 'Test Label', 'es' => 'Etiqueta de prueba' } }) + expect(label).to eq('Test Label') + end + end + end + + describe '.stored_searchable?' do + it 'returns true when indexing includes stored_searchable' do + result = controller.class.send(:stored_searchable?, ['stored_searchable'], 'test_field') + expect(result).to be true + end + + it 'returns true when indexing includes field_tesim' do + result = controller.class.send(:stored_searchable?, ['test_field_tesim'], 'test_field') + expect(result).to be true + end + + it 'returns false when neither condition is met' do + result = controller.class.send(:stored_searchable?, ['facetable'], 'test_field') + expect(result).to be false + end + end + + describe '.facetable?' do + it 'returns true when indexing includes facetable' do + result = controller.class.send(:facetable?, ['facetable'], 'test_field') + expect(result).to be true + end + + it 'returns false when indexing does not include facetable' do + result = controller.class.send(:facetable?, ['stored_searchable'], 'test_field') + expect(result).to be false + end + end + + describe '.admin_only?' do + it 'returns true when indexing includes admin_only' do + result = controller.class.send(:admin_only?, ['admin_only', 'stored_searchable']) + expect(result).to be true + end + + it 'returns false when indexing does not include admin_only' do + result = controller.class.send(:admin_only?, ['stored_searchable']) + expect(result).to be false + end + end + + describe '.require_view_helper_method?' do + it 'returns true for external_link render_as' do + result = controller.class.send(:require_view_helper_method?, { 'render_as' => 'external_link' }) + expect(result).to be true + end + + it 'returns true for linked render_as' do + result = controller.class.send(:require_view_helper_method?, { 'render_as' => 'linked' }) + expect(result).to be true + end + + it 'returns true for rights_statement render_as' do + result = controller.class.send(:require_view_helper_method?, { 'render_as' => 'rights_statement' }) + expect(result).to be true + end + + it 'returns false for other render_as values' do + result = controller.class.send(:require_view_helper_method?, { 'render_as' => 'faceted' }) + expect(result).to be false + end + + it 'returns false when view_options is nil' do + result = controller.class.send(:require_view_helper_method?, nil) + expect(result).to be false + end + end + + describe '.view_option_for_helper_method' do + it 'returns :iconify_auto_link for external_link' do + result = controller.class.send(:view_option_for_helper_method, { 'render_as' => 'external_link' }) + expect(result).to eq(:iconify_auto_link) + end + + it 'returns :index_field_link for linked' do + result = controller.class.send(:view_option_for_helper_method, { 'render_as' => 'linked' }) + expect(result).to eq(:index_field_link) + end + + it 'returns :rights_statement_links for rights_statement' do + result = controller.class.send(:view_option_for_helper_method, { 'render_as' => 'rights_statement' }) + expect(result).to eq(:rights_statement_links) + end + end +end + From a622249e40e57cc82d7d7c82b0e78da23ee77006 Mon Sep 17 00:00:00 2001 From: Sarah Proctor Date: Tue, 23 Dec 2025 12:06:15 -0800 Subject: [PATCH 04/11] =?UTF-8?q?=E2=9A=99=EF=B8=8F=20Moves=20facetable=20?= =?UTF-8?q?from=20render=5Fas=20to=20indexing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit updates the m3 profile spec fixture to specify sidebar faceting in the indexing section rather than the render_as section. Ref: - https://github.com/samvera/hyku/issues/2860 --- spec/fixtures/files/m3_profile.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/fixtures/files/m3_profile.yaml b/spec/fixtures/files/m3_profile.yaml index c88f711b38..b8a3f84012 100644 --- a/spec/fixtures/files/m3_profile.yaml +++ b/spec/fixtures/files/m3_profile.yaml @@ -184,6 +184,7 @@ properties: indexing: - keyword_sim - keyword_tesim + - facetable form: primary: false property_uri: http://schema.org/keywords @@ -192,7 +193,6 @@ properties: - Metadata - Repository view: - render_as: "faceted" html_dl: true abstract: available_on: From 3e7850af68a82fbf70fe200610ec945af72f91ac Mon Sep 17 00:00:00 2001 From: Sarah Proctor Date: Tue, 23 Dec 2025 12:08:12 -0800 Subject: [PATCH 05/11] =?UTF-8?q?=E2=9C=85=20=20Spec=20for=20FlexibleCatal?= =?UTF-8?q?ogBehavior?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add test coverage for FlexibleCatalogBehavior concern which dynamically loads M3 metadata profile properties into Blacklight catalog config. Tests both fixture and custom properties to verify the concern handles: - Index field creation and updates - Display labels - Itemprop mapping for semantic markup - Helper methods for linked/external link rendering - Facet field creation and linking - Search field parameter additions - Admin visibility controls Ref: - https://github.com/samvera/hyku/issues/2860 --- .../hyrax/flexible_catalog_behavior_spec.rb | 252 ++++++++---------- 1 file changed, 104 insertions(+), 148 deletions(-) diff --git a/spec/controllers/concerns/hyrax/flexible_catalog_behavior_spec.rb b/spec/controllers/concerns/hyrax/flexible_catalog_behavior_spec.rb index c0b4e1fc03..dfba5b3d7e 100644 --- a/spec/controllers/concerns/hyrax/flexible_catalog_behavior_spec.rb +++ b/spec/controllers/concerns/hyrax/flexible_catalog_behavior_spec.rb @@ -5,6 +5,9 @@ RSpec.describe Hyrax::FlexibleCatalogBehavior, type: :controller do let(:base_profile) { YAML.safe_load_file(Hyrax::Engine.root.join('spec', 'fixtures', 'files', 'm3_profile.yaml')) } + # adds additional properties to the base profile to + # include properties that do not exist in the blacklight + # config with various indexing and view options let(:custom_properties) do YAML.safe_load(<<-YAML) properties: @@ -34,31 +37,31 @@ range: http://www.w3.org/2001/XMLSchema#string view: html_dl: true - external_link: + related_resource: available_on: class: - GenericWork - Monograph display_label: - default: External Link + default: Related Resource indexing: - - external_link_tesim - - external_link_sim - property_uri: http://example.org/external_link + - related_resource_tesim + - related_resource_sim + property_uri: http://example.org/related_resource range: http://www.w3.org/2001/XMLSchema#string view: render_as: external_link html_dl: true - related_resource: + medium: available_on: class: - GenericWork - Monograph display_label: - default: Related Resource + default: Medium indexing: - - related_resource_tesim - - related_resource_sim + - medium_tesim + - medium_sim property_uri: http://purl.org/dc/terms/relation range: http://www.w3.org/2001/XMLSchema#string view: @@ -67,29 +70,16 @@ YAML end - before do - # Clean up any existing schemas - Hyrax::FlexibleSchema.destroy_all - - # Enable flexible metadata - allow(Hyrax.config).to receive(:flexible?).and_return(true) - end - - after do - Hyrax::FlexibleSchema.destroy_all - end - controller(ApplicationController) do include Blacklight::Configurable include Blacklight::SearchContext - include Hyrax::FlexibleCatalogBehavior # rubocop:disable RSpec/DescribedClass + include Hyrax::FlexibleCatalogBehavior configure_blacklight do |config| config.search_builder_class = Hyrax::CatalogSearchBuilder config.default_solr_params = { qt: 'search', rows: 10 } - # Start with a clean blacklight config - no pre-existing index fields - # This tests the scenario where all properties need to be added dynamically + # tests the scenario where all properties need to be added dynamically config.add_search_field('all_fields') do |field| field.solr_parameters = { qf: String.new('') } end @@ -103,154 +93,121 @@ def index describe 'loading flexible metadata profile' do before do + # ensure flexible metadata is enabled + allow(Hyrax.config).to receive(:flexible?).and_return(true) + + # set up routes for the anonymous controller routes.draw { get 'index' => 'anonymous#index' } - end - before do - # Create the schema in the database by merging base profile with custom properties + # create the schema in the database by merging base profile with custom properties Hyrax::FlexibleSchema.create!(profile: base_profile.deep_merge(custom_properties)) - # Manually trigger load_flexible_schema since it's a class method that runs once - # We need to call it after the schema is created + # manually trigger load_flexible_schema since it's a class method controller.class.load_flexible_schema - - get :index - blacklight_config = controller.blacklight_config end - - # title - has indexing: title_sim, title_tesim (facetable) - # date_modified - no indexing defined - # date_uploaded - no indexing defined - # depositor - has indexing: depositor_tesim, depositor_ssim - # creator - has indexing: creator_sim, creator_tesim (facetable) - # label - has indexing: label_sim, label_tesim (facetable) - # keyword - has indexing: keyword_sim, keyword_tesim (facetable), has view: render_as: "faceted" - # abstract - has indexing: abstract_sim, abstract_tesim (facetable) - # publication_date - has indexing: publication_date_tesim, publication_date_sim (facetable) - # department - has indexing: department_tesim, department_sim (facetable) - # external_link - has indexing: external_link_tesim, external_link_sim - # related_resource - has indexing: related_resource_tesim, related_resource_sim - - - - it 'loads flexible schema properties into blacklight config' do -# -# - - - expect(blacklight_config.index_fields).to have_key('title_tesim') - expect(blacklight_config.index_fields).to have_key('depositor_tesim') - expect(blacklight_config.index_fields).to have_key('creator_tesim') - expect(blacklight_config.index_fields).to have_key('label_tesim') - expect(blacklight_config.index_fields).to have_key('keyword_tesim') - expect(blacklight_config.index_fields).to have_key('abstract_tesim') - expect(blacklight_config.index_fields).to have_key('publication_date_tesim') - expect(blacklight_config.index_fields).to have_key('department_tesim') - expect(blacklight_config.index_fields).to have_key('external_link_tesim') - expect(blacklight_config.index_fields).to have_key('related_resource_tesim') - end - - it 'sets correct labels for index fields' do - get :index - - blacklight_config = controller.blacklight_config - - expect(blacklight_config.index_fields['title_tesim'].label).to eq('Title') - expect(blacklight_config.index_fields['depositor_tesim'].label).to eq('Depositor') - expect(blacklight_config.index_fields['creator_tesim'].label).to eq('Creator') - expect(blacklight_config.index_fields['label_tesim'].label).to eq('Label') - expect(blacklight_config.index_fields['keyword_tesim'].label).to eq('Keyword') - expect(blacklight_config.index_fields['abstract_tesim'].label).to eq('Abstract') - expect(blacklight_config.index_fields['publication_date_tesim'].label).to eq('Publication Date') - expect(blacklight_config.index_fields['department_tesim'].label).to eq('Department') - expect(blacklight_config.index_fields['external_link_tesim'].label).to eq('External Link') - expect(blacklight_config.index_fields['publication_date_tesim'].label).to eq('Publication Date') - expect(blacklight_config.index_fields['department_tesim'].label).to eq('Department') - expect(blacklight_config.index_fields['external_link_tesim'].label).to eq('External Link') - expect(blacklight_config.index_fields['related_resource_tesim'].label).to eq('Related Resource') + after do + # clean up created schemas after each test + Hyrax::FlexibleSchema.destroy_all end - it 'sets itemprop for index fields' do + let(:blacklight_config) do get :index - - blacklight_config = controller.blacklight_config - - expect(blacklight_config.index_fields['title_tesim'].itemprop).to eq('title') - expect(blacklight_config.index_fields['author_name_tesim'].itemprop).to eq('author_name') - expect(blacklight_config.index_fields['publication_date_tesim'].itemprop).to eq('publication_date') + controller.blacklight_config end - it 'adds facet fields for facetable properties' do - get :index - - blacklight_config = controller.blacklight_config - - # Verify facet fields are added for facetable properties - expect(blacklight_config.facet_fields).to have_key('title_sim') - expect(blacklight_config.facet_fields).to have_key('publication_date_sim') - expect(blacklight_config.facet_fields).to have_key('department_sim') + context 'properties with indexing' do + it 'are checked for existence in the blacklight config' do + # metadata properties from spec/fixtures/files/m3_profile.yaml + %w[title_tesim depositor_tesim creator_tesim label_tesim keyword_tesim abstract_tesim].each do |field| + expect(blacklight_config.index_fields).to have_key(field) + end + end - # Verify non-facetable properties don't have facet fields - expect(blacklight_config.facet_fields).not_to have_key('author_name_sim') - expect(blacklight_config.facet_fields).not_to have_key('external_link_sim') - end + it 'are added to the blacklight config' do + # metadata properties from custom_properties should be added then checked for existence in the blacklight config + %w[publication_date_tesim department_tesim related_resource_tesim medium_tesim].each do |field| + expect(blacklight_config.index_fields).to have_key(field) + end + end - it 'sets link_to_facet for facetable index fields' do - get :index + it 'have a label property in blacklight config' do + # gets the display_label from the metadata profile and adds it as the label attribute in blacklight config + expected_labels = { + 'depositor_tesim' => 'Depositor', + 'creator_tesim' => 'Creator', + 'label_tesim' => 'Label', + 'abstract_tesim' => 'Abstract', + 'department_tesim' => 'Department', + 'publication_date_tesim' => 'Publication Date', + 'medium_tesim' => 'Medium', + 'related_resource_tesim' => 'Related Resource' + } + + expected_labels.each do |field, label| + expect(blacklight_config.index_fields[field].label).to eq(label) + end + end - blacklight_config = controller.blacklight_config + it 'have an itemprop property added to the blacklight config' do + # itemprop is the property name that gets mapped to the Solr field name + %w[title depositor creator label abstract publication_date department related_resource medium].each do |field| + expect(blacklight_config.index_fields[field + '_tesim'].itemprop).to eq(field) + end + end - expect(blacklight_config.index_fields['title_tesim'].link_to_facet).to eq('title_sim') - expect(blacklight_config.index_fields['publication_date_tesim'].link_to_facet).to eq('publication_date_sim') - expect(blacklight_config.index_fields['department_tesim'].link_to_facet).to eq('department_sim') - end + it 'adds helper methods for properties with render_as view options' do + # related_resource_tesim should have iconify_auto_link helper + expect(blacklight_config.index_fields['related_resource_tesim'].helper_method).to eq(:iconify_auto_link) + expect(blacklight_config.index_fields['related_resource_tesim'].field_name).to eq('related_resource') - it 'adds properties to search qf parameter' do - get :index + # medium_tesim should have index_field_link helper + expect(blacklight_config.index_fields['medium_tesim'].helper_method).to eq(:index_field_link) + expect(blacklight_config.index_fields['medium_tesim'].field_name).to eq('medium') - blacklight_config = controller.blacklight_config - qf = blacklight_config.search_fields['all_fields'].solr_parameters[:qf] + # department_tesim should not have helper methods + expect(blacklight_config.index_fields['department_tesim'].helper_method).to be_nil + end - # Verify all 6 custom properties are added to the search query fields - expect(qf).to include('title_tesim') - expect(qf).to include('author_name_tesim') - expect(qf).to include('publication_date_tesim') - expect(qf).to include('department_tesim') - expect(qf).to include('external_link_tesim') - expect(qf).to include('related_resource_tesim') + it 'have the render_in_tenant? condition added to the blacklight config' do + # all fields should have the render_in_tenant? condition + # this allows admins to hide properties from catalog search results via the UI + %w[publication_date_tesim department_tesim related_resource_tesim medium_tesim].each do |field| + expect(blacklight_config.index_fields[field].if).to eq(:render_in_tenant?) + end + end end - it 'sets helper methods for fields with render_as view options' do - get :index - - blacklight_config = controller.blacklight_config - - # External link should have iconify_auto_link helper - expect(blacklight_config.index_fields['external_link_tesim'].helper_method).to eq(:iconify_auto_link) - expect(blacklight_config.index_fields['external_link_tesim'].field_name).to eq('external_link') - - # Related resource should have index_field_link helper - expect(blacklight_config.index_fields['related_resource_tesim'].helper_method).to eq(:index_field_link) - expect(blacklight_config.index_fields['related_resource_tesim'].field_name).to eq('related_resource') + context 'properties with sidebar faceting' do + it 'have a facet field added to the blacklight config' do + # if the property has facetable in the indexing section of the metadata profile, ensure the _sim field is added to the blacklight config + %w[keyword publication_date department].each do |field| + expect(blacklight_config.facet_fields).to have_key(field + '_sim') + end + + # verify non-facetable properties don't have facet fields + %w[related_resource medium].each do |field| + expect(blacklight_config.facet_fields).not_to have_key(field + '_sim') + end + end - # Regular fields should not have helper methods - expect(blacklight_config.index_fields['author_name_tesim'].helper_method).to be_nil + it 'have a link_to_facet property added to the blacklight config' do + # if the property has render_as: linked ensure the link_to_facet has the _sim field name + %w[keyword publication_date department].each do |field| + expect(blacklight_config.index_fields[field + '_tesim'].link_to_facet).to eq(field + '_sim') + end + end end - it 'sets render_in_tenant? condition for all dynamically added index fields' do - get :index - - blacklight_config = controller.blacklight_config + context 'search fields' do + it 'have the properties added to the search qf parameter' do + qf = blacklight_config.search_fields['all_fields'].solr_parameters[:qf] - # All dynamically added fields should have the render_in_tenant? condition - # This allows admins to hide properties from catalog search results - expect(blacklight_config.index_fields['title_tesim'].if).to eq(:render_in_tenant?) - expect(blacklight_config.index_fields['author_name_tesim'].if).to eq(:render_in_tenant?) - expect(blacklight_config.index_fields['publication_date_tesim'].if).to eq(:render_in_tenant?) - expect(blacklight_config.index_fields['department_tesim'].if).to eq(:render_in_tenant?) - expect(blacklight_config.index_fields['external_link_tesim'].if).to eq(:render_in_tenant?) - expect(blacklight_config.index_fields['related_resource_tesim'].if).to eq(:render_in_tenant?) + # verify the custom_properties are added to the search query fields + %w[title_tesim publication_date_tesim department_tesim related_resource_tesim medium_tesim].each do |field| + expect(qf).to include(field) + end + end end end @@ -368,4 +325,3 @@ def index end end end - From ebd9a8e6c8dcbc504d0cbbbab2515df4a600a668 Mon Sep 17 00:00:00 2001 From: Sarah Proctor Date: Tue, 23 Dec 2025 12:29:50 -0800 Subject: [PATCH 06/11] =?UTF-8?q?=F0=9F=90=9B=20facetable=20deafults=20in?= =?UTF-8?q?=20load=5Fflexible=5Fschema?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If a property has a `facet_field` in the CatalogController it will render on the sidebar as a facet even if the flexible metadata profile does not specify it as a facetable property. This commit removes `facet_field` from any property that does not specify `indexing.facetable` Ref: - https://github.com/samvera/hyku/issues/2792 --- .../hyrax/flexible_catalog_behavior.rb | 21 ++++++++++--------- .../hyrax/flexible_catalog_behavior_spec.rb | 16 ++++++++++++++ 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/app/controllers/concerns/hyrax/flexible_catalog_behavior.rb b/app/controllers/concerns/hyrax/flexible_catalog_behavior.rb index 31ba47b1b4..0ef42a9af4 100644 --- a/app/controllers/concerns/hyrax/flexible_catalog_behavior.rb +++ b/app/controllers/concerns/hyrax/flexible_catalog_behavior.rb @@ -32,16 +32,15 @@ def load_flexible_schema name = blacklight_config.index_fields.keys.detect { |key| key.start_with?(itemprop) } name ||= "#{itemprop}_tesim" - # blacklight_config.index_fields.keys - # ["all_text_timv", "all_text_tsimv", "title_tesim", "description_tesim", "keyword_tesim", "subject_tesim", "creator_tesim", "date_tesim", "contributor_tesim", "proxy_depositor_ssim", "depositor_tesim", "publisher_tesim", "based_near_label_tesim", "language_tesim", "date_uploaded_dtsi", "date_modified_dtsi", "date_created_tesim", "rights_statement_tesim", "license_tesim", "resource_type_tesim", "file_format_tesim", "identifier_tesim", "related_url_tesim", "embargo_release_date_dtsi", "lease_expiration_date_dtsi", "learning_resource_type_tesim", "education_level_tesim", "audience_tesim", "discipline_tesim"] -# debugger + + # for properties that DO exist in the CatalogController if blacklight_config.index_fields[name].present? if label blacklight_config.index_fields[name].label = I18n.t(label, default: label) blacklight_config.index_fields[name].custom_label = true end blacklight_config.index_fields[name].itemprop = itemprop - # for properties that DO exist in the CatalogController + if require_view_helper_method?(view_options) # add or update the helper method so linked fields will render correctly in the index view blacklight_config.index_fields[name].helper_method = view_option_for_helper_method(view_options) @@ -58,7 +57,6 @@ def load_flexible_schema end # if a property in the metadata profile doesn't exist in the CatalogController, add it blacklight_config.add_index_field(name, index_args) -# RuntimeError Exception: A index_field with the key depositor_tesim already exists. # all index fields get this property so an admin can hide a property from the catalog search results # by adding the name of the property via admin dashboard > Settings > Accounts > Hidden index fields @@ -74,14 +72,17 @@ def load_flexible_schema if facetable?(indexing, itemprop) name = "#{itemprop}_sim" - facet_args = { label: } - if indexing.include?("admin_only") - facet_args[:if] = lambda { |context, _field_config, _document| context.try(:current_user)&.admin? } - end - unless blacklight_config.facet_fields[name].present? + facet_args = { label: } + if indexing.include?("admin_only") + facet_args[:if] = lambda { |context, _field_config, _document| context.try(:current_user)&.admin? } + end blacklight_config.add_facet_field(name, **facet_args) end + else + # if the property does not have facetable in the indexing section of the metadata profile, remove the facet field from the blacklight config + name = "#{itemprop}_sim" + blacklight_config.facet_fields.delete(name) end end end diff --git a/spec/controllers/concerns/hyrax/flexible_catalog_behavior_spec.rb b/spec/controllers/concerns/hyrax/flexible_catalog_behavior_spec.rb index dfba5b3d7e..623aa0ddd5 100644 --- a/spec/controllers/concerns/hyrax/flexible_catalog_behavior_spec.rb +++ b/spec/controllers/concerns/hyrax/flexible_catalog_behavior_spec.rb @@ -197,6 +197,22 @@ def index expect(blacklight_config.index_fields[field + '_tesim'].link_to_facet).to eq(field + '_sim') end end + + context 'when a property changes from facetable to non-facetable' do + it 'removes the facet field from blacklight config' do + # manually add a facet field (simulating it existing in CatalogController) + controller.class.blacklight_config.add_facet_field('medium_sim', label: 'Medium') + + # verify it exists + expect(controller.class.blacklight_config.facet_fields).to have_key('medium_sim') + + # reload the schema (medium is not facetable in custom_properties) + controller.class.load_flexible_schema + + # should not exist since medium doesn't have 'facetable' in indexing + expect(controller.class.blacklight_config.facet_fields).not_to have_key('medium_sim') + end + end end context 'search fields' do From 798fa43aac9f433b73cf59fa54be4e35013ab2b3 Mon Sep 17 00:00:00 2001 From: Sarah Proctor Date: Tue, 23 Dec 2025 15:00:46 -0800 Subject: [PATCH 07/11] =?UTF-8?q?=E2=9A=99=EF=B8=8F=20Mock=20schema=20retr?= =?UTF-8?q?ieval?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit uses a mocked Hyrax::FlexibleSchema in the spec to avoid validation errors and improve test isolation. Ref: - https://github.com/samvera/hyku/issues/2860 --- .../hyrax/flexible_catalog_behavior_spec.rb | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/spec/controllers/concerns/hyrax/flexible_catalog_behavior_spec.rb b/spec/controllers/concerns/hyrax/flexible_catalog_behavior_spec.rb index 623aa0ddd5..a4e661fab1 100644 --- a/spec/controllers/concerns/hyrax/flexible_catalog_behavior_spec.rb +++ b/spec/controllers/concerns/hyrax/flexible_catalog_behavior_spec.rb @@ -93,22 +93,20 @@ def index describe 'loading flexible metadata profile' do before do - # ensure flexible metadata is enabled allow(Hyrax.config).to receive(:flexible?).and_return(true) - - # set up routes for the anonymous controller routes.draw { get 'index' => 'anonymous#index' } - # create the schema in the database by merging base profile with custom properties - Hyrax::FlexibleSchema.create!(profile: base_profile.deep_merge(custom_properties)) + # mock the schema retrieval to avoid database interactions + mock_schema = double('FlexibleSchema', + profile: base_profile.deep_merge(custom_properties)) - # manually trigger load_flexible_schema since it's a class method - controller.class.load_flexible_schema - end + allow(Hyrax::FlexibleSchema) + .to receive_message_chain(:order, :last) + .with("created_at asc") + .with(2) + .and_return([mock_schema]) - after do - # clean up created schemas after each test - Hyrax::FlexibleSchema.destroy_all + controller.class.load_flexible_schema end let(:blacklight_config) do From e5db2fedc5745484c0bb341beddc2df7a8384c5a Mon Sep 17 00:00:00 2001 From: Sarah Proctor Date: Tue, 23 Dec 2025 15:02:59 -0800 Subject: [PATCH 08/11] =?UTF-8?q?=E2=9A=99=EF=B8=8F=20Uses=20render=5Fas?= =?UTF-8?q?=20linked=20for=20text=20fixture?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit updates the m3_profile.yaml fixture to set the render_as option to linked rather than faceted and updates the corresponding specs Ref: - https://github.com/samvera/hyku/issues/2860 --- spec/fixtures/files/m3_profile.yaml | 1 + spec/services/hyrax/m3_schema_loader_spec.rb | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/spec/fixtures/files/m3_profile.yaml b/spec/fixtures/files/m3_profile.yaml index b8a3f84012..c7944d4bfc 100644 --- a/spec/fixtures/files/m3_profile.yaml +++ b/spec/fixtures/files/m3_profile.yaml @@ -193,6 +193,7 @@ properties: - Metadata - Repository view: + render_as: linked html_dl: true abstract: available_on: diff --git a/spec/services/hyrax/m3_schema_loader_spec.rb b/spec/services/hyrax/m3_schema_loader_spec.rb index d9c49afffd..b0fbec062a 100644 --- a/spec/services/hyrax/m3_schema_loader_spec.rb +++ b/spec/services/hyrax/m3_schema_loader_spec.rb @@ -133,7 +133,7 @@ expect(schema_loader.view_definitions_for(schema: GenericWork.to_s)) .to eq({ creator: { "html_dl" => true, "display_label" => { "default" => "Creator" }, "admin_only" => false }, - keyword: { "render_as" => "faceted", "html_dl" => true, "display_label" => { "default" => "Keyword" }, "admin_only" => false }, + keyword: { "render_as" => "linked", "html_dl" => true, "display_label" => { "default" => "Keyword" }, "admin_only" => false }, abstract: { "html_dl" => true, "display_label" => { "default" => "Abstract" }, "admin_only" => false } }) end @@ -183,7 +183,7 @@ it 'includes fields matching the context' do expect(schema_loader.view_definitions_for(schema: Monograph.to_s, contexts: 'flexible_context')) .to eq( - keyword: { "render_as" => "faceted", "html_dl" => true, "display_label" => { "default" => "Keyword" }, "admin_only" => false }, + keyword: { "render_as" => "linked", "html_dl" => true, "display_label" => { "default" => "Keyword" }, "admin_only" => false }, abstract: { "html_dl" => true, "display_label" => { "default" => "Abstract" }, "admin_only" => false } ) end From e1b01c805c485c1c81de703053ac8df134dcab14 Mon Sep 17 00:00:00 2001 From: Rob Kaufman Date: Fri, 16 Jan 2026 14:57:24 -0800 Subject: [PATCH 09/11] Change index field visibility condition to render_optionally --- app/controllers/concerns/hyrax/flexible_catalog_behavior.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/concerns/hyrax/flexible_catalog_behavior.rb b/app/controllers/concerns/hyrax/flexible_catalog_behavior.rb index 0ef42a9af4..e08dd2171c 100644 --- a/app/controllers/concerns/hyrax/flexible_catalog_behavior.rb +++ b/app/controllers/concerns/hyrax/flexible_catalog_behavior.rb @@ -61,7 +61,7 @@ def load_flexible_schema # all index fields get this property so an admin can hide a property from the catalog search results # by adding the name of the property via admin dashboard > Settings > Accounts > Hidden index fields # NOTE: it is likely this will be handled by the metadata profile in the future - blacklight_config.index_fields[name].if = :render_in_tenant? + blacklight_config.index_fields[name].if = :render_optionally? end qf = blacklight_config.search_fields['all_fields'].solr_parameters[:qf] From 3d4ccca401cfc5def9b7f4dbc7723de59623ebba Mon Sep 17 00:00:00 2001 From: Rob Kaufman Date: Fri, 16 Jan 2026 14:59:33 -0800 Subject: [PATCH 10/11] optional rendering hook --- app/controllers/concerns/hyrax/flexible_catalog_behavior.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/controllers/concerns/hyrax/flexible_catalog_behavior.rb b/app/controllers/concerns/hyrax/flexible_catalog_behavior.rb index e08dd2171c..c829117e59 100644 --- a/app/controllers/concerns/hyrax/flexible_catalog_behavior.rb +++ b/app/controllers/concerns/hyrax/flexible_catalog_behavior.rb @@ -144,5 +144,10 @@ def initialize self.class.load_flexible_schema super end + + # Hook to allow optional rendering at the app level + def render_optionally? + true + end end end From a63e0ce88caee3e6ea5fef897753049b10047612 Mon Sep 17 00:00:00 2001 From: Sarah Proctor Date: Mon, 19 Jan 2026 10:32:43 -0800 Subject: [PATCH 11/11] =?UTF-8?q?=E2=9C=85=20Specs=20allow=20a=20hook=20me?= =?UTF-8?q?thod=20`render=5Foptionally=3F`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../concerns/hyrax/flexible_catalog_behavior_spec.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spec/controllers/concerns/hyrax/flexible_catalog_behavior_spec.rb b/spec/controllers/concerns/hyrax/flexible_catalog_behavior_spec.rb index a4e661fab1..49663c15a7 100644 --- a/spec/controllers/concerns/hyrax/flexible_catalog_behavior_spec.rb +++ b/spec/controllers/concerns/hyrax/flexible_catalog_behavior_spec.rb @@ -167,11 +167,11 @@ def index expect(blacklight_config.index_fields['department_tesim'].helper_method).to be_nil end - it 'have the render_in_tenant? condition added to the blacklight config' do - # all fields should have the render_in_tenant? condition - # this allows admins to hide properties from catalog search results via the UI + it 'have the render_optionally? condition added to the blacklight config' do + # all fields should have the render_optionally? condition + # this allows a Hyku hook to hide properties from catalog search results %w[publication_date_tesim department_tesim related_resource_tesim medium_tesim].each do |field| - expect(blacklight_config.index_fields[field].if).to eq(:render_in_tenant?) + expect(blacklight_config.index_fields[field].if).to eq(:render_optionally?) end end end