module TrajectPlus module Indexer class ToFieldStep < Traject::Indexer::ToFieldStep # @param single [Bool] if true, this outputs a scalar value (rather than an Array) # by default Traject only outputs arrays. def initialize(fieldname, procs, block, source_location, single: false) super(fieldname, procs, block, source_location) @single = single end def single? !!@single end # disable to_field_step? so we can implement our own version of add_accumulator_to_context def to_field_step? false end def add_accumulator_to_context!(accumulator, context) self.class.add_accumulator_to_context!(self, field_name, accumulator, context) end def self.add_accumulator_to_context!(field, field_name, accumulator, context) accumulator.compact! unless context.settings[ALLOW_NIL_VALUES] return if accumulator.empty? and not (context.settings[ALLOW_EMPTY_FIELDS]) # field_name can actually be an array of field names Array(field_name).each do |a_field_name| if field.single? context.output_hash[a_field_name] = accumulator.first if accumulator.length > 0 else context.output_hash[a_field_name] ||= [] existing_accumulator = context.output_hash[a_field_name].concat(accumulator) existing_accumulator.uniq! unless context.settings[ALLOW_DUPLICATE_VALUES] end end end end class ComposeStep < ToFieldStep attr_reader :indexer def initialize(fieldname, procs, block, source_location, indexer) @indexer = indexer @field_name = fieldname @procs = procs @block = block @source_location = source_location end def execute(context) accumulator = [] source_record = context.source_record if procs procs.call(context.source_record, accumulator, context) else accumulator << context.source_record end accumulator.each_with_index.map do |record, index| new_context = Traject::Indexer::Context.new( source_record: record, settings: indexer.settings, position: index, position_in_input: index ) new_context.clipboard[:parent] = context indexer.map_to_context!(new_context) result = new_context.output_hash if field_name self.class.add_accumulator_to_context! self, field_name, [result], context else result.each do |k, v| self.class.add_accumulator_to_context! self, k, Array(v), context end end end end end end end