lib/csv_decision/result.rb in csv_decision-0.4.1 vs lib/csv_decision/result.rb in csv_decision-0.5.0
- old
+ new
@@ -20,24 +20,30 @@
# @return [Boolean] Returns true if this is a multi-row result
attr_reader :multi_result
# (see Decision.initialize)
- def initialize(table:, input:)
- # Attributes hash contains the output decision key value pairs
- @attributes = {}
-
+ def initialize(table:)
@outs = table.columns.outs
@outs_functions = table.outs_functions
- @if_columns = table.columns.ifs
+ @table = table
+ end
+ # Initialize the object for new input data.
+ #
+ # @param data [Hash{Symbol=>Object}] Input data hash.
+ # @return [void]
+ def input(data)
+ # Attributes hash contains the output decision key value pairs
+ @attributes = {}
+ @multi_result = false
# Partial result always copies in the input hash for calculating output functions.
# Note that these input key values will not be mutated, as output columns can never
# have the same symbol as an input hash key.
# However, the rest of this hash is mutated as output column evaluation results
# are accumulated.
- @partial_result = input.slice(*table.columns.input_keys) if @outs_functions
+ @partial_result = data.slice(*@table.columns.input_keys) if @outs_functions
end
# Common case for building a single row result is just copying output column values to the
# final result hash.
# @param row [Array]
@@ -55,11 +61,11 @@
# Derive the final result.
# @return [Hash{Symbol=>Object}]
def final_result
# If there are no if: columns, then nothing needs to be filtered out of this result hash.
- return @attributes if @if_columns.empty?
+ return @attributes if @table.columns.ifs.empty?
@multi_result ? multi_row_result : single_row_result
end
# Evaluate the output columns, and use them to start building the final result,
@@ -89,22 +95,22 @@
private
# Case where we have a single row result, which either gets returned
# or filtered by the if: column conditions.
def single_row_result
- @if_columns.each_key do |col|
- return false unless @attributes[col]
-
- # Remove the if: column from the final result hash.
- @attributes.delete(col)
+ # All if: columns must evaluate to true
+ if @table.columns.ifs.keys.all? { |col| @attributes[col] }
+ # Delete if: columns from final result
+ @table.columns.ifs.each_key { |col| @attributes.delete(col) }
+ return @attributes
end
- @attributes
+ false
end
def multi_row_result
- @if_columns.each_key { |col| check_if_column(col) }
+ @table.columns.ifs.each_key { |col| check_if_column(col) }
normalize_result
end
def check_if_column(col)
@@ -129,49 +135,50 @@
def normalize_result
# Peek at the first column's result and see how many rows it contains.
count = @attributes.values.first.count
@multi_result = count > 1
- case count
- when 0
- {}
+ return {} if count.zero?
+ return @attributes.transform_values!(&:first) if count == 1
- # Single row array values do not require arrays.
- when 1
- @attributes.transform_values!(&:first)
-
- else
- @attributes
- end
+ @attributes
end
def eval_outs_constants(row:)
@outs.each_pair do |col, column|
- value = row[col]
- next if value.is_a?(Matchers::Proc)
+ cell = row[col]
+ next if cell.is_a?(Matchers::Proc)
- @partial_result[column.name] = value
- @attributes[column.name] = value
+ @partial_result[column.name] = cell
+ @attributes[column.name] = cell
end
end
def eval_outs_procs(row:)
@outs.each_pair do |col, column|
- proc = row[col]
- next unless proc.is_a?(Matchers::Proc)
+ cell = row[col]
+ next unless cell.is_a?(Matchers::Proc)
- @attributes[column.name] = proc.function[@partial_result]
- @partial_result[column.name] = @attributes[column.name]
+ eval_out_proc(cell: cell, column_name: column.name, column_type: column.type)
end
end
+ def eval_out_proc(cell:, column_name:, column_type:)
+ @attributes[column_name] = cell.function[@partial_result]
+
+ # Do not add if: columns to the partial result
+ return if column_type == :if
+ @partial_result[column_name] = @attributes[column_name]
+ end
+
def partial_result(index)
- @attributes.each_pair do |column_name, value|
+ @attributes.each_pair do |column_name, values|
+ value = values[index]
# Delete this column from the partial result in case there is data from a prior result row
- next @partial_result.delete(column_name) if value[index].is_a?(Matchers::Proc)
+ next @partial_result.delete(column_name) if value.is_a?(Matchers::Proc)
# Add this constant value to the partial result row built so far.
- @partial_result[column_name] = value[index]
+ @partial_result[column_name] = value
end
@partial_result
end
\ No newline at end of file