class CSVDecision::ScanRow
Data
row object indicating which columns are constants versus procs. @api private
Constants
- NO_CONSTANTS
These column types cannot have constants in their data cells.
Attributes
@return [Array<Integer>] Column indices for simple constants.
@return [Array<Integer>] Column indices for Proc objects.
Public Class Methods
# File lib/csv_decision/scan_row.rb, line 72 def initialize @constants = [] @procs = [] end
Scan
the table cell against all matches.
@param column [Dictionary::Entry] Column dictionary entry. @param matchers [Array<Matchers::Matcher>] @param cell [String] @return [false, Matchers::Proc]
# File lib/csv_decision/scan_row.rb, line 21 def self.scan(column:, matchers:, cell:) return false if cell == '' proc = scan_matchers(column: column, matchers: matchers, cell: cell) return proc if proc # Must be a simple string constant - this is OK except for a certain column types. invalid_constant?(type: :constant, column: column) end
Private Class Methods
A guard column can only use output matchers
# File lib/csv_decision/scan_row.rb, line 46 def self.guard_ins_matcher?(column, matcher) column.type == :guard && !matcher.outs? end
# File lib/csv_decision/scan_row.rb, line 59 def self.invalid_constant?(type:, column:) return false unless type == :constant && NO_CONSTANTS.member?(column.type) raise CellValidationError, "#{column.type}: column cannot contain constants" end
# File lib/csv_decision/scan_row.rb, line 31 def self.scan_matchers(column:, matchers:, cell:) matchers.each do |matcher| # Guard function only accepts the same matchers as an output column. next if guard_ins_matcher?(column, matcher) proc = scan_proc(column: column, cell: cell, matcher: matcher) return proc if proc end # Must be a string constant false end
# File lib/csv_decision/scan_row.rb, line 51 def self.scan_proc(column:, cell:, matcher:) proc = matcher.matches?(cell) invalid_constant?(type: proc.type, column: column) if proc proc end
Public Instance Methods
Match cells in the input hash against a decision table row. @param row (see ScanRow.scan_columns
) @param hash (see Decision#row_scan) @return [Boolean] True for a match, false otherwise.
# File lib/csv_decision/scan_row.rb, line 108 def match?(row:, scan_cols:, hash:) # Check any table row cell constants first, and maybe fail fast... return false if @constants.any? { |col| row[col] != scan_cols[col] } # These table row cells are Proc objects which need evaluating and # must all return a truthy value. @procs.all? { |col| row[col].call(value: scan_cols[col], hash: hash) } end
Scan
all the specified columns
(e.g., inputs) in the given data
row using the matchers
array supplied.
@param row [Array<String>] Data
row - still just all string constants. @param columns [Array<Columns::Entry>] Array of column dictionary entries. @param matchers [Array<Matchers::Matcher>] Array of table cell matchers. @return [Array] Data
row with anything not a string constant replaced with a Proc or a
non-string constant.
# File lib/csv_decision/scan_row.rb, line 85 def scan_columns(row:, columns:, matchers:) columns.each_pair do |col, column| cell = row[col] # An empty input cell matches everything, and so never needs to be scanned, # but it cannot be indexed either. next column.indexed = false if cell == '' && column.ins? # If the column is text only then no special matchers need be used. next @constants << col if column.eval == false # Need to scan the cell against all matchers, and possibly overwrite # the cell contents with a Matchers::Proc value. row[col] = scan_cell(column: column, col: col, matchers: matchers, cell: cell) end row end
Private Instance Methods
# File lib/csv_decision/scan_row.rb, line 119 def scan_cell(column:, col:, matchers:, cell:) # Scan the cell against all the matchers proc = ScanRow.scan(column: column, matchers: matchers, cell: cell) return set(proc: proc, col: col, column: column) if proc # Just a plain constant @constants << col cell end
# File lib/csv_decision/scan_row.rb, line 130 def set(proc:, col:, column:) # Unbox a constant if proc.type == :constant @constants << col return proc.function end @procs << col column.indexed = false proc end