Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lib/digital_scriptorium.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
require 'digital_scriptorium/property_id'

require 'digital_scriptorium/ds_item'
require 'digital_scriptorium/no_current_holding_exception'
require 'digital_scriptorium/multiple_current_holdings_exception'
require 'digital_scriptorium/ds_meta'
require 'digital_scriptorium/holding'
require 'digital_scriptorium/manuscript'
Expand Down
19 changes: 14 additions & 5 deletions lib/digital_scriptorium/ds_meta.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,26 @@ def initialize(record, export_hash)
manuscript = export_hash[record.described_manuscript_id]
current_holdings = current_holdings(manuscript, export_hash)

if current_holdings.size != 1
raise "Manuscripts must have exactly 1 current holding, found #{current_holdings.size}"
end

@holding = current_holdings.first
@holding = validate_holdings_count(manuscript, current_holdings)
@manuscript = manuscript
@record = record
end

def current_holdings(manuscript, export_hash)
manuscript.holding_ids.filter_map { |id| export_hash[id] if export_hash[id]&.current? }
end

private

def validate_holdings_count(manuscript, current_holdings)
case current_holdings.size
when 0
raise NoCurrentHoldingException, manuscript.id
when 1
current_holdings.first
else
raise MultipleCurrentHoldingsException.new(manuscript.id, current_holdings.size)
end
end
end
end
15 changes: 15 additions & 0 deletions lib/digital_scriptorium/multiple_current_holdings_exception.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

module DigitalScriptorium
# Exception raised when a manuscript has multiple current holdings, which is an invalid state
# that requires correction in the data.
class MultipleCurrentHoldingsException < StandardError
attr_reader :manuscript_id, :holdings_count

def initialize(manuscript_id, holdings_count)
@manuscript_id = manuscript_id
@holdings_count = holdings_count
super("Manuscript #{manuscript_id} has #{holdings_count} current holdings, expected at most 1")
end
end
end
14 changes: 14 additions & 0 deletions lib/digital_scriptorium/no_current_holding_exception.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# frozen_string_literal: true

module DigitalScriptorium
# Exception raised when a manuscript has no current holding, which is a valid state
# but requires special handling in processing workflows.
class NoCurrentHoldingException < StandardError
attr_reader :manuscript_id

def initialize(manuscript_id)
@manuscript_id = manuscript_id
super("Manuscript #{manuscript_id} has no current holding")
end
end
end
38 changes: 37 additions & 1 deletion spec/digital_scriptorium/ds_meta_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,50 @@ module DigitalScriptorium
include WikibaseRepresentable::Representers

RSpec.describe DsMeta do
let(:record) { export_hash.fetch('Q544') }
let(:manuscript) { export_hash.fetch('Q543') }

context 'with a record concerning a manuscript with a single current holding' do
it 'correctly sets the holding' do
record = export_hash.fetch('Q544')
meta = described_class.new(record, export_hash)
expect(meta.holding).to eq export_hash.fetch('Q542')
end
end

context 'with a record concerning a manuscript with no current holdings' do
let(:manuscript_no_holdings) do
manuscript.tap { |m| allow(m).to receive(:holding_ids).and_return([]) }
end

it 'raises NoCurrentHoldingException' do
allow(export_hash).to receive(:[]).with(record.described_manuscript_id).and_return(manuscript_no_holdings)

expect { described_class.new(record, export_hash) }
.to raise_error(DigitalScriptorium::NoCurrentHoldingException,
'Manuscript Q543 has no current holding')
end
end

context 'with a record concerning a manuscript with multiple current holdings' do
let(:first_holding) { instance_double(DigitalScriptorium::Holding, current?: true) }
let(:second_holding) { instance_double(DigitalScriptorium::Holding, current?: true) }
let(:manuscript_multi_holdings) do
manuscript.tap { |m| allow(m).to receive(:holding_ids).and_return(%w[H1 H2]) }
end

before do
allow(export_hash).to receive(:[]).with(record.described_manuscript_id).and_return(manuscript_multi_holdings)
allow(export_hash).to receive(:[]).with('H1').and_return(first_holding)
allow(export_hash).to receive(:[]).with('H2').and_return(second_holding)
end

it 'raises MultipleCurrentHoldingsException' do
expect { described_class.new(record, export_hash) }
.to raise_error(DigitalScriptorium::MultipleCurrentHoldingsException,
'Manuscript Q543 has 2 current holdings, expected at most 1')
end
end

# TODO: Create setters in wikibase_representable and use them to build objects for testing
# (currently) counterfactual holdings scenarios (i.e., other than exactly one current holding)
end
Expand Down