class CSVDecision::Scan

Scan the input hash for all the paths specified in the decision table @api private

Public Class Methods

table(table:, input:, symbolize_keys:) click to toggle source

Main method for making decisions with a table that has paths.

@param table [CSVDecision::Table] Decision table. @param input [Hash] Input hash (keys may or may not be symbolized) @param symbolize_keys [Boolean] Set to false if keys are symbolized and it's

OK to mutate the input hash. Otherwise a copy of the input hash is symbolized.

@return [Hash{Symbol=>Object}] Decision result.

# File lib/csv_decision/scan.rb, line 18
def self.table(table:, input:, symbolize_keys:)
  input = symbolize_keys ? input.deep_symbolize_keys : input
  decision = Decision.new(table: table)
  input_hashes = InputHashes.new

  if table.options[:first_match]
    scan_first_match(input: input, decision: decision, input_hashes: input_hashes)
  else
    scan_accumulate(input: input, decision: decision, input_hashes: input_hashes)
  end
end

Private Class Methods

accumulate(final:, result:) click to toggle source
# File lib/csv_decision/scan.rb, line 76
def self.accumulate(final:, result:)
  return result if final == {}

  final.each_pair { |key, value| final[key] = Array(value) + Array(result[key]) }
  final
end
scan(rows:, input:, final:, decision:) click to toggle source
# File lib/csv_decision/scan.rb, line 63
def self.scan(rows:, input:, final:, decision:)
  # Note that +rows+ must be enclosed in an array for this method to work.
  result = decision.index_scan_accumulate(scan_cols: input[:scan_cols],
                                          hash: input[:hash],
                                          index_rows: [rows])

  # Accumulate this potentially multi-row result into the final result.
  final = accumulate(final: final, result: result) if result.present?

  final
end
scan_accumulate(input:, decision:, input_hashes:) click to toggle source
# File lib/csv_decision/scan.rb, line 48
def self.scan_accumulate(input:, decision:, input_hashes:)
  # Final result
  result = {}

  decision.table.paths.each do |path, rows|
    data = input_hashes.data(decision: decision, path: path, input: input)
    next if data == {}

    result = scan(rows: rows, input: data, final: result, decision: decision)
  end

  result
end
scan_first_match(input:, decision:, input_hashes:) click to toggle source
# File lib/csv_decision/scan.rb, line 30
def self.scan_first_match(input:, decision:, input_hashes:)
  decision.table.paths.each do |path, rows|
    data = input_hashes.data(decision: decision, path: path, input: input)
    next if data == {}

    # Note that +rows+ must be enclosed in an array for this method to work.
    result = decision.index_scan_first_match(
      scan_cols: data[:scan_cols],
      hash: data[:hash],
      index_rows: [rows]
    )
    return result if result != {}
  end

  {}
end