diff --git a/README.md b/README.md index 6b180f0..495aab1 100644 --- a/README.md +++ b/README.md @@ -269,6 +269,35 @@ table.decide(ISIN: '123456789012', country: 'GB', class: 'private') #=> {PAID: ' ``` +#### Input `path` columns + +For hashes that contain sub-hashes, it's possible to specify a path for the purposes +of matching. (Arrays are currently not supported.) + +```ruby +data = <<~DATA + path:, path:, out :value + header, , :source_name + header, metrics, :service_name + payload, , :amount + payload, ref_data, :account_id +DATA +table = CSVDecision.parse(data, first_match: false) + +input = { + header: { + id: 1, type_cd: 'BUY', source_name: 'Client', client_name: 'AAPL', + metrics: { service_name: 'Trading', receive_time: '12:00' } + }, + payload: { + tran_id: 9, amount: '100.00', + ref_data: { account_id: '5010', type_id: 'BUYL' } + } +} + +table.decide(input) #=> { value: %w[Client Trading 100.00 5010] } +``` + ### Testing `csv_decision` includes thorough [RSpec](http://rspec.info) tests: diff --git a/doc/CSVDecision.html b/doc/CSVDecision.html index d4c3866..85f5674 100644 --- a/doc/CSVDecision.html +++ b/doc/CSVDecision.html @@ -79,7 +79,7 @@
Defined in:
lib/csv_decision.rb,
- lib/csv_decision/data.rb,
lib/csv_decision/load.rb,
lib/csv_decision/index.rb,
lib/csv_decision/input.rb,
lib/csv_decision/parse.rb,
lib/csv_decision/table.rb,
lib/csv_decision/header.rb,
lib/csv_decision/result.rb,
lib/csv_decision/columns.rb,
lib/csv_decision/options.rb,
lib/csv_decision/decision.rb,
lib/csv_decision/defaults.rb,
lib/csv_decision/matchers.rb,
lib/csv_decision/scan_row.rb,
lib/csv_decision/validate.rb,
lib/csv_decision/dictionary.rb,
lib/csv_decision/matchers/guard.rb,
lib/csv_decision/matchers/range.rb,
lib/csv_decision/matchers/symbol.rb,
lib/csv_decision/matchers/numeric.rb,
lib/csv_decision/matchers/pattern.rb,
lib/csv_decision/matchers/constant.rb,
lib/csv_decision/matchers/function.rb
+ lib/csv_decision/data.rb,
lib/csv_decision/load.rb,
lib/csv_decision/scan.rb,
lib/csv_decision/index.rb,
lib/csv_decision/input.rb,
lib/csv_decision/parse.rb,
lib/csv_decision/paths.rb,
lib/csv_decision/table.rb,
lib/csv_decision/header.rb,
lib/csv_decision/result.rb,
lib/csv_decision/columns.rb,
lib/csv_decision/options.rb,
lib/csv_decision/decision.rb,
lib/csv_decision/defaults.rb,
lib/csv_decision/matchers.rb,
lib/csv_decision/scan_row.rb,
lib/csv_decision/validate.rb,
lib/csv_decision/dictionary.rb,
lib/csv_decision/matchers/guard.rb,
lib/csv_decision/matchers/range.rb,
lib/csv_decision/matchers/symbol.rb,
lib/csv_decision/matchers/numeric.rb,
lib/csv_decision/matchers/pattern.rb,
lib/csv_decision/matchers/constant.rb,
lib/csv_decision/matchers/function.rb
@@ -121,7 +121,7 @@

Overview

- Classes: CellValidationError, Columns, Decision, Error, FileError, Index, Matchers, Result, ScanRow, Table, TableValidationError + Classes: CellValidationError, Columns, Decision, Error, FileError, Index, Matchers, Paths, Result, Scan, ScanRow, Table, TableValidationError

@@ -532,12 +532,12 @@

 
 
-46
 47
-48
+48 +49 -
# File 'lib/csv_decision/parse.rb', line 46
+      
# File 'lib/csv_decision/parse.rb', line 47
 
 def self.parse(data, options = {})
   Parse.table(data: data, options: Options.normalize(options))
@@ -611,7 +611,7 @@ 

diff --git a/doc/CSVDecision/CellValidationError.html b/doc/CSVDecision/CellValidationError.html index 37a7df7..37ef6b1 100644 --- a/doc/CSVDecision/CellValidationError.html +++ b/doc/CSVDecision/CellValidationError.html @@ -133,7 +133,7 @@

Overview

diff --git a/doc/CSVDecision/Columns.html b/doc/CSVDecision/Columns.html index 30f658b..2c413f7 100644 --- a/doc/CSVDecision/Columns.html +++ b/doc/CSVDecision/Columns.html @@ -405,6 +405,30 @@

Output columns hash keyed by column index.

+ + + +
  • + + + #paths ⇒ Hash{Index=>Entry} + + + + + + + + + + + private + + +
    +

    path: columns hash keyed by column index.

    +
    +
  • @@ -477,22 +501,22 @@

     
     
    -167
    -168
    -169
    -170
    -171
    -172
    -173
    -174
    -175
    -176
    -177
     178
    -179
    +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 -
    # File 'lib/csv_decision/columns.rb', line 167
    +      
    # File 'lib/csv_decision/columns.rb', line 178
     
     def initialize(table)
       # If a column does not have a valid header cell, then it's empty of data.
    @@ -802,12 +826,12 @@ 

     
     
    -128
    -129
    -130
    +133 +134 +135

    -
    # File 'lib/csv_decision/columns.rb', line 128
    +      
    # File 'lib/csv_decision/columns.rb', line 133
     
     def defaults
       @dictionary&.defaults
    @@ -847,12 +871,12 @@ 

     
     
    -133
    -134
    -135
    +138 +139 +140

    -
    # File 'lib/csv_decision/columns.rb', line 133
    +      
    # File 'lib/csv_decision/columns.rb', line 138
     
     def defaults=(value)
       @dictionary.defaults = value
    @@ -910,12 +934,12 @@ 

     
     
    -139
    -140
    -141
    +144 +145 +146

    -
    # File 'lib/csv_decision/columns.rb', line 139
    +      
    # File 'lib/csv_decision/columns.rb', line 144
     
     def dictionary
       @dictionary.columns
    @@ -968,12 +992,12 @@ 

     
     
    -157
    -158
    -159
    +162 +163 +164

    -
    # File 'lib/csv_decision/columns.rb', line 157
    +      
    # File 'lib/csv_decision/columns.rb', line 162
     
     def ifs
       @dictionary.ifs
    @@ -1031,12 +1055,12 @@ 

     
     
    -162
    -163
    -164
    +173 +174 +175

    -
    # File 'lib/csv_decision/columns.rb', line 162
    +      
    # File 'lib/csv_decision/columns.rb', line 173
     
     def input_keys
       @dictionary.columns.select { |_k, v| v == :in }.keys
    @@ -1089,12 +1113,12 @@ 

     
     
    -145
    -146
    -147
    +150 +151 +152

    -
    # File 'lib/csv_decision/columns.rb', line 145
    +      
    # File 'lib/csv_decision/columns.rb', line 150
     
     def ins
       @dictionary.ins
    @@ -1147,12 +1171,12 @@ 

     
     
    -151
    -152
    -153
    +156 +157 +158

    -
    # File 'lib/csv_decision/columns.rb', line 151
    +      
    # File 'lib/csv_decision/columns.rb', line 156
     
     def outs
       @dictionary&.outs
    @@ -1160,6 +1184,64 @@ 

    + + +
    +

    + + #pathsHash{Index=>Entry} + + + + + +

    +
    +

    + This method is part of a private API. + You should avoid using this method if possible, as it may be removed or be changed in the future. +

    + +

    path: columns hash keyed by column index.

    + + +
    +
    +
    + +

    Returns:

    +
      + +
    • + + + (Hash{Index=>Entry}) + + + +
    • + +
    + +
    + + + + +
    +
    +
    +
    +168
    +169
    +170
    +
    +
    # File 'lib/csv_decision/columns.rb', line 168
    +
    +def paths
    +  @dictionary.paths
    +end
    +
    @@ -1167,7 +1249,7 @@

    diff --git a/doc/CSVDecision/Columns/Dictionary.html b/doc/CSVDecision/Columns/Dictionary.html index c2c2c20..97941c9 100644 --- a/doc/CSVDecision/Columns/Dictionary.html +++ b/doc/CSVDecision/Columns/Dictionary.html @@ -257,6 +257,33 @@

    Instance Attribute Summary collaps

    All output column dictionary entries.

    + + + +
  • + + + #paths ⇒ Hash{Integer=>Symbol} + + + + + + + + + + + + + + private + + +
    +

    All path columns.

    +
    +
  • @@ -335,16 +362,17 @@

     
     
    -118
    -119
    -120
    -121
     122
     123
    -124
    +124 +125 +126 +127 +128 +129

    -
    # File 'lib/csv_decision/columns.rb', line 118
    +      
    # File 'lib/csv_decision/columns.rb', line 122
     
     def initialize
       @columns = {}
    @@ -352,6 +380,7 @@ 

    @ifs = {} @ins = {} @outs = {} + @paths = {} end

    @@ -691,13 +720,78 @@

    + + +
    +

    + + #pathsHash{Integer=>Symbol} + + + + + +

    +
    +

    + This method is part of a private API. + You should avoid using this method if possible, as it may be removed or be changed in the future. +

    + +

    Returns All path columns. This is actually just a subset of :outs.

    + + +
    +
    +
    + +

    Returns:

    +
      + +
    • + + + (Hash{Integer=>Symbol}) + + + + — +
      +

      All path columns. This is actually just a subset of :outs.

      +
      + +
    • + +
    + +
    + + + + +
    +
    +
    +
    +120
    +121
    +122
    +
    +
    # File 'lib/csv_decision/columns.rb', line 120
    +
    +def paths
    +  @paths
    +end
    +
    +
    + diff --git a/doc/CSVDecision/Data.html b/doc/CSVDecision/Data.html index b630396..3db1f81 100644 --- a/doc/CSVDecision/Data.html +++ b/doc/CSVDecision/Data.html @@ -469,7 +469,7 @@

    diff --git a/doc/CSVDecision/Decision.html b/doc/CSVDecision/Decision.html index af2f2f2..3081af8 100644 --- a/doc/CSVDecision/Decision.html +++ b/doc/CSVDecision/Decision.html @@ -118,6 +118,40 @@

    Overview

    +

    Instance Attribute Summary collapse

    +
      + +
    • + + + #first_match ⇒ Boolean + + + + + + + + + readonly + + + + + + + private + + +
      +

      True if a first match decision table.

      +
      + +
    • + + +
    + @@ -147,7 +181,7 @@

    -

    Main method for making decisions.

    +

    Main method for making decisions without a path.

    @@ -165,7 +199,31 @@

  • - #index_scan ⇒ Hash{Symbol=>Object} + #index_scan_accumulate(scan_cols:, hash:, index_rows:) ⇒ Hash{Symbol=>Object} + + + + + + + + + + + private + + +
    +

    Scan the index for an accumulated result.

    +
    + +
  • + + +
  • + + + #index_scan_first_match(scan_cols:, hash:, index_rows:) ⇒ Hash{Symbol=>Object} @@ -180,7 +238,7 @@

    -

    Use an index to scan the decision table up against the input hash.

    +

    Scan the index for a first match result.

  • @@ -189,7 +247,7 @@

  • - #initialize(table:, input:) ⇒ Decision + #initialize(table:) ⇒ Decision @@ -215,7 +273,7 @@

  • - #table_scan ⇒ Hash{Symbol=>Object} + #input(data) ⇒ void @@ -230,7 +288,31 @@

    -

    Scan the decision table up against the input hash.

    +

    Initialize the input data used to make the decision.

    +
    + +

  • + + +
  • + + + #scan(data) ⇒ Hash{Symbol=>Object} + + + + + + + + + + + private + + +
    +

    Scan the decision table and produce an output decision.

  • @@ -245,7 +327,7 @@

    Constructor Details

    - #initialize(table:, input:) ⇒ Decision + #initialize(table:) ⇒ Decision @@ -279,22 +361,6 @@

    Decision table being processed.

    -
    - -

  • - -
  • - - input - - - (Hash{Symbol=>Object}) - - - - — -
    -

    Input hash data structure.

  • @@ -308,37 +374,23 @@

     
     
    +31
     32
     33
     34
     35
     36
    -37
    -38
    -39
    -40
    -41
    -42
    -43
    -44
    -45
    +37

    -
    # File 'lib/csv_decision/decision.rb', line 32
    +      
    # File 'lib/csv_decision/decision.rb', line 31
     
    -def initialize(table:, input:)
    +def initialize(table:)
       # The result object is a hash of values, and each value will be an array if this is
       # a multi-row result for the +first_match: false+ option.
    -  @result = Result.new(table: table, input: input[:hash])
    -
    -  # All rows picked by the matching process. An array if +first_match: false+,
    -  # otherwise a single row.
    -  @rows_picked = []
    -
    +  @result = Result.new(table: table)
       @first_match = table.options[:first_match]
    -
       @table = table
    -  @input = input
     end
    @@ -347,6 +399,76 @@

    +
    +

    Instance Attribute Details

    + + + +
    +

    + + #first_matchBoolean (readonly) + + + + + +

    +
    +

    + This method is part of a private API. + You should avoid using this method if possible, as it may be removed or be changed in the future. +

    + +

    Returns True if a first match decision table.

    + + +
    +
    +
    + +

    Returns:

    +
      + +
    • + + + (Boolean) + + + + — +
      +

      True if a first match decision table.

      +
      + +
    • + +
    + +
    + + + + +
    +
    +
    +
    +28
    +29
    +30
    +
    +
    # File 'lib/csv_decision/decision.rb', line 28
    +
    +def first_match
    +  @first_match
    +end
    +
    +
    + +
    +

    Class Method Details

    @@ -368,7 +490,7 @@

    You should avoid using this method if possible, as it may be removed or be changed in the future.

    -

    Main method for making decisions.

    +

    Main method for making decisions without a path.

    @@ -460,24 +582,18 @@

    22 23 24 -25 -26 -27 -28

    +25
    # File 'lib/csv_decision/decision.rb', line 18
     
     def self.make(table:, input:, symbolize_keys:)
       # Parse and transform the hash supplied as input
    -  input = Input.parse(table: table, input: input, symbolize_keys: symbolize_keys)
    +  data = Input.parse(table: table, input: input, symbolize_keys: symbolize_keys)
     
       # The decision object collects the results of the search and
    -  # calculates the final result
    -  decision = Decision.new(table: table, input: input)
    -
    -  # Use the table's index if present
    -  table.index ? decision.index_scan : decision.table_scan
    +  # calculates the final result.
    +  Decision.new(table: table).scan(data)
     end
    @@ -491,9 +607,9 @@

    Instance Method Details

    -

    +

    - #index_scanHash{Symbol=>Object} + #index_scan_accumulate(scan_cols:, hash:, index_rows:) ⇒ Hash{Symbol=>Object} @@ -506,13 +622,50 @@

    You should avoid using this method if possible, as it may be removed or be changed in the future.

    -

    Use an index to scan the decision table up against the input hash.

    +

    Scan the index for an accumulated result.

    +

    Parameters:

    +
      + +
    • + + scan_cols + + + (Hash{Integer=>Object}) + + + +
    • + +
    • + + hash + + + (Hash{Symbol=>Object}) + + + +
    • + +
    • + + index_rows + + + (Array<Integer>) + + + +
    • +
    +

    Returns:

      @@ -523,10 +676,120 @@

      - — -
      -

      Decision result.

      + + +

    + +
    + + + + +
    +
    +
    +
    +87
    +88
    +89
    +90
    +91
    +92
    +93
    +94
    +95
    +96
    +97
    +98
    +99
    +
    +
    # File 'lib/csv_decision/decision.rb', line 87
    +
    +def index_scan_accumulate(scan_cols:, hash:, index_rows:)
    +  index_rows.each do |start_row, end_row|
    +    @table.each(start_row, end_row || start_row) do |row, index|
    +      next unless @table.scan_rows[index].match?(row: row, hash: hash, scan_cols: scan_cols)
    +
    +      # Accumulate output rows.
    +      @rows_picked << row
    +      @result.accumulate_outs(row)
    +    end
    +  end
    +
    +  @rows_picked.empty? ? {} : accumulated_result
    +end
    +
    + + +
    +

    + + #index_scan_first_match(scan_cols:, hash:, index_rows:) ⇒ Hash{Symbol=>Object} + + + + + +

    +
    +

    + This method is part of a private API. + You should avoid using this method if possible, as it may be removed or be changed in the future. +

    + +

    Scan the index for a first match result.

    + + +
    +
    +

    Parameters:

    +
      + +
    • + + scan_cols + + + (Hash{Integer=>Object}) + + + +
    • + +
    • + + hash + + + (Hash{Symbol=>Object}) + + + +
    • + +
    • + + index_rows + + + (Array<Integer>) + + + +
    • + +
    + +

    Returns:

    +
      + +
    • + + + (Hash{Symbol=>Object}) + +
    • @@ -538,11 +801,6 @@

       
       
      -64
      -65
      -66
      -67
      -68
       69
       70
       71
      @@ -550,23 +808,24 @@ 

      73 74 75 -76

      +76 +77 +78 +79

    -
    # File 'lib/csv_decision/decision.rb', line 64
    -
    -def index_scan
    -  # If the index lookup fails, there's no match.
    -  return {} unless (index_rows = Array(@table.index.hash[@input[:key]]))
    +      
    # File 'lib/csv_decision/decision.rb', line 69
     
    -  hash = @input[:hash]
    -  scan_cols = @input[:scan_cols]
    +def index_scan_first_match(scan_cols:, hash:, index_rows:)
    +  index_rows.each do |start_row, end_row|
    +    @table.each(start_row, end_row || start_row) do |row, index|
    +      next unless @table.scan_rows[index].match?(row: row, hash: hash, scan_cols: scan_cols)
     
    -  if @first_match
    -    index_scan_first_match(scan_cols: scan_cols, hash: hash, index_rows: index_rows)
    -  else
    -    index_scan_accumulate(scan_cols: scan_cols, hash: hash, index_rows: index_rows)
    +      return @result.attributes if first_match_found(row)
    +    end
       end
    +
    +  {}
     end
    @@ -574,9 +833,9 @@

    -

    +

    - #table_scanHash{Symbol=>Object} + #input(data) ⇒ void @@ -588,14 +847,111 @@

    This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

    +

    This method returns an undefined value.

    +

    Initialize the input data used to make the decision.

    -

    Scan the decision table up against the input hash.

    + +

    + +
    +

    Parameters:

    +
      + +
    • + + data + + + (Hash{Symbol=>Object}) + + + + — +
      +

      Input hash data structure.

      +
      + +
    • + +
    + + +
    + + + + +
    +
    +
    +
    +43
    +44
    +45
    +46
    +47
    +48
    +49
    +50
    +51
    +
    +
    # File 'lib/csv_decision/decision.rb', line 43
    +
    +def input(data)
    +  @result.input(data[:hash])
    +
    +  # All rows picked by the matching process. An array if +first_match: false+,
    +  # otherwise a single row.
    +  @rows_picked = []
    +
    +  @input = data
    +end
    +
    + + +
    +

    + + #scan(data) ⇒ Hash{Symbol=>Object} + + + + + +

    +
    +

    + This method is part of a private API. + You should avoid using this method if possible, as it may be removed or be changed in the future. +

    + +

    Scan the decision table and produce an output decision.

    +

    Parameters:

    +
      + +
    • + + data + + + (Hash{Symbol=>Object}) + + + + — +
      +

      Input hash data structure.

      +
      + +
    • +
    +

    Returns:

      @@ -621,29 +977,19 @@

       
       
      -50
      -51
      -52
      -53
      -54
      -55
      -56
       57
       58
      -59
      +59 +60 +61

    -
    # File 'lib/csv_decision/decision.rb', line 50
    -
    -def table_scan
    -  hash = @input[:hash]
    -  scan_cols = @input[:scan_cols]
    +      
    # File 'lib/csv_decision/decision.rb', line 57
     
    -  if @first_match
    -    scan_first_match(hash: hash, scan_cols: scan_cols)
    -  else
    -    scan_accumulate(hash: hash, scan_cols: scan_cols)
    -  end
    +def scan(data)
    +  input(data)
    +  # Use the table's index if present
    +  @table.index ? index_scan : table_scan
     end
    @@ -655,7 +1001,7 @@

    diff --git a/doc/CSVDecision/Defaults.html b/doc/CSVDecision/Defaults.html index b5d031e..6e8c27d 100644 --- a/doc/CSVDecision/Defaults.html +++ b/doc/CSVDecision/Defaults.html @@ -281,7 +281,7 @@

    diff --git a/doc/CSVDecision/Dictionary.html b/doc/CSVDecision/Dictionary.html index 3a2945e..b715828 100644 --- a/doc/CSVDecision/Dictionary.html +++ b/doc/CSVDecision/Dictionary.html @@ -388,16 +388,16 @@

     
     
    -120
     121
     122
     123
     124
     125
    -126
    +126 +127

    -
    # File 'lib/csv_decision/dictionary.rb', line 120
    +      
    # File 'lib/csv_decision/dictionary.rb', line 121
     
     def self.build(header:, dictionary:)
       header.each_with_index do |cell, index|
    @@ -416,7 +416,7 @@ 

    diff --git a/doc/CSVDecision/Dictionary/Entry.html b/doc/CSVDecision/Dictionary/Entry.html index e6081ca..9fd7a74 100644 --- a/doc/CSVDecision/Dictionary/Entry.html +++ b/doc/CSVDecision/Dictionary/Entry.html @@ -448,7 +448,6 @@

     
     
    -91
     92
     93
     94
    @@ -456,10 +455,11 @@ 

    96 97 98 -99

    +99 +100

    -
    # File 'lib/csv_decision/dictionary.rb', line 91
    +      
    # File 'lib/csv_decision/dictionary.rb', line 92
     
     def initialize(name:, type:, eval: nil, set_if: nil, indexed: nil)
       @name = name
    @@ -532,12 +532,12 @@ 

     
     
    -75
     76
    -77
    +77 +78

    -
    # File 'lib/csv_decision/dictionary.rb', line 75
    +      
    # File 'lib/csv_decision/dictionary.rb', line 76
     
     def eval
       @eval
    @@ -599,12 +599,12 @@ 

     
     
    -84
     85
    -86
    +86 +87

    -
    # File 'lib/csv_decision/dictionary.rb', line 84
    +      
    # File 'lib/csv_decision/dictionary.rb', line 85
     
     def function
       @function
    @@ -664,12 +664,12 @@ 

     
     
    -71
     72
    -73
    +73 +74

    -
    # File 'lib/csv_decision/dictionary.rb', line 71
    +      
    # File 'lib/csv_decision/dictionary.rb', line 72
     
     def indexed
       @indexed
    @@ -729,12 +729,12 @@ 

     
     
    -65
     66
    -67
    +67 +68

    -
    # File 'lib/csv_decision/dictionary.rb', line 65
    +      
    # File 'lib/csv_decision/dictionary.rb', line 66
     
     def name
       @name
    @@ -798,12 +798,12 @@ 

     
     
    -80
     81
    -82
    +82 +83

    -
    # File 'lib/csv_decision/dictionary.rb', line 80
    +      
    # File 'lib/csv_decision/dictionary.rb', line 81
     
     def set_if
       @set_if
    @@ -863,12 +863,12 @@ 

     
     
    -68
     69
    -70
    +70 +71

    -
    # File 'lib/csv_decision/dictionary.rb', line 68
    +      
    # File 'lib/csv_decision/dictionary.rb', line 69
     
     def type
       @type
    @@ -970,17 +970,17 @@ 

     
     
    -50
     51
     52
     53
     54
     55
     56
    -57
    +57 +58

    -
    # File 'lib/csv_decision/dictionary.rb', line 50
    +      
    # File 'lib/csv_decision/dictionary.rb', line 51
     
     def self.create(name:, type:)
       entry = ENTRY[type]
    @@ -1049,12 +1049,12 @@ 

     
     
    -60
     61
    -62
    +62 +63

    -
    # File 'lib/csv_decision/dictionary.rb', line 60
    +      
    # File 'lib/csv_decision/dictionary.rb', line 61
     
     def ins?
       @ins
    @@ -1107,17 +1107,17 @@ 

     
     
    -104
     105
     106
     107
     108
     109
     110
    -111
    +111 +112

    -
    # File 'lib/csv_decision/dictionary.rb', line 104
    +      
    # File 'lib/csv_decision/dictionary.rb', line 105
     
     def to_h
       {
    @@ -1137,7 +1137,7 @@ 

    diff --git a/doc/CSVDecision/Error.html b/doc/CSVDecision/Error.html index 769a1cd..bac9b15 100644 --- a/doc/CSVDecision/Error.html +++ b/doc/CSVDecision/Error.html @@ -129,7 +129,7 @@

    Direct Known Subclasses

    diff --git a/doc/CSVDecision/FileError.html b/doc/CSVDecision/FileError.html index d6c665c..783a8d5 100644 --- a/doc/CSVDecision/FileError.html +++ b/doc/CSVDecision/FileError.html @@ -133,7 +133,7 @@

    Overview

    diff --git a/doc/CSVDecision/Header.html b/doc/CSVDecision/Header.html index da825f1..3533400 100644 --- a/doc/CSVDecision/Header.html +++ b/doc/CSVDecision/Header.html @@ -122,7 +122,7 @@

    Constant Summary

    %r{
    -  \A(?<type>in/text|in|out/text|out|guard|if|set/nil\?|set/blank\?|set)
    +  \A(?<type>in/text|in|out/text|out|guard|if|set/nil\?|set/blank\?|set|path)
       \s*:\s*(?<name>\S?.*)\z
     }xi
    @@ -637,7 +637,7 @@

    diff --git a/doc/CSVDecision/Index.html b/doc/CSVDecision/Index.html index b729fbd..a0c050a 100644 --- a/doc/CSVDecision/Index.html +++ b/doc/CSVDecision/Index.html @@ -731,7 +731,7 @@

    diff --git a/doc/CSVDecision/Input.html b/doc/CSVDecision/Input.html index 9740ba3..a04037d 100644 --- a/doc/CSVDecision/Input.html +++ b/doc/CSVDecision/Input.html @@ -127,6 +127,28 @@

    + private + + +
    + + + + +
  • + + + .parse_data(table:, input:) ⇒ Hash{Symbol=>Object} + + + + + + + + + + private @@ -245,7 +267,8 @@

    17 18 19 -20

  • +20 +21
    # File 'lib/csv_decision/input.rb', line 13
    @@ -253,7 +276,8 @@ 

    def self.parse(table:, input:, symbolize_keys:) validate(input) - parsed_input = parse_input(table: table, input: symbolize_keys ? input.symbolize_keys : input) + parsed_input = + parse_data(table: table, input: symbolize_keys ? input.symbolize_keys : input) parsed_input[:key] = parse_key(table: table, hash: parsed_input[:hash]) if table.index parsed_input @@ -261,6 +285,108 @@

    + + +
    +

    + + .parse_data(table:, input:) ⇒ Hash{Symbol=>Object} + + + + + +

    +
    +

    + This method is part of a private API. + You should avoid using this method if possible, as it may be removed or be changed in the future. +

    + + +
    +
    +
    +

    Parameters:

    +
      + +
    • + + table + + + (CSVDecision::Table) + + + + — +
      +

      Decision table.

      +
      + +
    • + +
    • + + input + + + (Hash) + + + + — +
      +

      Input hash (keys may or may not be symbolized)

      +
      + +
    • + +
    + +

    Returns:

    +
      + +
    • + + + (Hash{Symbol=>Object}) + + + +
    • + +
    + +
    + + + + +
    +
    +
    +
    +26
    +27
    +28
    +29
    +30
    +31
    +32
    +33
    +
    +
    # File 'lib/csv_decision/input.rb', line 26
    +
    +def self.parse_data(table:, input:)
    +  defaulted_columns = table.columns.defaults
    +
    +  # Code path optimized for no defaults
    +  return parse_cells(table: table, input: input) if defaulted_columns.empty?
    +
    +  parse_defaulted(table: table, input: input, defaulted_columns: defaulted_columns)
    +end
    +
    @@ -268,7 +394,7 @@

    diff --git a/doc/CSVDecision/Load.html b/doc/CSVDecision/Load.html index 424d274..a093012 100644 --- a/doc/CSVDecision/Load.html +++ b/doc/CSVDecision/Load.html @@ -286,7 +286,7 @@

    diff --git a/doc/CSVDecision/Matchers.html b/doc/CSVDecision/Matchers.html index 70f174d..eb0ca8e 100644 --- a/doc/CSVDecision/Matchers.html +++ b/doc/CSVDecision/Matchers.html @@ -94,8 +94,8 @@
    Defined in:
    -
    lib/csv_decision/matchers.rb,
    - lib/csv_decision.rb,
    lib/csv_decision/matchers/guard.rb,
    lib/csv_decision/matchers/range.rb,
    lib/csv_decision/matchers/symbol.rb,
    lib/csv_decision/matchers/numeric.rb,
    lib/csv_decision/matchers/pattern.rb,
    lib/csv_decision/matchers/constant.rb,
    lib/csv_decision/matchers/function.rb
    +
    lib/csv_decision.rb,
    + lib/csv_decision/matchers.rb,
    lib/csv_decision/matchers/guard.rb,
    lib/csv_decision/matchers/range.rb,
    lib/csv_decision/matchers/symbol.rb,
    lib/csv_decision/matchers/numeric.rb,
    lib/csv_decision/matchers/pattern.rb,
    lib/csv_decision/matchers/constant.rb,
    lib/csv_decision/matchers/function.rb
    @@ -178,7 +178,7 @@

    Constant Summary

    You should avoid using this constant if possible, as it may be removed or be changed in the future.

    -

    Match string for inequality

    +

    Match Regexp for inequality

    @@ -219,7 +219,7 @@

    Constant Summary

    You should avoid using this constant if possible, as it may be removed or be changed in the future.

    -

    Match string for equality

    +

    Match Regexp for equality

    @@ -354,6 +354,30 @@

  • + .compare?(lhs:, compare:, rhs:) ⇒ nil, Boolean + + + + + + + + + + + private + + +
    +

    Compare one object with another if they both respond to the compare method.

    +
    + +
  • + + +
  • + + .normalize_operator(operator) ⇒ String @@ -614,14 +638,14 @@

     
     
    -153
    -154
    -155
    -156
    -157
    +167 +168 +169 +170 +171

  • -
    # File 'lib/csv_decision/matchers.rb', line 153
    +      
    # File 'lib/csv_decision/matchers.rb', line 167
     
     def initialize(options)
       matchers = options[:matchers].collect { |klass| klass.new(options) }
    @@ -688,12 +712,12 @@ 

     
     
    -147
    -148
    -149
    +161 +162 +163

    -
    # File 'lib/csv_decision/matchers.rb', line 147
    +      
    # File 'lib/csv_decision/matchers.rb', line 161
     
     def ins
       @ins
    @@ -753,12 +777,12 @@ 

     
     
    -150
    -151
    -152
    +164 +165 +166

    -
    # File 'lib/csv_decision/matchers.rb', line 150
    +      
    # File 'lib/csv_decision/matchers.rb', line 164
     
     def outs
       @outs
    @@ -776,7 +800,110 @@ 

    Class Method Details

    -

    +

    + + .compare?(lhs:, compare:, rhs:) ⇒ nil, Boolean + + + + + +

    +
    +

    + This method is part of a private API. + You should avoid using this method if possible, as it may be removed or be changed in the future. +

    + +

    Compare one object with another if they both respond to the compare method.

    + + +
    +
    +
    +

    Parameters:

    +
      + +
    • + + lhs + + + (Object) + + + +
    • + +
    • + + compare + + + (Object) + + + +
    • + +
    • + + rhs + + + (Object) + + + +
    • + +
    + +

    Returns:

    +
      + +
    • + + + (nil, Boolean) + + + +
    • + +
    + +
    + + + + +
    +
    +
    +
    +133
    +134
    +135
    +136
    +137
    +138
    +139
    +
    +
    # File 'lib/csv_decision/matchers.rb', line 133
    +
    +def self.compare?(lhs:, compare:, rhs:)
    +  # Is the rhs the same class or a superclass of lhs, and does rhs respond to the
    +  # compare method?
    +  return lhs.send(compare, rhs) if lhs.is_a?(rhs.class) && rhs.respond_to?(compare)
    +
    +  nil
    +end
    +
    +
    + +
    +

    .normalize_operator(operator) ⇒ String @@ -1024,21 +1151,21 @@

     
     
    -133
    -134
    -135
    -136
    -137
    -138
    -139
    -140
    -141
    -142
    -143
    -144
    +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158

    -
    # File 'lib/csv_decision/matchers.rb', line 133
    +      
    # File 'lib/csv_decision/matchers.rb', line 147
     
     def self.parse(columns:, matchers:, row:)
       # Build an array of column indexes requiring simple constant matches,
    @@ -1311,12 +1438,12 @@ 

     
     
    -164
    -165
    -166
    +178 +179 +180

    -
    # File 'lib/csv_decision/matchers.rb', line 164
    +      
    # File 'lib/csv_decision/matchers.rb', line 178
     
     def parse_ins(columns:, row:)
       Matchers.parse(columns: columns, matchers: @ins, row: row)
    @@ -1410,12 +1537,12 @@ 

     
     
    -173
    -174
    -175
    +187 +188 +189

    -
    # File 'lib/csv_decision/matchers.rb', line 173
    +      
    # File 'lib/csv_decision/matchers.rb', line 187
     
     def parse_outs(columns:, row:)
       Matchers.parse(columns: columns, matchers: @outs, row: row)
    @@ -1430,7 +1557,7 @@ 

    diff --git a/doc/CSVDecision/Matchers/Constant.html b/doc/CSVDecision/Matchers/Constant.html index ee0c7aa..8c59b37 100644 --- a/doc/CSVDecision/Matchers/Constant.html +++ b/doc/CSVDecision/Matchers/Constant.html @@ -391,12 +391,12 @@

     
     
    +64
     65
    -66
    -67
    +66

    -
    # File 'lib/csv_decision/matchers/constant.rb', line 65
    +      
    # File 'lib/csv_decision/matchers/constant.rb', line 64
     
     def matches?(cell)
       Matchers::Constant.matches?(cell)
    @@ -454,12 +454,12 @@ 

     
     
    +69
     70
    -71
    -72
    +71

    -
    # File 'lib/csv_decision/matchers/constant.rb', line 70
    +      
    # File 'lib/csv_decision/matchers/constant.rb', line 69
     
     def outs?
       true
    @@ -474,7 +474,7 @@ 

    diff --git a/doc/CSVDecision/Matchers/Function.html b/doc/CSVDecision/Matchers/Function.html index fb0311d..e9f171b 100644 --- a/doc/CSVDecision/Matchers/Function.html +++ b/doc/CSVDecision/Matchers/Function.html @@ -501,7 +501,7 @@

    diff --git a/doc/CSVDecision/Matchers/Guard.html b/doc/CSVDecision/Matchers/Guard.html index 6e518c1..bdb9103 100644 --- a/doc/CSVDecision/Matchers/Guard.html +++ b/doc/CSVDecision/Matchers/Guard.html @@ -311,15 +311,15 @@

     
     
    -132
    -133
    -134
    -135
    -136
    -137
    +123 +124 +125 +126 +127 +128

    -
    # File 'lib/csv_decision/matchers/guard.rb', line 132
    +      
    # File 'lib/csv_decision/matchers/guard.rb', line 123
     
     def self.matches?(cell)
       proc = symbol_proc(cell)
    @@ -410,12 +410,12 @@ 

     
     
    -141
    -142
    -143
    +132 +133 +134

    -
    # File 'lib/csv_decision/matchers/guard.rb', line 141
    +      
    # File 'lib/csv_decision/matchers/guard.rb', line 132
     
     def matches?(cell)
       Guard.matches?(cell)
    @@ -473,12 +473,12 @@ 

     
     
    -146
    -147
    -148
    +137 +138 +139

    -
    # File 'lib/csv_decision/matchers/guard.rb', line 146
    +      
    # File 'lib/csv_decision/matchers/guard.rb', line 137
     
     def outs?
       true
    @@ -493,7 +493,7 @@ 

    diff --git a/doc/CSVDecision/Matchers/Matcher.html b/doc/CSVDecision/Matchers/Matcher.html index a52de55..24f12ae 100644 --- a/doc/CSVDecision/Matchers/Matcher.html +++ b/doc/CSVDecision/Matchers/Matcher.html @@ -267,10 +267,10 @@

     
     
    -179
    +193

    -
    # File 'lib/csv_decision/matchers.rb', line 179
    +      
    # File 'lib/csv_decision/matchers.rb', line 193
     
     def initialize(_options = nil); end
    @@ -333,12 +333,12 @@

     
     
    -201
    -202
    -203
    +215 +216 +217

    -
    # File 'lib/csv_decision/matchers.rb', line 201
    +      
    # File 'lib/csv_decision/matchers.rb', line 215
     
     def ins?
       true
    @@ -418,10 +418,10 @@ 

     
     
    -187
    +201

    -
    # File 'lib/csv_decision/matchers.rb', line 187
    +      
    # File 'lib/csv_decision/matchers.rb', line 201
     
     def matches?(cell); end
    @@ -477,12 +477,12 @@

     
     
    -193
    -194
    -195
    +207 +208 +209

    -
    # File 'lib/csv_decision/matchers.rb', line 193
    +      
    # File 'lib/csv_decision/matchers.rb', line 207
     
     def outs?
       false
    @@ -497,7 +497,7 @@ 

    diff --git a/doc/CSVDecision/Matchers/Numeric.html b/doc/CSVDecision/Matchers/Numeric.html index 9a92a76..666a02c 100644 --- a/doc/CSVDecision/Matchers/Numeric.html +++ b/doc/CSVDecision/Matchers/Numeric.html @@ -291,20 +291,14 @@

    33 34 35 -36 -37 -38 -39

    +36
    # File 'lib/csv_decision/matchers/numeric.rb', line 29
     
     def self.matches?(cell)
    -  match = COMPARISON.match(cell)
    -  return false unless match
    -
    -  numeric_cell = Matchers.to_numeric(match['value'])
    -  return false unless numeric_cell
    +  return false unless (match = COMPARISON.match(cell))
    +  return false unless (numeric_cell = Matchers.to_numeric(match['value']))
     
       comparator = match['comparator']
       Matchers::Proc.new(type: :proc,
    @@ -391,12 +385,12 @@ 

     
     
    -42
    -43
    -44
    +39 +40 +41

    -
    # File 'lib/csv_decision/matchers/numeric.rb', line 42
    +      
    # File 'lib/csv_decision/matchers/numeric.rb', line 39
     
     def matches?(cell)
       Numeric.matches?(cell)
    @@ -411,7 +405,7 @@ 

    diff --git a/doc/CSVDecision/Matchers/Pattern.html b/doc/CSVDecision/Matchers/Pattern.html index f3c7312..f7677d2 100644 --- a/doc/CSVDecision/Matchers/Pattern.html +++ b/doc/CSVDecision/Matchers/Pattern.html @@ -284,13 +284,13 @@

     
     
    +78
     79
     80
    -81
    -82
    +81

    -
    # File 'lib/csv_decision/matchers/pattern.rb', line 79
    +      
    # File 'lib/csv_decision/matchers/pattern.rb', line 78
     
     def initialize(options = {})
       # By default regexp's must have an explicit comparator.
    @@ -351,6 +351,7 @@ 

     
     
    +65
     66
     67
     68
    @@ -360,11 +361,10 @@ 

    72 73 74 -75 -76

    +75

    -
    # File 'lib/csv_decision/matchers/pattern.rb', line 66
    +      
    # File 'lib/csv_decision/matchers/pattern.rb', line 65
     
     def self.matches?(cell, regexp_explicit:)
       comparator, value = regexp?(cell: cell, explicit: regexp_explicit)
    @@ -461,12 +461,12 @@ 

     
     
    +89
     90
    -91
    -92
    +91

    -
    # File 'lib/csv_decision/matchers/pattern.rb', line 90
    +      
    # File 'lib/csv_decision/matchers/pattern.rb', line 89
     
     def matches?(cell)
       Pattern.matches?(cell, regexp_explicit: @regexp_explicit)
    @@ -481,7 +481,7 @@ 

    diff --git a/doc/CSVDecision/Matchers/Proc.html b/doc/CSVDecision/Matchers/Proc.html index 5ad03bd..4bfc627 100644 --- a/doc/CSVDecision/Matchers/Proc.html +++ b/doc/CSVDecision/Matchers/Proc.html @@ -694,7 +694,7 @@

    diff --git a/doc/CSVDecision/Matchers/Range.html b/doc/CSVDecision/Matchers/Range.html index 973ba86..fdbdc76 100644 --- a/doc/CSVDecision/Matchers/Range.html +++ b/doc/CSVDecision/Matchers/Range.html @@ -369,7 +369,7 @@

    diff --git a/doc/CSVDecision/Matchers/Symbol.html b/doc/CSVDecision/Matchers/Symbol.html index 7d3e925..ff70321 100644 --- a/doc/CSVDecision/Matchers/Symbol.html +++ b/doc/CSVDecision/Matchers/Symbol.html @@ -291,37 +291,27 @@

     
     
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    +132 +133 +134 +135 +136 +137 +138 +139 +140

    -
    # File 'lib/csv_decision/matchers/symbol.rb', line 108
    +      
    # File 'lib/csv_decision/matchers/symbol.rb', line 132
     
     def self.matches?(cell)
       return false unless (match = SYMBOL_COMPARE_RE.match(cell))
     
    -  comparator = match['comparator'] || '='
    -  name = match['name'].to_sym
    -  if match['type'] == ':'
    -    comparison(comparator: comparator, name: name)
    +  comparator = match['comparator']
    +  type = match['type']
    +  return false if comparator.nil? && type.nil?
     
    -  # Method call - e.g, .blank? or !.present?
    -  # Can also take the forms: := .blank? or !=.present?
    -  else
    -    method_call(comparator: comparator, name: name)
    -  end
    +  comparator_type(comparator: comparator || '=', type: type, name: match['name'].to_sym)
     end
    @@ -406,12 +396,12 @@

     
     
    -125
    -126
    -127
    +144 +145 +146

    -
    # File 'lib/csv_decision/matchers/symbol.rb', line 125
    +      
    # File 'lib/csv_decision/matchers/symbol.rb', line 144
     
     def matches?(cell)
       Symbol.matches?(cell)
    @@ -426,7 +416,7 @@ 

    diff --git a/doc/CSVDecision/Options.html b/doc/CSVDecision/Options.html index a109324..d7877cf 100644 --- a/doc/CSVDecision/Options.html +++ b/doc/CSVDecision/Options.html @@ -433,7 +433,7 @@

    diff --git a/doc/CSVDecision/Parse.html b/doc/CSVDecision/Parse.html index 0499e6a..6e8045c 100644 --- a/doc/CSVDecision/Parse.html +++ b/doc/CSVDecision/Parse.html @@ -230,7 +230,6 @@

     
     
    -57
     58
     59
     60
    @@ -243,10 +242,11 @@ 

    67 68 69 -70

    +70 +71

    -
    # File 'lib/csv_decision/parse.rb', line 57
    +      
    # File 'lib/csv_decision/parse.rb', line 58
     
     def self.table(data:, options:)
       table = CSVDecision::Table.new
    @@ -272,7 +272,7 @@ 

    diff --git a/doc/CSVDecision/Paths.html b/doc/CSVDecision/Paths.html new file mode 100644 index 0000000..89a7197 --- /dev/null +++ b/doc/CSVDecision/Paths.html @@ -0,0 +1,742 @@ + + + + + + + Class: CSVDecision::Paths + + — Documentation by YARD 0.9.12 + + + + + + + + + + + + + + + + + + + +
    + + +

    Class: CSVDecision::Paths + + + Private +

    +
    + +
    +
    Inherits:
    +
    + Object + +
      +
    • Object
    • + + + +
    + show all + +
    +
    + + + + + + + + + + + +
    +
    Defined in:
    +
    lib/csv_decision/paths.rb
    +
    + +
    + +

    Overview

    +
    +

    + This class is part of a private API. + You should avoid using this class if possible, as it may be removed or be changed in the future. +

    + +

    Build an index for a decision table with one or more input columns +designated as keys

    + + +
    +
    +
    + + +
    + + + +

    Instance Attribute Summary collapse

    +
      + +
    • + + + #paths ⇒ Hash + + + + + + + + + readonly + + + + + + + private + + +
      +

      The index hash mapping in input values to one or more data array row +indexes.

      +
      + +
    • + + +
    + + + + + +

    + Class Method Summary + collapse +

    + + + +

    + Instance Method Summary + collapse +

    + + + + +
    +

    Constructor Details

    + +
    +

    + + #initialize(table:, columns:) ⇒ Paths + + + + + +

    +
    +

    + This method is part of a private API. + You should avoid using this method if possible, as it may be removed or be changed in the future. +

    + +

    Returns a new instance of Paths

    + + +
    +
    +
    +

    Parameters:

    +
      + +
    • + + table + + + (CSVDecision::Table) + + + + — +
      +

      Decision table.

      +
      + +
    • + +
    • + + columns + + + (Array<Index>) + + + + — +
      +

      Array of column indexes to be indexed.

      +
      + +
    • + +
    + + +
    + + + + +
    +
    +
    +
    +45
    +46
    +47
    +48
    +49
    +50
    +51
    +52
    +
    +
    # File 'lib/csv_decision/paths.rb', line 45
    +
    +def initialize(table:, columns:)
    +  @paths = []
    +  @columns = columns
    +
    +  build(table)
    +
    +  freeze
    +end
    +
    +
    + +
    + +
    +

    Instance Attribute Details

    + + + +
    +

    + + #pathsHash (readonly) + + + + + +

    +
    +

    + This method is part of a private API. + You should avoid using this method if possible, as it may be removed or be changed in the future. +

    + +

    Returns The index hash mapping in input values to one or more data array +row indexes.

    + + +
    +
    +
    + +

    Returns:

    +
      + +
    • + + + (Hash) + + + + — +
      +

      The index hash mapping in input values to one or more data array row +indexes.

      +
      + +
    • + +
    + +
    + + + + +
    +
    +
    +
    +41
    +42
    +43
    +
    +
    # File 'lib/csv_decision/paths.rb', line 41
    +
    +def paths
    +  @paths
    +end
    +
    +
    + +
    + + +
    +

    Class Method Details

    + + +
    +

    + + .scan(table:) ⇒ CSVDecision::Paths + + + + + +

    +
    +

    + This method is part of a private API. + You should avoid using this method if possible, as it may be removed or be changed in the future. +

    + +

    Build the index of paths

    + + +
    +
    +
    +

    Parameters:

    +
      + +
    • + + table + + + (CSVDecision::Table) + + + + — +
      +

      Decision table being indexed.

      +
      + +
    • + +
    + +

    Returns:

    + + +
    + + + + +
    +
    +
    +
    +16
    +17
    +18
    +19
    +20
    +21
    +22
    +
    +
    # File 'lib/csv_decision/paths.rb', line 16
    +
    +def self.scan(table:)
    +  # Do we even have paths?
    +  columns = table.columns.paths.keys
    +  return [] if columns.empty?
    +
    +  table.paths = Paths.new(table: table, columns: columns).paths
    +end
    +
    +
    + +
    +

    + + .symbol(value) ⇒ nil, Symbol + + + + + +

    +
    +

    + This method is part of a private API. + You should avoid using this method if possible, as it may be removed or be changed in the future. +

    + +

    Returns Non-empty string converted to a symbol.

    + + +
    +
    +
    +

    Parameters:

    +
      + +
    • + + value + + + (String) + + + + — +
      +

      Cell value for the path: column.

      +
      + +
    • + +
    + +

    Returns:

    +
      + +
    • + + + (nil, Symbol) + + + + — +
      +

      Non-empty string converted to a symbol.

      +
      + +
    • + +
    + +
    + + + + +
    +
    +
    +
    +36
    +37
    +38
    +
    +
    # File 'lib/csv_decision/paths.rb', line 36
    +
    +def self.symbol(value)
    +  value.blank? ? nil : value.to_sym
    +end
    +
    +
    + +
    +

    + + .value(current_value, index) ⇒ Integer, Array + + + + + +

    +
    +

    + This method is part of a private API. + You should avoid using this method if possible, as it may be removed or be changed in the future. +

    + +

    Returns New path key value.

    + + +
    +
    +
    +

    Parameters:

    +
      + +
    • + + current_value + + + (Integer, Array) + + + + — +
      +

      Current path value.

      +
      + +
    • + +
    • + + index + + + (Integer) + + + + — +
      +

      Array row index to be included in the path entry.

      +
      + +
    • + +
    + +

    Returns:

    +
      + +
    • + + + (Integer, Array) + + + + — +
      +

      New path key value.

      +
      + +
    • + +
    + +
    + + + + +
    +
    +
    +
    +27
    +28
    +29
    +30
    +31
    +32
    +
    +
    # File 'lib/csv_decision/paths.rb', line 27
    +
    +def self.value(current_value, index)
    +  return [current_value, index] if current_value.is_a?(Integer)
    +
    +  current_value[-1] = index
    +  current_value
    +end
    +
    +
    + +
    + +
    + + + +
    + + \ No newline at end of file diff --git a/doc/CSVDecision/Result.html b/doc/CSVDecision/Result.html index 3419ac4..d48512b 100644 --- a/doc/CSVDecision/Result.html +++ b/doc/CSVDecision/Result.html @@ -376,7 +376,7 @@

  • - #initialize(table:, input:) ⇒ Object + #initialize(table:) ⇒ Object @@ -394,6 +394,30 @@

    +

  • + + +
  • + + + #input(data) ⇒ void + + + + + + + + + + + private + + +
    +

    Initialize the object for new input data.

    +
    +
  • @@ -406,7 +430,7 @@

    Constructor Details

    - #initialize(table:, input:) ⇒ Object + #initialize(table:) ⇒ Object @@ -434,22 +458,6 @@

    Decision table being processed.

    -
    - - - -
  • - - input - - - (Hash{Symbol=>Object}) - - - - — -
    -

    Input hash data structure.

  • @@ -467,35 +475,15 @@

    26 27 28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39

    +29
    # File 'lib/csv_decision/result.rb', line 25
     
    -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
    -
    -  # 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
    +  @table = table
     end
    @@ -821,12 +809,12 @@

     
     
    -52
    -53
    -54
    +58 +59 +60

    -
    # File 'lib/csv_decision/result.rb', line 52
    +      
    # File 'lib/csv_decision/result.rb', line 58
     
     def accumulate_outs(row)
       @outs.each_pair { |col, column| add_cell(column_name: column.name, cell: row[col]) }
    @@ -882,12 +870,12 @@ 

     
     
    -45
    -46
    -47
    +51 +52 +53

    -
    # File 'lib/csv_decision/result.rb', line 45
    +      
    # File 'lib/csv_decision/result.rb', line 51
     
     def add_outs(row)
       @outs.each_pair { |col, column| @attributes[column.name] = row[col] }
    @@ -964,12 +952,12 @@ 

     
     
    -85
    -86
    -87
    +91 +92 +93

    -
    # File 'lib/csv_decision/result.rb', line 85
    +      
    # File 'lib/csv_decision/result.rb', line 91
     
     def eval_cell_proc(proc:, column_name:, index:)
       @attributes[column_name][index] = proc.function[partial_result(index)]
    @@ -1025,18 +1013,18 @@ 

     
     
    -70
    -71
    -72
    -73
    -74
    -75
     76
     77
    -78
    +78 +79 +80 +81 +82 +83 +84

    -
    # File 'lib/csv_decision/result.rb', line 70
    +      
    # File 'lib/csv_decision/result.rb', line 76
     
     def eval_outs(row)
       # Set the constants first, in case the functions refer to them
    @@ -1095,25 +1083,106 @@ 

     
     
    -58
    -59
    -60
    -61
    -62
    -63
    +64 +65 +66 +67 +68 +69

    -
    # File 'lib/csv_decision/result.rb', line 58
    +      
    # File 'lib/csv_decision/result.rb', line 64
     
     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
    + + +
    +

    + + #input(data) ⇒ void + + + + + +

    +
    +

    + This method is part of a private API. + You should avoid using this method if possible, as it may be removed or be changed in the future. +

    +

    This method returns an undefined value.

    +

    Initialize the object for new input data.

    + + +
    +
    +
    +

    Parameters:

    +
      + +
    • + + data + + + (Hash{Symbol=>Object}) + + + + — +
      +

      Input data hash.

      +
      + +
    • + +
    + + +
    + + + + +
    +
    +
    +
    +35
    +36
    +37
    +38
    +39
    +40
    +41
    +42
    +43
    +44
    +45
    +
    +
    # File 'lib/csv_decision/result.rb', line 35
    +
    +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 = data.slice(*@table.columns.input_keys) if @outs_functions
    +end
    +
    @@ -1121,7 +1190,7 @@

    diff --git a/doc/CSVDecision/Scan.html b/doc/CSVDecision/Scan.html new file mode 100644 index 0000000..20c7c72 --- /dev/null +++ b/doc/CSVDecision/Scan.html @@ -0,0 +1,313 @@ + + + + + + + Class: CSVDecision::Scan + + — Documentation by YARD 0.9.12 + + + + + + + + + + + + + + + + + + + +
    + + +

    Class: CSVDecision::Scan + + + Private +

    +
    + +
    +
    Inherits:
    +
    + Object + +
      +
    • Object
    • + + + +
    + show all + +
    +
    + + + + + + + + + + + +
    +
    Defined in:
    +
    lib/csv_decision/scan.rb
    +
    + +
    + +

    Overview

    +
    +

    + This class is part of a private API. + You should avoid using this class if possible, as it may be removed or be changed in the future. +

    + +

    Scan the input hash for all the paths specified in the decision table

    + + +
    +
    +
    + + +

    Defined Under Namespace

    +

    + + + + + Classes: InputHashes + + +

    + + + + + + + + +

    + Class Method Summary + collapse +

    + + + + + + +
    +

    Class Method Details

    + + +
    +

    + + .table(table:, input:, symbolize_keys:) ⇒ Hash{Symbol=>Object} + + + + + +

    +
    +

    + This method is part of a private API. + You should avoid using this method if possible, as it may be removed or be changed in the future. +

    + +

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

    + + +
    +
    +
    +

    Parameters:

    +
      + +
    • + + table + + + (CSVDecision::Table) + + + + — +
      +

      Decision table.

      +
      + +
    • + +
    • + + input + + + (Hash) + + + + — +
      +

      Input hash (keys may or may not be symbolized)

      +
      + +
    • + +
    • + + 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.

      +
      + +
    • + +
    + +

    Returns:

    +
      + +
    • + + + (Hash{Symbol=>Object}) + + + + — +
      +

      Decision result.

      +
      + +
    • + +
    + +
    + + + + +
    +
    +
    +
    +18
    +19
    +20
    +21
    +22
    +23
    +24
    +25
    +
    +
    # File 'lib/csv_decision/scan.rb', line 18
    +
    +def self.table(table:, input:, symbolize_keys:)
    +  scan_table(
    +    table: table,
    +    input: symbolize_keys ? input.deep_symbolize_keys : input,
    +    decision: Decision.new(table: table),
    +    input_hashes: InputHashes.new
    +  )
    +end
    +
    +
    + +
    + +
    + + + +
    + + \ No newline at end of file diff --git a/doc/CSVDecision/Scan/InputHashes.html b/doc/CSVDecision/Scan/InputHashes.html new file mode 100644 index 0000000..4c2e29e --- /dev/null +++ b/doc/CSVDecision/Scan/InputHashes.html @@ -0,0 +1,369 @@ + + + + + + + Class: CSVDecision::Scan::InputHashes + + — Documentation by YARD 0.9.12 + + + + + + + + + + + + + + + + + + + +
    + + +

    Class: CSVDecision::Scan::InputHashes + + + Private +

    +
    + +
    +
    Inherits:
    +
    + Object + +
      +
    • Object
    • + + + +
    + show all + +
    +
    + + + + + + + + + + + +
    +
    Defined in:
    +
    lib/csv_decision/scan.rb
    +
    + +
    + +

    Overview

    +
    +

    + This class is part of a private API. + You should avoid using this class if possible, as it may be removed or be changed in the future. +

    + +

    Derive the parsed input hash, using a cache for speed.

    + + +
    +
    +
    + + +
    + + + + + + + +

    + Instance Method Summary + collapse +

    + + + + +
    +

    Constructor Details

    + +
    +

    + + #initializeInputHashes + + + + + +

    +
    +

    + This method is part of a private API. + You should avoid using this method if possible, as it may be removed or be changed in the future. +

    + +

    Returns a new instance of InputHashes

    + + +
    +
    +
    + + +
    + + + + +
    +
    +
    +
    +71
    +72
    +73
    +
    +
    # File 'lib/csv_decision/scan.rb', line 71
    +
    +def initialize
    +  @input_hashes = {}
    +end
    +
    +
    + +
    + + +
    +

    Instance Method Details

    + + +
    +

    + + #data(table:, path:, input:) ⇒ Hash{Symbol=>Object} + + + + + +

    +
    +

    + This method is part of a private API. + You should avoid using this method if possible, as it may be removed or be changed in the future. +

    + +

    Returns Parsed input hash.

    + + +
    +
    +
    +

    Parameters:

    +
      + +
    • + + path + + + (Array<Symbol] Path for the input hash.) + + + + — +
      +

      ath [Array<Symbol] Path for the input hash.

      +
      + +
    • + +
    • + + input + + + (Hash{Symbol=>Object}) + + + + — +
      +

      Input hash.

      +
      + +
    • + +
    + +

    Returns:

    +
      + +
    • + + + (Hash{Symbol=>Object}) + + + + — +
      +

      Parsed input hash.

      +
      + +
    • + +
    + +
    + + + + +
    +
    +
    +
    +78
    +79
    +80
    +81
    +82
    +83
    +84
    +85
    +86
    +87
    +88
    +89
    +
    +
    # File 'lib/csv_decision/scan.rb', line 78
    +
    +def data(table:, path:, input:)
    +  return @input_hashes[path] if @input_hashes.key?(path)
    +
    +  # Use the path - an array of symbol keys, to dig out the input sub-hash
    +  hash = path.empty? ? input : input.dig(*path)
    +
    +  # Parse and transform the hash supplied as input
    +  data = hash.blank? ? {} : Input.parse_data(table: table, input: hash)
    +
    +  # Cache the parsed input hash data for this path
    +  @input_hashes[path] = data
    +end
    +
    +
    + +
    + +
    + + + +
    + + \ No newline at end of file diff --git a/doc/CSVDecision/ScanRow.html b/doc/CSVDecision/ScanRow.html index ea2f4f4..dc51602 100644 --- a/doc/CSVDecision/ScanRow.html +++ b/doc/CSVDecision/ScanRow.html @@ -856,7 +856,7 @@

    diff --git a/doc/CSVDecision/Table.html b/doc/CSVDecision/Table.html index 3dece51..ee30f81 100644 --- a/doc/CSVDecision/Table.html +++ b/doc/CSVDecision/Table.html @@ -165,7 +165,7 @@

    Instance Attribute Summary collaps
    -

    File path name if decision table was loaded from a CSV file.

    +

    CSV file.

    @@ -303,6 +303,33 @@

    Instance Attribute Summary collaps

    Used to implement outputting of final results.

    + + + +
  • + + + #paths ⇒ CSVDecision::Path + + + + + + + + + + + + + + + + +
    +

    The array of paths built on one or more input columns.

    +
    +
  • @@ -509,25 +536,19 @@

     
     
    -79
    -80
    -81
    -82
     83
     84
     85
     86
     87
    -88
    +88 +89

    -
    # File 'lib/csv_decision/table.rb', line 79
    +      
    # File 'lib/csv_decision/table.rb', line 83
     
     def initialize
    -  @file = nil
    -  @index = nil
    -  @options = nil
    -  @outs_functions = nil
    +  @paths = []
       @outs_rows = []
       @if_rows = []
       @rows = []
    @@ -618,7 +639,7 @@ 

    -

    Returns File path name if decision table was loaded from a CSV file.

    +

    CSV file.

    @@ -637,7 +658,7 @@

    -

    File path name if decision table was loaded from a CSV file.

    +

    File path name if decision table was loaded from a

    @@ -650,12 +671,12 @@

     
     
    -34
     35
    -36
    +36 +37

    -
    # File 'lib/csv_decision/table.rb', line 34
    +      
    # File 'lib/csv_decision/table.rb', line 35
     
     def file
       @file
    @@ -715,12 +736,12 @@ 

     
     
    -61
    -62
    -63
    +65 +66 +67

    -
    # File 'lib/csv_decision/table.rb', line 61
    +      
    # File 'lib/csv_decision/table.rb', line 65
     
     def if_rows
       @if_rows
    @@ -776,12 +797,12 @@ 

     
     
    -37
     38
    -39
    +39 +40

    -
    # File 'lib/csv_decision/table.rb', line 37
    +      
    # File 'lib/csv_decision/table.rb', line 38
     
     def index
       @index
    @@ -837,12 +858,12 @@ 

     
     
    -40
    -41
    -42
    +44 +45 +46

    -
    # File 'lib/csv_decision/table.rb', line 40
    +      
    # File 'lib/csv_decision/table.rb', line 44
     
     def options
       @options
    @@ -884,12 +905,12 @@ 

     
     
    -44
    -45
    -46
    +48 +49 +50

    -
    # File 'lib/csv_decision/table.rb', line 44
    +      
    # File 'lib/csv_decision/table.rb', line 48
     
     def outs_functions
       @outs_functions
    @@ -949,12 +970,12 @@ 

     
     
    -57
    -58
    -59
    +61 +62 +63

    -
    # File 'lib/csv_decision/table.rb', line 57
    +      
    # File 'lib/csv_decision/table.rb', line 61
     
     def outs_rows
       @outs_rows
    @@ -965,6 +986,67 @@ 

    + +
    +

    + + #pathsCSVDecision::Path + + + + + +

    +
    + +

    Returns The array of paths built on one or more input columns.

    + + +
    +
    +
    + +

    Returns:

    +
      + +
    • + + + (CSVDecision::Path) + + + + — +
      +

      The array of paths built on one or more input columns.

      +
      + +
    • + +
    + +
    + + + + +
    +
    +
    +
    +41
    +42
    +43
    +
    +
    # File 'lib/csv_decision/table.rb', line 41
    +
    +def paths
    +  @paths
    +end
    +
    +
    + +

    @@ -1014,12 +1096,12 @@

     
     
    -48
    -49
    -50
    +52 +53 +54

    -
    # File 'lib/csv_decision/table.rb', line 48
    +      
    # File 'lib/csv_decision/table.rb', line 52
     
     def rows
       @rows
    @@ -1079,12 +1161,12 @@ 

     
     
    -53
    -54
    -55
    +57 +58 +59

    -
    # File 'lib/csv_decision/table.rb', line 53
    +      
    # File 'lib/csv_decision/table.rb', line 57
     
     def scan_rows
       @scan_rows
    @@ -1181,7 +1263,7 @@ 

    # File 'lib/csv_decision/table.rb', line 15
     
     def decide(input)
    -  Decision.make(table: self, input: input, symbolize_keys: true)
    +  decision(input: input, symbolize_keys: true)
     end
    @@ -1270,7 +1352,7 @@

    # File 'lib/csv_decision/table.rb', line 26
     
     def decide!(input)
    -  Decision.make(table: self, input: input, symbolize_keys: false)
    +  decision( input: input, symbolize_keys: false)
     end
    @@ -1348,17 +1430,17 @@

     
     
    -69
    -70
    -71
    -72
     73
     74
     75
    -76
    +76 +77 +78 +79 +80

    -
    # File 'lib/csv_decision/table.rb', line 69
    +      
    # File 'lib/csv_decision/table.rb', line 73
     
     def each(first = 0, last = @rows.count - 1)
       index = first
    @@ -1378,7 +1460,7 @@ 

    diff --git a/doc/CSVDecision/TableValidationError.html b/doc/CSVDecision/TableValidationError.html index 70fd64b..e81aef4 100644 --- a/doc/CSVDecision/TableValidationError.html +++ b/doc/CSVDecision/TableValidationError.html @@ -133,7 +133,7 @@

    Overview

    diff --git a/doc/CSVDecision/Validate.html b/doc/CSVDecision/Validate.html index d5e98c3..3e16539 100644 --- a/doc/CSVDecision/Validate.html +++ b/doc/CSVDecision/Validate.html @@ -412,7 +412,7 @@

    diff --git a/doc/_index.html b/doc/_index.html index 63f92ab..9d2da00 100644 --- a/doc/_index.html +++ b/doc/_index.html @@ -136,16 +136,16 @@

    Namespace Listing A-Z

  • - Dictionary + Dictionary - (CSVDecision::Columns) + (CSVDecision)
  • - Dictionary + Dictionary - (CSVDecision) + (CSVDecision::Columns)
  • @@ -245,6 +245,13 @@

    Namespace Listing A-Z

    +
  • + InputHashes + + (CSVDecision::Scan) + +
  • + @@ -330,6 +337,13 @@

    Namespace Listing A-Z

    +
  • + Paths + + (CSVDecision) + +
  • +
  • Pattern @@ -374,6 +388,13 @@

    Namespace Listing A-Z

  • S
    • +
    • + Scan + + (CSVDecision) + +
    • +
    • ScanRow @@ -440,7 +461,7 @@

      Namespace Listing A-Z

      diff --git a/doc/class_list.html b/doc/class_list.html index 3ebf847..c9bba2a 100644 --- a/doc/class_list.html +++ b/doc/class_list.html @@ -43,7 +43,7 @@

      Class List

      diff --git a/doc/file.README.html b/doc/file.README.html index 9c5f96a..46b9988 100644 --- a/doc/file.README.html +++ b/doc/file.README.html @@ -86,10 +86,9 @@

      Why use csv_decision?

      Typical “business logic” is notoriously illogical - full of corner cases and one-off exceptions. A decision table can express data-based decisions -in a way that comes more naturally to subject matter experts, who typically -prefer spreadsheet models. Business logic may then be encapsulated, -avoiding the need to write tortuous conditional expressions in Ruby that -draw the ire of rubocop and its ilk.

      +in a way that comes naturally to subject matter experts, who typically use +spreadsheet models. Business logic can be encapsulated in a table, avoiding +the need for tortuous conditional expressions.

      This gem and the examples below take inspiration from rufus/decision. @@ -125,9 +124,8 @@

      Simple example

      | | Zach

    When the topic is finance and the region is -Europe the team member Donald is selected.

    - -

    This is a “first match” decision table in that as soon as a match is made +Europe the team member Donald is selected. This +is a “first match” decision table in that as soon as a match is made execution stops and a single output row (hash) is returned.

    The ordering of rows matters. Ernest, who is in charge of @@ -137,7 +135,7 @@

    Simple example

    has been placed last, catching all the input combos not matching any other row.

    -

    Here is the example as code:

    +

    Here's the example as code:

    “`ruby # Valid CSV string data = <<~DATA in :topic, in :region, out :team_member sports, Europe, Alice sports, , Bob finance, America, @@ -152,7 +150,7 @@

    Simple example

    'culture', region: 'America') #=> { team_member: 'Zach' } “`

    -

    An empty in: cell means “matches any value”, even nils.

    +

    An empty in: cell means “matches any value”.

    Note that all column header names are symbolized, so it's actually more accurate to write in :topic; however spaces before and after @@ -181,39 +179,33 @@

    Simple example

    CSV Decision features

    • Either returns the first matching row as a hash (default), or accumulates -all matches as an array of hashes (i.e., parse option -first_match: false or CSV file option +all matches as an array of hashes (i.e., parse option +first_match: false or CSV file option accumulate).

    • Fast decision-time performance (see benchmarks folder). -Automatically indexes all text-only columns that do not contain any empty -strings.

      +Automatically indexes all constants-only columns that do not contain any +empty strings.

    • -

      In addition to simple strings, csv_decision can match basic -Ruby constants (e.g., =nil), regular expressions (e.g., -=~ on|off), comparisons (e.g., > 100.0 ) and -Ruby-style ranges (e.g., 1..10)

      +

      In addition to strings, can match basic Ruby constants (e.g., +=nil), regular expressions (e.g., =~ on|off), +comparisons (e.g., > 100.0 ) and Ruby-style ranges (e.g., +1..10)

    • Can compare an input column versus another input hash key - e.g., > :column.

    • Any cell starting with # is treated as a comment, and comments -may appear anywhere in the table. (Comment cells are always interpreted as -the empty string.)

      +may appear anywhere in the table.

    • -

      Can use column symbol expressions or Ruby methods (0-arity) in input +

      Column symbol expressions or Ruby methods (0-arity) may be used in input columns for matching - e.g., :column.zero? or :column == 0.

    • May also use Ruby methods in output columns - e.g., :column.length.

    • -

      Accepts data as a file, CSV string or an array of arrays. (For safety all -input data is force encoded to UTF-8, and non-ascii strings are converted -to empty strings.)

      -
    • -

      All CSV cells are parsed for correctness, and helpful error messages -generated for bad input.

      +

      Accepts data as a file, CSV string or an array of arrays.

    Constants other than strings

    @@ -263,7 +255,9 @@

    Column header symbols

    operators are also supported: !=, >, >=, <, <=. In addition, you can also apply a Ruby 0-arity method - e.g., .present? or -.nil?. Negation is also supported - e.g., !.nil?.

    +.nil?. Negation is also supported - e.g., !.nil?. +Note that .nil? can also be written as := nil?, +and !.nil? as := !nil?, depending on preference.

    For more simple examples see spec/csv_decision/examples_spec.rb.

    @@ -347,6 +341,34 @@

    Input set columns

    table.decide(ISIN: '123456789012', country: 'GB', class: 'private') #=> {PAID: '123456789012', len: 12}
    +

    Input path columns

    + +

    For hashes that contain sub-hashes, it's possible to specify a path for +the purposes of matching. (Arrays are currently not supported.)

    + +
    data = <<~DATA
    +  path:,   path:,    out :value
    +  header,  ,         :source_name
    +  header,  metrics,  :service_name
    +  payload, ,         :amount
    +  payload, ref_data, :account_id
    +DATA
    +table = CSVDecision.parse(data, first_match: false)
    +
    +input = {
    +  header: { 
    +    id: 1, type_cd: 'BUY', source_name: 'Client', client_name: 'AAPL',
    +    metrics: { service_name: 'Trading', receive_time: '12:00' } 
    +  },
    +  payload: { 
    +    tran_id: 9, amount: '100.00',
    +    ref_data: { account_id: '5010', type_id: 'BUYL' } 
    +  }
    +}
    +
    +table.decide(input) #=> { value: %w[Client Trading 100.00 5010] }
    +
    +

    Testing

    csv_decision includes thorough License

    diff --git a/doc/index.html b/doc/index.html index e610a53..943c869 100644 --- a/doc/index.html +++ b/doc/index.html @@ -86,10 +86,9 @@

    Why use csv_decision?

    Typical “business logic” is notoriously illogical - full of corner cases and one-off exceptions. A decision table can express data-based decisions -in a way that comes more naturally to subject matter experts, who typically -prefer spreadsheet models. Business logic may then be encapsulated, -avoiding the need to write tortuous conditional expressions in Ruby that -draw the ire of rubocop and its ilk.

    +in a way that comes naturally to subject matter experts, who typically use +spreadsheet models. Business logic can be encapsulated in a table, avoiding +the need for tortuous conditional expressions.

    This gem and the examples below take inspiration from rufus/decision. @@ -125,9 +124,8 @@

    Simple example

    | | Zach

    When the topic is finance and the region is -Europe the team member Donald is selected.

    - -

    This is a “first match” decision table in that as soon as a match is made +Europe the team member Donald is selected. This +is a “first match” decision table in that as soon as a match is made execution stops and a single output row (hash) is returned.

    The ordering of rows matters. Ernest, who is in charge of @@ -137,7 +135,7 @@

    Simple example

    has been placed last, catching all the input combos not matching any other row.

    -

    Here is the example as code:

    +

    Here's the example as code:

    “`ruby # Valid CSV string data = <<~DATA in :topic, in :region, out :team_member sports, Europe, Alice sports, , Bob finance, America, @@ -152,7 +150,7 @@

    Simple example

    'culture', region: 'America') #=> { team_member: 'Zach' } “`

    -

    An empty in: cell means “matches any value”, even nils.

    +

    An empty in: cell means “matches any value”.

    Note that all column header names are symbolized, so it's actually more accurate to write in :topic; however spaces before and after @@ -181,39 +179,33 @@

    Simple example

    CSV Decision features

    Constants other than strings

    @@ -263,7 +255,9 @@

    Column header symbols

    operators are also supported: !=, >, >=, <, <=. In addition, you can also apply a Ruby 0-arity method - e.g., .present? or -.nil?. Negation is also supported - e.g., !.nil?.

    +.nil?. Negation is also supported - e.g., !.nil?. +Note that .nil? can also be written as := nil?, +and !.nil? as := !nil?, depending on preference.

    For more simple examples see spec/csv_decision/examples_spec.rb.

    @@ -347,6 +341,34 @@

    Input set columns

    table.decide(ISIN: '123456789012', country: 'GB', class: 'private') #=> {PAID: '123456789012', len: 12} +

    Input path columns

    + +

    For hashes that contain sub-hashes, it's possible to specify a path for +the purposes of matching. (Arrays are currently not supported.)

    + +
    data = <<~DATA
    +  path:,   path:,    out :value
    +  header,  ,         :source_name
    +  header,  metrics,  :service_name
    +  payload, ,         :amount
    +  payload, ref_data, :account_id
    +DATA
    +table = CSVDecision.parse(data, first_match: false)
    +
    +input = {
    +  header: { 
    +    id: 1, type_cd: 'BUY', source_name: 'Client', client_name: 'AAPL',
    +    metrics: { service_name: 'Trading', receive_time: '12:00' } 
    +  },
    +  payload: { 
    +    tran_id: 9, amount: '100.00',
    +    ref_data: { account_id: '5010', type_id: 'BUYL' } 
    +  }
    +}
    +
    +table.decide(input) #=> { value: %w[Client Trading 100.00 5010] }
    +
    +

    Testing

    csv_decision includes thorough License

    diff --git a/doc/method_list.html b/doc/method_list.html index 242199d..32c6800 100644 --- a/doc/method_list.html +++ b/doc/method_list.html @@ -78,16 +78,16 @@

    Method List

  • - build - CSVDecision::Dictionary + build + CSVDecision::Index
  • - build - CSVDecision::Index + build + CSVDecision::Dictionary
  • @@ -117,6 +117,14 @@

    Method List

  • +
    + #columns + CSVDecision::Columns::Dictionary +
    +
  • + + +
  • #columns CSVDecision::Table @@ -124,7 +132,7 @@

    Method List

  • -
  • +
  • #columns CSVDecision::Index @@ -132,15 +140,15 @@

    Method List

  • -
  • +
  • - #columns - CSVDecision::Columns::Dictionary + compare? + CSVDecision::Matchers
  • -
  • +
  • #constants CSVDecision::ScanRow @@ -148,7 +156,7 @@

    Method List

  • -
  • +
  • create CSVDecision::Dictionary::Entry @@ -156,6 +164,14 @@

    Method List

  • +
  • +
    + #data + CSVDecision::Scan::InputHashes +
    +
  • + +
  • #decide @@ -254,16 +270,16 @@

    Method List

  • - from_csv - CSVDecision::Options + #first_match + CSVDecision::Decision
  • - #function - CSVDecision::Dictionary::Entry + from_csv + CSVDecision::Options
  • @@ -277,6 +293,14 @@

    Method List

  • +
    + #function + CSVDecision::Dictionary::Entry +
    +
  • + + +
  • #hash CSVDecision::Index @@ -284,7 +308,7 @@

    Method List

  • -
  • +
  • #if_rows CSVDecision::Table @@ -292,7 +316,7 @@

    Method List

  • -
  • +
  • #ifs CSVDecision::Columns @@ -300,7 +324,7 @@

    Method List

  • -
  • +
  • #ifs CSVDecision::Columns::Dictionary @@ -308,7 +332,7 @@

    Method List

  • -
  • +
  • #index CSVDecision::Table @@ -316,9 +340,17 @@

    Method List

  • +
  • +
    + #index_scan_accumulate + CSVDecision::Decision +
    +
  • + +
  • - #index_scan + #index_scan_first_match CSVDecision::Decision
  • @@ -334,24 +366,24 @@

    Method List

  • - #initialize - CSVDecision::Columns + #initialize + CSVDecision::Table
  • - #initialize - CSVDecision::ScanRow + #initialize + CSVDecision::Columns
  • - #initialize - CSVDecision::Dictionary::Entry + #initialize + CSVDecision::Matchers::Function
  • @@ -366,8 +398,8 @@

    Method List

  • - #initialize - CSVDecision::Columns::Dictionary + #initialize + CSVDecision::Matchers::Proc
  • @@ -382,40 +414,40 @@

    Method List

  • - #initialize - CSVDecision::Matchers::Pattern + #initialize + CSVDecision::Result
  • - #initialize - CSVDecision::Result + #initialize + CSVDecision::Paths
  • - #initialize - CSVDecision::Matchers::Matcher + #initialize + CSVDecision::Matchers::Pattern
  • - #initialize - CSVDecision::Matchers::Proc + #initialize + CSVDecision::Matchers::Matcher
  • - #initialize - CSVDecision::Table + #initialize + CSVDecision::Dictionary::Entry
  • @@ -430,8 +462,40 @@

    Method List

  • - #initialize - CSVDecision::Matchers::Function + #initialize + CSVDecision::ScanRow +
    +
  • + + +
  • +
    + #initialize + CSVDecision::Columns::Dictionary +
    +
  • + + +
  • +
    + #initialize + CSVDecision::Scan::InputHashes +
    +
  • + + +
  • +
    + #input + CSVDecision::Decision +
    +
  • + + +
  • +
    + #input + CSVDecision::Result
  • @@ -462,32 +526,32 @@

    Method List

  • - #ins - CSVDecision::Matchers + #ins + CSVDecision::Columns
  • - #ins - CSVDecision::Columns + #ins + CSVDecision::Matchers
  • - #ins? - CSVDecision::Matchers::Matcher + #ins? + CSVDecision::Dictionary::Entry
  • - #ins? - CSVDecision::Dictionary::Entry + #ins? + CSVDecision::Matchers::Matcher
  • @@ -542,8 +606,8 @@

    Method List

  • - matches? - CSVDecision::Matchers::Guard + matches? + CSVDecision::Matchers::Range
  • @@ -558,23 +622,23 @@

    Method List

  • - matches? - CSVDecision::Matchers::Range + matches? + CSVDecision::Matchers::Guard
  • - #matches? - CSVDecision::Matchers::Range + matches? + CSVDecision::Matchers::Symbol
  • - matches? + #matches? CSVDecision::Matchers::Symbol
  • @@ -582,15 +646,15 @@

    Method List

  • - #matches? - CSVDecision::Matchers::Symbol + matches? + CSVDecision::Matchers::Numeric
  • - matches? + #matches? CSVDecision::Matchers::Numeric
  • @@ -598,16 +662,16 @@

    Method List

  • - #matches? - CSVDecision::Matchers::Numeric + matches? + CSVDecision::Matchers::Pattern
  • - matches? - CSVDecision::Matchers::Pattern + #matches? + CSVDecision::Matchers::Matcher
  • @@ -622,23 +686,23 @@

    Method List

  • - #matches? - CSVDecision::Matchers::Constant + #matches? + CSVDecision::Matchers::Range
  • - matches? - CSVDecision::Matchers::Function + #matches? + CSVDecision::Matchers::Constant
  • - #matches? + matches? CSVDecision::Matchers::Function
  • @@ -646,8 +710,8 @@

    Method List

  • - #matches? - CSVDecision::Matchers::Matcher + #matches? + CSVDecision::Matchers::Function
  • @@ -742,16 +806,16 @@

    Method List

  • - #outs? - CSVDecision::Matchers::Guard + #outs? + CSVDecision::Matchers::Constant
  • - #outs? - CSVDecision::Matchers::Constant + #outs? + CSVDecision::Matchers::Guard
  • @@ -774,16 +838,16 @@

    Method List

  • - #outs_functions - CSVDecision::Result + #outs_functions + CSVDecision::Table
  • - #outs_functions - CSVDecision::Table + #outs_functions + CSVDecision::Result
  • @@ -806,8 +870,8 @@

    Method List

  • - parse - CSVDecision::Header + parse + CSVDecision::Matchers
  • @@ -822,8 +886,8 @@

    Method List

  • - parse - CSVDecision::Matchers + parse + CSVDecision::Header
  • @@ -837,6 +901,14 @@

    Method List

  • +
    + parse_data + CSVDecision::Input +
    +
  • + + +
  • #parse_ins CSVDecision::Matchers @@ -844,7 +916,7 @@

    Method List

  • -
  • +
  • #parse_outs CSVDecision::Matchers @@ -852,7 +924,7 @@

    Method List

  • -
  • +
  • path CSVDecision::Load @@ -860,7 +932,39 @@

    Method List

  • +
  • +
    + #paths + CSVDecision::Columns +
    +
  • + +
  • +
    + #paths + CSVDecision::Columns::Dictionary +
    +
  • + + +
  • +
    + #paths + CSVDecision::Table +
    +
  • + + +
  • +
    + #paths + CSVDecision::Paths +
    +
  • + + +
  • #procs CSVDecision::ScanRow @@ -868,7 +972,7 @@

    Method List

  • -
  • +
  • regexp CSVDecision::Matchers @@ -876,7 +980,7 @@

    Method List

  • -
  • +
  • root CSVDecision @@ -884,7 +988,7 @@

    Method List

  • -
  • +
  • row? CSVDecision::Header @@ -892,7 +996,7 @@

    Method List

  • -
  • +
  • #rows CSVDecision::Table @@ -900,6 +1004,14 @@

    Method List

  • +
  • +
    + #scan + CSVDecision::Decision +
    +
  • + +
  • scan @@ -909,6 +1021,14 @@

    Method List

  • +
    + scan + CSVDecision::Paths +
    +
  • + + +
  • #scan_columns CSVDecision::ScanRow @@ -916,7 +1036,7 @@

    Method List

  • -
  • +
  • #scan_rows CSVDecision::Table @@ -924,7 +1044,7 @@

    Method List

  • -
  • +
  • #set_if CSVDecision::Dictionary::Entry @@ -932,7 +1052,7 @@

    Method List

  • -
  • +
  • strip_columns CSVDecision::Data @@ -940,7 +1060,7 @@

    Method List

  • -
  • +
  • strip_empty_columns CSVDecision::Header @@ -948,6 +1068,14 @@

    Method List

  • +
  • +
    + symbol + CSVDecision::Paths +
    +
  • + +
  • #symbols @@ -958,16 +1086,16 @@

    Method List

  • - table - CSVDecision::Parse + table + CSVDecision::Scan
  • - #table_scan - CSVDecision::Decision + table + CSVDecision::Parse
  • @@ -998,21 +1126,29 @@

    Method List

  • - #type - CSVDecision::Matchers::Proc + #type + CSVDecision::Dictionary::Entry
  • - #type - CSVDecision::Dictionary::Entry + #type + CSVDecision::Matchers::Proc
  • +
    + value + CSVDecision::Paths +
    +
  • + + +
  • value CSVDecision::Index diff --git a/doc/top-level-namespace.html b/doc/top-level-namespace.html index 3b24640..62f1795 100644 --- a/doc/top-level-namespace.html +++ b/doc/top-level-namespace.html @@ -100,7 +100,7 @@

    Defined Under Namespace