class Blacklight::Configuration

Blacklight::Configuration holds the configuration for a Blacklight::Controller, including fields to display, facets to show, sort options, and search fields.

Public Class Methods

default_values() click to toggle source

rubocop:disable Metrics/MethodLength

# File lib/blacklight/configuration.rb, line 25
def default_values
  @default_values ||= begin
    {
    # === Search request configuration
    # HTTP method to use when making requests to solr; valid
    # values are :get and :post.
    http_method: :get,
    # The path to send requests to solr.
    solr_path: 'select',
    # Default values of parameters to send with every search request
    default_solr_params: {},
    ##
    # === Single document request configuration
    # The solr request handler to use when requesting only a single document
    document_solr_request_handler: nil,
    # The path to send single document requests to solr
    document_solr_path: 'get',
    document_unique_id_param: :ids,
    # Default values of parameters to send when requesting a single document
    default_document_solr_params: {},
    fetch_many_document_params: {},
    document_pagination_params: {},
    ##
    # == Response models
    ## Class for sending and receiving requests from a search index
    repository_class: nil,
    ## Class for converting Blacklight parameters to request parameters for the repository_class
    search_builder_class: nil,
    # model that maps index responses to the blacklight response model
    response_model: nil,
    # the model to use for each response document
    document_model: nil,
    # Class for paginating long lists of facet fields
    facet_paginator_class: nil,
    # repository connection configuration
    connection_config: nil,
    ##
    # == Blacklight view configuration
    navbar: OpenStructWithHashAccess.new(partials: {}),
    # General configuration for all views
    index: ViewConfig::Index.new(
      # document presenter class used by helpers and views
      document_presenter_class: nil,
      # component class used to render a document; defaults to Blacklight::DocumentComponent,
      #   but can be set explicitly to avoid any legacy behavior
      document_component: nil,
      # solr field to use to render a document title
      title_field: nil,
      # solr field to use to render format-specific partials
      display_type_field: nil,
      # partials to render for each document(see #render_document_partials)
      partials: [:index_header, :thumbnail, :index],
      document_actions: NestedOpenStructWithHashAccess.new(ToolConfig),
      collection_actions: NestedOpenStructWithHashAccess.new(ToolConfig),
      # what field, if any, to use to render grouped results
      group: false,
      # additional response formats for search results
      respond_to: OpenStructWithHashAccess.new
    ),
    # Additional configuration when displaying a single document
    show: ViewConfig::Show.new(
      # document presenter class used by helpers and views
      document_presenter_class: nil,
      document_component: nil,
      display_type_field: nil,
      # Default route parameters for 'show' requests.
      # Set this to a hash with additional arguments to merge into the route,
      # or set `controller: :current` to route to the current controller.
      route: nil,
      # partials to render for each document(see #render_document_partials)
      partials: [:show_header, :show],
      document_actions: NestedOpenStructWithHashAccess.new(ToolConfig)
    ),
    action_mapping: NestedOpenStructWithHashAccess.new(
      ViewConfig,
      default: { top_level_config: :index },
      show: { top_level_config: :show },
      citation: { parent_config: :show }
    ),
    # Configurations for specific types of index views
    view: NestedOpenStructWithHashAccess.new(ViewConfig,
                                             list: {},
                                             atom: {
                                               if: false, # by default, atom should not show up as an alternative view
                                               partials: [:document],
                                               summary_partials: [:index]
                                             },
                                             rss: {
                                               if: false, # by default, rss should not show up as an alternative view
                                               partials: [:document]
                                           }),
    #
    # These fields are created and managed below by `define_field_access`
    # facet_fields
    # index_fields
    # show_fields
    # sort_fields
    # search_fields
    ##
    # === Blacklight behavior configuration
    # Maxiumum number of spelling suggestions to offer
    spell_max: 5,
    # Maximum number of results to show per page
    max_per_page: 100,
    # Options for the user for number of results to show per page
    per_page: [10, 20, 50, 100],
    default_per_page: nil,
    # how many searches to save in session history
    search_history_window: 100,
    default_facet_limit: 10,
    default_more_limit: 20,
    # proc for determining whether the session is a crawler/bot
    # ex.: crawler_detector: lambda { |req| req.env['HTTP_USER_AGENT'] =~ /bot/ }
    crawler_detector: nil,
    autocomplete_suggester: 'mySuggester',
    raw_endpoint: OpenStructWithHashAccess.new(enabled: false),
    track_search_session: true,
    advanced_search: OpenStruct.new(enabled: false)
    }
  end
  # rubocop:enable Metrics/MethodLength
end
new(hash = {}) { |self| ... } click to toggle source
Calls superclass method
# File lib/blacklight/configuration.rb, line 170
def initialize(hash = {})
  super(self.class.default_values.deep_dup.merge(hash))
  yield(self) if block_given?

  @view_config ||= {}
end

Public Instance Methods

add_facet_fields_to_solr_request!(*fields) click to toggle source

Add any configured facet fields to the default solr parameters hash @overload add_facet_fields_to_solr_request!

add all facet fields to the solr request

@overload add_facet_fields_to_solr_request! field, field, etc

@param [Symbol] field Field names to add to the solr request
# File lib/blacklight/configuration.rb, line 278
def add_facet_fields_to_solr_request!(*fields)
  if fields.empty?
    self.add_facet_fields_to_solr_request = true
  else
    facet_fields.slice(*fields).each_value { |v| v.include_in_request = true }
  end
end
add_field_configuration_to_solr_request!(*fields) click to toggle source

Add any configured facet fields to the default solr parameters hash @overload add_field_configuration_to_solr_request!

add all index, show, and facet fields to the solr request

@overload add_field_configuration_to_solr_request! field, field, etc

@param [Symbol] field Field names to add to the solr request
# File lib/blacklight/configuration.rb, line 291
def add_field_configuration_to_solr_request!(*fields)
  if fields.empty?
    self.add_field_configuration_to_solr_request = true
  else
    index_fields.slice(*fields).each_value { |v| v.include_in_request = true }
    show_fields.slice(*fields).each_value { |v| v.include_in_request = true }
    facet_fields.slice(*fields).each_value { |v| v.include_in_request = true }
  end
end
add_nav_action(name, opts = {}) click to toggle source

Add a partial to the header navbar @!macro partial_if_unless

# File lib/blacklight/configuration.rb, line 378
def add_nav_action(name, opts = {})
  add_action(navbar.partials, name, opts)
end
add_results_collection_tool(name, opts = {}) click to toggle source

Add a tool for the search result list itself @!macro partial_if_unless

# File lib/blacklight/configuration.rb, line 366
def add_results_collection_tool(name, opts = {})
  add_action(index.collection_actions, name, opts)
end
add_results_document_tool(name, opts = {}) click to toggle source

Add a partial to the tools for each document in the search results. @!macro partial_if_unless

# File lib/blacklight/configuration.rb, line 372
def add_results_document_tool(name, opts = {})
  add_action(index.document_actions, name, opts)
end
add_show_tools_partial(name, opts = {}) click to toggle source

Add a partial to the tools when rendering a document. @!macro partial_if_unless

@param name [String] the name of the document partial
@param opts [Hash]
@option opts [Symbol,Proc] :if render this action if the method identified by the symbol or the proc evaluates to true. The proc will receive the action configuration and the document or documents for the action.
@option opts [Symbol,Proc] :unless render this action unless the method identified by the symbol or the proc evaluates to true. The proc will receive the action configuration and the document or documents for the action.
# File lib/blacklight/configuration.rb, line 357
def add_show_tools_partial(name, opts = {})
  opts[:partial] ||= 'document_action'
  add_action(show.document_actions, name, opts)
  klass && ActionBuilder.new(klass, name, opts).build
end
build(klass) click to toggle source

builds a copy for the provided controller class

# File lib/blacklight/configuration.rb, line 311
def build(klass)
  deep_copy.tap do |conf|
    conf.klass = klass
  end
end
Also aliased as: inheritable_copy
configure() { |self| ... } click to toggle source

DSL helper

# File lib/blacklight/configuration.rb, line 228
def configure
  yield self if block_given?
  self
end
connection_config() click to toggle source
Calls superclass method
# File lib/blacklight/configuration.rb, line 207
def connection_config
  super || Blacklight.connection_config
end
deep_copy() click to toggle source

Provide a 'deep copy' of Blacklight::Configuration that can be modified without effecting the original Blacklight::Configuration instance.

Note: Rails provides `#deep_dup`, but it aggressively `#dup`'s class names too, turning them into anonymous class instances.

# File lib/blacklight/configuration.rb, line 306
def deep_copy
  deep_transform_values_in_object(self, &method(:_deep_copy))
end
default_per_page() click to toggle source
Calls superclass method
# File lib/blacklight/configuration.rb, line 223
def default_per_page
  super || per_page.first
end
default_search_field() click to toggle source

Returns default search field, used for simpler display in history, etc. if not set, defaults to first defined search field

Calls superclass method
# File lib/blacklight/configuration.rb, line 235
def default_search_field
  field = super || search_fields.values.find { |f| f.default == true }
  field || search_fields.values.first
end
default_sort_field() click to toggle source

Returns default sort field, used for simpler display in history, etc. if not set, defaults to first defined sort field

Calls superclass method
# File lib/blacklight/configuration.rb, line 242
def default_sort_field
  field = super || sort_fields.values.find { |f| f.default == true }
  field || sort_fields.values.first
end
default_title_field() click to toggle source
# File lib/blacklight/configuration.rb, line 247
def default_title_field
  document_model.unique_key || 'id'
end
document_factory() click to toggle source

A class that builds documents

Calls superclass method
# File lib/blacklight/configuration.rb, line 182
def document_factory
  super || Blacklight::DocumentFactory
end
document_model() click to toggle source
Calls superclass method
# File lib/blacklight/configuration.rb, line 177
def document_model
  super || ::SolrDocument
end
document_model=(*args) click to toggle source

only here to support alias_method

Calls superclass method
# File lib/blacklight/configuration.rb, line 187
def document_model=(*args)
  super
end
facet_configuration_for_field(field) click to toggle source

@param [String] field Solr facet name @return [Blacklight::Configuration::FacetField] Blacklight facet configuration for the solr field

# File lib/blacklight/configuration.rb, line 253
def facet_configuration_for_field(field)
  # short-circuit on the common case, where the solr field name and the blacklight field name are the same.
  return facet_fields[field] if facet_fields[field] && facet_fields[field].field == field

  # Find the facet field configuration for the solr field, or provide a default.
  facet_fields.values.find { |v| v.field.to_s == field.to_s } ||
    FacetField.new(field: field).normalize!
end
facet_field_names(group = nil) click to toggle source

@param [String] group (nil) a group name of facet fields @return [Array<String>] a list of the facet field names from the configuration

# File lib/blacklight/configuration.rb, line 264
def facet_field_names(group = nil)
  facet_fields.select { |_facet, opts| group == opts[:group] }.values.map(&:field)
end
facet_group_names() click to toggle source

@return [Array<String>] a list of facet groups

# File lib/blacklight/configuration.rb, line 269
def facet_group_names
  facet_fields.map { |_facet, opts| opts[:group] }.uniq
end
facet_paginator_class() click to toggle source
Calls superclass method
# File lib/blacklight/configuration.rb, line 219
def facet_paginator_class
  super || Blacklight::Solr::FacetPaginator
end
for_display_type(display_type) { |conf| ... } click to toggle source

Add a section of config that only applies to documents with a matching display type

# File lib/blacklight/configuration.rb, line 384
def for_display_type display_type, &_block
  self.fields_for_type ||= {}

  (fields_for_type[display_type] ||= self.class.new).tap do |conf|
    yield(conf) if block_given?
  end
end
freeze() click to toggle source
Calls superclass method
# File lib/blacklight/configuration.rb, line 432
def freeze
  each { |_k, v| v.is_a?(OpenStruct) && v.freeze }
  super
end
index_fields_for(document_or_display_types) click to toggle source

Return a list of fields for the index display that should be used for the provided document. This respects any configuration made using for_display_type

# File lib/blacklight/configuration.rb, line 395
def index_fields_for(document_or_display_types)
  display_types = if document_or_display_types.is_a? Blacklight::Document
                    Deprecation.warn self, "Calling index_fields_for with a #{document_or_display_types.class} is deprecated and will be removed in Blacklight 8. Pass the display type instead."
                    document_or_display_types[index.display_type_field || 'format']
                  else
                    document_or_display_types
                  end

  fields = {}.with_indifferent_access

  Array.wrap(display_types).each do |display_type|
    fields = fields.merge(for_display_type(display_type).index_fields)
  end

  fields.merge(index_fields)
end
inheritable_copy(klass)
Alias for: build
locate_search_builder_class() click to toggle source
# File lib/blacklight/configuration.rb, line 215
def locate_search_builder_class
  ::SearchBuilder
end
repository() click to toggle source
# File lib/blacklight/configuration.rb, line 203
def repository
  repository_class.new(self)
end
repository_class() click to toggle source
Calls superclass method
# File lib/blacklight/configuration.rb, line 199
def repository_class
  super || Blacklight::Solr::Repository
end
response_model() click to toggle source
Calls superclass method
# File lib/blacklight/configuration.rb, line 191
def response_model
  super || Blacklight::Solr::Response
end
response_model=(*args) click to toggle source
Calls superclass method
# File lib/blacklight/configuration.rb, line 195
def response_model=(*args)
  super
end
search_builder_class() click to toggle source
Calls superclass method
# File lib/blacklight/configuration.rb, line 211
def search_builder_class
  super || locate_search_builder_class
end
show_fields_for(document_or_display_types) click to toggle source

Return a list of fields for the show page that should be used for the provided document. This respects any configuration made using for_display_type

# File lib/blacklight/configuration.rb, line 415
def show_fields_for(document_or_display_types)
  display_types = if document_or_display_types.is_a? Blacklight::Document
                    Deprecation.warn self, "Calling show_fields_for with a #{document_or_display_types.class} is deprecated and will be removed in Blacklight 8. Pass the display type instead."
                    document_or_display_types[show.display_type_field || 'format']
                  else
                    document_or_display_types
                  end

  fields = {}.with_indifferent_access

  Array.wrap(display_types).each do |display_type|
    fields = fields.merge(for_display_type(display_type).show_fields)
  end

  fields.merge(show_fields)
end
view_config(view_type = nil, action_name: :index) click to toggle source

Get a view configuration for the given view type + action. The effective view configuration is inherited from:

  • the configuration from blacklight_config.view with the key `view_type`

  • the configuration from blacklight_config.action_mapping with the key `action_name`

  • any parent config for the action map result above

  • the action_mapping default configuration

  • the top-level index/show view configuration

@param [Symbol,#to_sym] view_type @return [Blacklight::Configuration::ViewConfig]

# File lib/blacklight/configuration.rb, line 328
def view_config(view_type = nil, action_name: :index)
  view_type &&= view_type.to_sym
  action_name &&= action_name.to_sym
  action_name ||= :index

  if view_type == :show
    action_name = view_type
    view_type = nil
  end

  @view_config[[view_type, action_name]] ||= begin
    if view_type.nil?
      action_config(action_name)
    else
      base_config = action_config(action_name)
      base_config.merge(view.fetch(view_type, {}))
    end
  end
end

Private Instance Methods

_deep_copy(value) click to toggle source

Provide custom duplication for certain types of configuration (intended for use in e.g. deep_transform_values)

# File lib/blacklight/configuration.rb, line 448
def _deep_copy(value)
  case value
  when Module then value
  when NestedOpenStructWithHashAccess then value.class.new(value.nested_class, deep_transform_values_in_object(value.to_h, &method(:_deep_copy)))
  when OpenStruct then value.class.new(deep_transform_values_in_object(value.to_h, &method(:_deep_copy)))
  else
    value.dup
  end
end
_deep_transform_values_in_object(object) { |object| ... } click to toggle source

Ported from Rails 6

# File lib/blacklight/configuration.rb, line 468
def _deep_transform_values_in_object(object, &block)
  case object
  when Hash
    object.transform_values { |value| _deep_transform_values_in_object(value, &block) }
  when Array
    object.map { |e| _deep_transform_values_in_object(e, &block) }
  else
    yield(object)
  end
end
action_config(action, default: :index) click to toggle source
# File lib/blacklight/configuration.rb, line 479
def action_config(action, default: :index)
  action_config = action_mapping[action]
  action_config ||= action_mapping[:default]

  if action_config.parent_config && action_config.parent_config != :default
    parent_config = action_mapping[action_config.parent_config]
    raise "View configuration error: the parent configuration of #{action_config.key}, #{parent_config.key}, must not specific its own parent configuration" if parent_config.parent_config

    action_config = action_config.reverse_merge(parent_config)
  end
  action_config = action_config.reverse_merge(action_mapping[:default]) if action_config != action_mapping[:default]

  action_config = action_config.reverse_merge(self[action_config.top_level_config]) if action_config.top_level_config
  action_config = action_config.reverse_merge(show) if default == :show && action_config.top_level_config != :show
  action_config.reverse_merge(index)
end
add_action(config_hash, name, opts) { |config| ... } click to toggle source
# File lib/blacklight/configuration.rb, line 439
def add_action(config_hash, name, opts)
  config = Blacklight::Configuration::ToolConfig.new opts
  config.name ||= name
  config.key = name
  yield(config) if block_given?
  config_hash[name] = config
end
deep_transform_values_in_object(object, &block) click to toggle source

This is a little shim to support Rails 6 (which has Hash#deep_transform_values) and earlier versions (which use our backport). Once we drop support for Rails 6, this can go away.

# File lib/blacklight/configuration.rb, line 461
def deep_transform_values_in_object(object, &block)
  return object.deep_transform_values(&block) if object.respond_to?(:deep_transform_values)

  _deep_transform_values_in_object(object, &block)
end