lib/csv_decision/dictionary.rb in csv_decision-0.0.9 vs lib/csv_decision/dictionary.rb in csv_decision-0.1.0

- old
+ new

@@ -24,13 +24,11 @@ def ins? %i[in guard].member?(type) ? true : false end end - # TODO: implement all anonymous column types - # COLUMN_TYPE_ANONYMOUS = Set.new(%i[path if guard]).freeze - # These column types do not need a name + # These column types do not need a name. COLUMN_TYPE_ANONYMOUS = Set.new(%i[guard if]).freeze private_constant :COLUMN_TYPE_ANONYMOUS # Classify and build a dictionary of all input and output columns by # parsing the header row. @@ -40,31 +38,25 @@ def self.build(header:, dictionary:) header.each_with_index do |cell, index| dictionary = parse_cell(cell: cell, index: index, dictionary: dictionary) end - validate(dictionary) - end - - def self.validate(dictionary) - dictionary.outs.each_pair do |col, column| - validate_out(dictionary: dictionary, column_name: column.name, col: col) - end - dictionary end - private_class_method :validate - def self.validate_out(dictionary:, column_name:, col:) - if dictionary.ins.any? { |_, column| column_name == column.name } - raise CellValidationError, "output column name '#{column_name}' is also an input column" - end + # Add a new symbol to the dictionary of named input and output columns. + # + # @param columns [{Symbol=>Symbol}] Hash of column names with key values :in or :out. + # @param name [Symbol] Symbolized column name. + # @param out [false, Index] False if an input column, otherwise the index of the output column. + # @return [{Symbol=>Symbol}] Column dictionary updated with the new name. + def self.add_name(columns:, name:, out: false) + validate_name(columns: columns, name: name, out: out) - return unless dictionary.outs.any? { |key, column| column_name == column.name && col != key } - raise CellValidationError, "output column name '#{column_name}' is duplicated" + columns[name] = out ? out : :in + columns end - private_class_method :validate_out def self.validate_column(cell:, index:) match = Header::COLUMN_TYPE.match(cell) raise CellValidationError, 'column name is not well formed' unless match @@ -122,23 +114,56 @@ # Columns::Default.new(entry.name, nil, default_if(type)) # # # Treat set: as an in: column # dictionary.ins[index] = entry - when :in, :guard + when :in + add_name(columns: dictionary.columns, name: entry.name) dictionary.ins[index] = entry + # A guard column is still added to the ins hash for parsing as an input column. + when :guard + dictionary.ins[index] = entry + when :out + add_name(columns: dictionary.columns, name: entry.name, out: index) dictionary.outs[index] = entry + # Add an if: column to both the +outs+ hash for output column parsing, and also + # a specialized +ifs+ hash used for evaluating them for row filtering. when :if dictionary.outs[index] = entry dictionary.ifs[index] = entry end dictionary end private_class_method :dictionary_entry + + def self.validate_name(columns:, name:, out:) + return unless (in_out = columns[name]) + + return validate_out_name(in_out: in_out, name: name) if out + validate_in_name(in_out: in_out, name: name) + end + private_class_method :validate_name + + def self.validate_out_name(in_out:, name:) + if in_out == :in + raise CellValidationError, "output column name '#{name}' is also an input column" + end + + raise CellValidationError, "output column name '#{name}' is duplicated" + end + private_class_method :validate_out_name + + def self.validate_in_name(in_out:, name:) + # in: columns may be duped + return if in_out == :in + + raise CellValidationError, "output column name '#{name}' is also an input column" + end + private_class_method :validate_in_name # def self.default_if(type) # return nil if type == :set # return :nil? if type == :'set/nil' # :blank? \ No newline at end of file