Skip to content
Merged
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
15 changes: 14 additions & 1 deletion app/models/concerns/bulkrax/has_matchers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,20 @@ def set_parsed_data(name, value)
def set_parsed_object_data(object_multiple, object_name, name, index, value)
target_key = parsed_object_target_key(object_name)
target = object_target_for(target_key, object_name, object_multiple, index)
assign_object_value(target, name, value)
assign_object_value(target, object_row_key(name), value)
end

# The key a value is written under inside an `object:` row. Defaults to the
# mapping key, but a mapping may set `name:` (alias `row_key:`) to use a
# different in-row key. This lets two mappings with distinct (globally
# unique) keys both write the same in-row key into different objects — e.g.
# a `title` sub-property shared by two compounds, each needing a unique
# top-level mapping key but the same `title` key inside its row.
def object_row_key(name)
cfg = mapping[name]
return name unless cfg.is_a?(Hash)

cfg['name'] || cfg[:name] || cfg['row_key'] || cfg[:row_key] || name
end

# Resolve the hash slot that `name` should be written into, initializing
Expand Down
41 changes: 41 additions & 0 deletions spec/models/bulkrax/csv_entry_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,47 @@ class ::Avocado < Work
end
end

# Compound metadata is a Valkyrie-only feature: the in-row `name:` option
# supports compounds whose sub-property keys collide across parents
# (e.g. a `title` shared by two compounds). Exercise it against a Valkyrie
# resource whose schema declares `type: hash, multiple: true` parents.
context 'when a mapping declares name: to set the in-row key (Valkyrie compound)' do
# `name:` (alias `row_key:`) decouples the in-row key from the globally
# unique mapping key, so two mappings with distinct keys can write the
# same in-row key into different compounds.
let(:importer) do
FactoryBot.create(:bulkrax_importer_csv, field_mapping: {
'compound_one_title' => { from: ['compound_one_title'], object: 'compound_one', nested_attributes: true, name: 'title' },
'compound_two_title' => { from: ['compound_two_title'], object: 'compound_two', nested_attributes: true, name: 'title' }
})
end

around do |example|
previous = Bulkrax.object_factory
Bulkrax.object_factory = Bulkrax::ValkyrieObjectFactory
example.run
Bulkrax.object_factory = previous
end

before do
allow(subject).to receive(:factory_class).and_return(WorkResource)
allow(subject).to receive(:raw_metadata).and_return(
'source_identifier' => '2',
'title' => 'some title',
'compound_one_title_1' => 'Title A',
'compound_two_title_1' => 'Title B'
)
end

it 'writes each value under the configured in-row key, independently per compound' do
metadata = subject.build_metadata
expect(metadata['compound_one_attributes']['0']['title']).to eq('Title A')
expect(metadata['compound_two_attributes']['0']['title']).to eq('Title B')
# The unique mapping key is not used as the in-row key.
expect(metadata['compound_one_attributes']['0']).not_to have_key('compound_one_title')
end
end

context 'with object fields not prefixed and properties with multiple values' do
let(:importer) do
FactoryBot.create(:bulkrax_importer_csv, field_mapping: {
Expand Down
9 changes: 9 additions & 0 deletions spec/test_app/config/metadata/work_resource.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,12 @@ attributes:
required: false
primary: false
multiple: false
# Two compound (Array<Hash>) parents used to exercise the `name:` (row_key)
# field-mapping option on a Valkyrie resource: a shared in-row key (`title`)
# written into different compounds from distinct, globally unique mapping keys.
compound_one:
type: hash
multiple: true
compound_two:
type: hash
multiple: true
Loading