Skip to content

Commit

Permalink
Merge pull request #318 from scientist-softserv/rails_hyrax_upgrade
Browse files Browse the repository at this point in the history
Rails hyrax upgrade
  • Loading branch information
jeremyf authored Jan 23, 2024
2 parents 3fa2d4b + bed6faa commit 2f6efa2
Show file tree
Hide file tree
Showing 10 changed files with 167 additions and 13 deletions.
30 changes: 22 additions & 8 deletions app/indexers/concerns/iiif_print/child_indexer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,33 @@ module ChildIndexer
def self.decorate_work_types!
# TODO: This method is in the wrong location; says indexing but there's also the SetChildFlag
# consideration. Consider refactoring this stuff into a single nested module.
#

Hyrax.config.curation_concerns.each do |work_type|
work_type.send(:include, IiifPrint::SetChildFlag) unless work_type.included_modules.include?(IiifPrint::SetChildFlag)
indexer = work_type.indexer
unless indexer.respond_to?(:iiif_print_lineage_service)
indexer.prepend(self)
indexer.class_attribute(:iiif_print_lineage_service, default: IiifPrint::LineageService)
end
next unless work_type.respond_to?(:iiif_print_config?)
next unless work_type.iiif_print_config?

indexer = if work_type < Valkyrie::Resource
IiifPrint::PersistenceLayer::ValkyrieAdapter.decorate_with_adapter_logic(work_type: work_type)
else
IiifPrint::PersistenceLayer::ActiveFedoraAdapter.decorate_with_adapter_logic(work_type: work_type)
end

indexer.prepend(self).class_attribute(:iiif_print_lineage_service, default: IiifPrint::LineageService) unless indexer.respond_to?(:iiif_print_lineage_service)
work_type::GeneratedResourceSchema.send(:include, IiifPrint::SetChildFlag) if work_type.const_defined?(:GeneratedResourceSchema)
end
end

def to_solr
super.tap do |index_document|
index_document['is_page_of_ssim'] = iiif_print_lineage_service.ancestor_ids_for(resource)

# Due to a long-standing hack in Hyrax, the file_set_ids_ssim contains both file_set_ids and
# child work ids.
#
# See https://github.com/samvera/hyrax/blob/2b807fe101176d594129ef8a8fe466d3d03a372b/app/indexers/hyrax/work_indexer.rb#L15-L18
index_document['file_set_ids_ssim'] = iiif_print_lineage_service.descendent_member_ids_for(resource)
end
end

def generate_solr_document
super.tap do |solr_doc|
solr_doc['is_child_bsi'] ||= object.is_child
Expand Down
11 changes: 11 additions & 0 deletions app/services/iiif_print/simple_schema_loader_decorator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# frozen_string_literal: true

# OVERRIDE Hyrax v5.0.0rc2 to add schemas that are located in config/metadata/*.yaml

module IiifPrint
module SimpleSchemaLoaderDecorator
def config_search_paths
super + [IiifPrint::Engine.root]
end
end
end
21 changes: 21 additions & 0 deletions config/metadata/child_works_from_pdf_splitting.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
attributes:
is_child:
type: bool
multiple: false
index_keys:
- "is_child_bsi"
form:
required: false
primary: false
multiple: false
predicate: "http://id.loc.gov/vocabulary/identifiers/isChild"
split_from_pdf_id:
type: string
multiple: false
index_keys:
- "split_from_pdf_id_ssi"
form:
required: false
primary: false
multiple: false
predicate: "http://id.loc.gov/vocabulary/identifiers/splitFromPdfId"
18 changes: 15 additions & 3 deletions lib/iiif_print.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,12 @@ class << self
:clean_for_tests!,
:destroy_children_split_from,
:grandparent_for,
:object_in_works,
:object_ordered_works,
:parent_for,
:solr_construct_query,
:solr_name,
:solr_query,
:parent_for,
to: :persistence_adapter
)
end
Expand Down Expand Up @@ -112,10 +114,15 @@ class << self
# @see IiifPrint::DEFAULT_MODEL_CONFIGURATION
# @todo Because not every job will split PDFs and write to a child model. May want to introduce
# an alternative splitting method to create new filesets on the existing work instead of new child works.
# rubocop:disable Metrics/MethodLength
def self.model_configuration(**kwargs)
Module.new do
def iiif_print_config?
true
extend ActiveSupport::Concern

class_methods do
def iiif_print_config?
true
end
end

# We don't know what you may want in your configuration, but from this gems implementation,
Expand All @@ -127,8 +134,13 @@ def iiif_print_config?
define_method(:iiif_print_config) do
@iiif_print_config ||= ModelConfig.new(**kwargs)
end

def iiif_print_config?
true
end
end
end
# rubocop:enable Metrics/MethodLength

# @api public
#
Expand Down
9 changes: 9 additions & 0 deletions lib/iiif_print/engine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,17 @@ class Engine < ::Rails::Engine
Hyrax::IiifManifestPresenter.prepend(IiifPrint::IiifManifestPresenterBehavior)
Hyrax::IiifManifestPresenter::Factory.prepend(IiifPrint::IiifManifestPresenterFactoryBehavior)
Hyrax::ManifestBuilderService.prepend(IiifPrint::ManifestBuilderServiceBehavior)

# Hyrax::SimpleSchemaLoader was introduced in Hyrax 3.0; as this gem supports Hyrax 2.9.6 we need to be cautious
'Hyrax::SimpleSchemaLoader'.safe_constantize&.prepend(IiifPrint::SimpleSchemaLoaderDecorator)

Hyrax::Renderers::FacetedAttributeRenderer.prepend(Hyrax::Renderers::FacetedAttributeRendererDecorator)
Hyrax::WorksControllerBehavior.prepend(IiifPrint::WorksControllerBehaviorDecorator)

# Hyku::WorksControllerBehavior was introduced in Hyku v6.0.0+. Yes we don't depend on Hyku,
# but this allows us to do minimal Hyku antics with IiifPrint.
'Hyku::WorksControllerBehavior'.safe_constantize&.prepend(IiifPrint::WorksControllerBehaviorDecorator)

Hyrax::WorkShowPresenter.prepend(IiifPrint::WorkShowPresenterDecorator)
Hyrax::IiifHelper.prepend(IiifPrint::IiifHelperDecorator)

Expand Down
6 changes: 4 additions & 2 deletions lib/iiif_print/lineage_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ module LineageService
# @return [Array<String>]
def self.ancestor_ids_for(object)
ancestor_ids ||= []
object.in_works.each do |work|
# Yes, we're fetching the works, then compressing those into identifiers. Because in the case
# of slugs, we need not the identifier, but the slug as the id.
IiifPrint.object_in_works(object).each do |work|
ancestor_ids << ancestry_identifier_for(work)
ancestor_ids += ancestor_ids_for(work) if work.is_child
end
Expand Down Expand Up @@ -50,7 +52,7 @@ def self.descendent_member_ids_for(object)
# The Hydara::Works implementation of file_set_ids is "members.select(&:file_set?).map(&:id)";
# so no sense doing `object.file_set_ids + object.member_ids`
file_set_ids = object.member_ids
object.ordered_works&.each do |child|
IiifPrint.object_ordered_works(object)&.each do |child|
file_set_ids += descendent_member_ids_for(child)
end
file_set_ids.flatten.uniq.compact
Expand Down
21 changes: 21 additions & 0 deletions lib/iiif_print/persistence_layer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,27 @@ module IiifPrint
module PersistenceLayer
# @abstract
class AbstractAdapter
##
# @param object [Object]
# @return [Array<Object>]
def self.object_in_works(object)
raise NotImplementedError, "#{self}.{__method__}"
end

##
# @param object [Object]
# @return [Array<Object>]
def self.object_ordered_works(object)
raise NotImplementedError, "#{self}.{__method__}"
end

##
# @param work_type [Class]
# @return the corresponding indexer for the work_type
def self.decorate_with_adapter_logic(work_type:)
raise NotImplementedError, "#{self}.{__method__}"
end

##
# @param file_set [Object]
# @param work [Object]
Expand Down
22 changes: 22 additions & 0 deletions lib/iiif_print/persistence_layer/active_fedora_adapter.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,28 @@
module IiifPrint
module PersistenceLayer
class ActiveFedoraAdapter < AbstractAdapter
##
# @param object [ActiveFedora::Base]
# @return [Array<SolrDocument>]
def self.object_in_works(object)
object.in_works
end

##
# @param object [ActiveFedora::Base]
# @return [Array<SolrDocument>]
def self.object_ordered_works(object)
object.ordered_works
end

##
# @param work_type [Class<ActiveFedora::Base>]
# @return indexer for the given :work_type
def self.decorate_with_adapter_logic(work_type:)
work_type.send(:include, IiifPrint::SetChildFlag) unless work_type.included_modules.include?(IiifPrint::SetChildFlag)
work_type.indexer
end

##
# Return the immediate parent of the given :file_set.
#
Expand Down
27 changes: 27 additions & 0 deletions lib/iiif_print/persistence_layer/valkyrie_adapter.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,33 @@
module IiifPrint
module PersistenceLayer
class ValkyrieAdapter < AbstractAdapter
##
# @param object [Valkyrie::Resource]
# @return [Array<Valkyrie::Resource>]
def self.object_in_works(object)
Array.wrap(Hyrax.custom_queries.find_parent_work(resource: object))
end

##
# @param object [Valkyrie::Resource]
# @return [Array<Valkyrie::Resource>]
def self.object_ordered_works(object)
child_file_sets = Hyrax.custom_queries.find_child_file_sets(resource: object).to_a
child_works = Hyrax.custom_queries.find_child_works(resource: object).to_a
child_works + child_file_sets
end

##
# @param work_type [Class<Valkyrie::Resource>]
# @return the indexer for the given :work_type
def self.decorate_with_adapter_logic(work_type:)
work_type.send(:include, Hyrax::Schema(:child_works_from_pdf_splitting)) unless work_type.included_modules.include?(Hyrax::Schema(:child_works_from_pdf_splitting))
# TODO: Use `Hyrax::ValkyrieIndexer.indexer_class_for` once changes are merged.
indexer = "#{work_type}Indexer".constantize
indexer.send(:include, Hyrax::Indexer(:child_works_from_pdf_splitting)) unless indexer.included_modules.include?(Hyrax::Indexer(:child_works_from_pdf_splitting))
indexer
end

##
# Return the immediate parent of the given :file_set.
#
Expand Down
15 changes: 15 additions & 0 deletions spec/services/iiif_print/simple_schema_loader_decorator_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

require 'spec_helper'

RSpec.describe Hyrax::SimpleSchemaLoader do
subject(:instance) { described_class.new }

context '#config_search_paths' do
subject { instance.config_search_paths }

# Would it make sense for IiifPrint::Engine to come before Hyrax::Engine? As IiifPrint depends
# on Hyrax.
it { is_expected.to match_array([Rails.root, Hyrax::Engine.root, IiifPrint::Engine.root]) }
end
end

0 comments on commit 2f6efa2

Please sign in to comment.