diff --git a/lib/kiba/extend/transforms/prepend.rb b/lib/kiba/extend/transforms/prepend.rb index bfe0554ea..f90374ab5 100644 --- a/lib/kiba/extend/transforms/prepend.rb +++ b/lib/kiba/extend/transforms/prepend.rb @@ -3,16 +3,129 @@ module Extend module Transforms module Prepend ::Prepend = Kiba::Extend::Transforms::Prepend + + # Adds the value of prepended_field to the beginning of the value(s) of the target_field + # + # If target field value is blank, it is left blank, even if there is a prepended field value. If there is no value in prepended field, target field is left as-is + # + # == Examples + # Input table: + # + # | a | b | + # ----------- + # | c | d | + # | e;f | g | + # | | h | + # | i | | + # + # Used in pipeline as: + # transform Prepend::FieldToFieldValue, target_field: :a, prepended_field: :b, sep: ': ' + # + # Results in: + # + # | a | b | + # -------------- + # | d: c | d | + # | d: e;f | g | + # | | h | + # | i | | + # + # Used in pipeline as: + # transform Prepend::FieldToFieldValue, target_field: :a, prepended_field: :b, sep: ': ', + # delete_prepended: true, mvdelim: ';' + # + # Results in: + # + # | a | + # ------------- + # | d: c | + # | d: e;d: f | + # | | + # | i | + class FieldToFieldValue + # @param target_field [Symbol] Name of field to prepend to + # @param prepended_field [Symbol] Name of field whose value should be prepended + # @param sep [String] Text inserted between prepended field value and target field value + # @param delete_prepended [Boolean] Whether or not to delete the prepended_field column after prepending + # @param mvdelim [String] Character(s) on which to split multiple values in target field before prepending. If empty string, behaves as a single value field + def initialize(target_field:, prepended_field:, sep: '', delete_prepended: false, mvdelim: '') + @field = target_field + @prepend = prepended_field + @sep = sep + @delete = delete_prepended + @mvdelim = mvdelim + end + + # @private + def process(row) + fv = row.fetch(@field, nil) + prepend_val = row.fetch(@prepend, nil) + row.delete(@prepend) if @delete + return row if fv.blank? + return row if prepend_val.blank? + + values = @mvdelim.blank? ? [fv] : fv.split(@mvdelim) + row[@field] = values.map{ |val| "#{prepend_val}#{@sep}#{val}"} + .join(@mvdelim) + row.delete(@prepend) if @delete + row + end + end + + # Adds the specified value to the specified field + # + # If target field value is blank, it is left blank + # + # == Examples + # Input table: + # + # | a | b | + # ----------- + # | c | d | + # | e;f | g | + # | | h | + # | i | | + # + # Used in pipeline as: + # transform Prepend::ToFieldValue, field: :a, value: 'pre: ' + # + # Results in: + # + # | a | b | + # -------------- + # | pre: c | d | + # | pre: e;f | g | + # | | h | + # | pre: i | | + # + # Used in pipeline as: + # transform Prepend::ToFieldValue, field: :a, value: 'pre: ', mvdelim: ';' + # + # Results in: + # + # | a | b | + # --------------------- + # | pre: c | d | + # | pre: e;pre: f | g | + # | | h | + # | pre: i | | class ToFieldValue - def initialize(field:, value:) + # @param field [Symbol] The field to prepend to + # @param value [String] The value to be prepended + # @param mvdelim [String] Character(s) on which to split multiple values in field before prepending. If empty string, behaves as a single value field + def initialize(field:, value:, mvdelim: '') @field = field @value = value + @mvdelim = mvdelim end + # @private def process(row) fv = row.fetch(@field, nil) return row if fv.blank? - row[@field] = "#{@value}#{fv}" + + fieldvals = @mvdelim.blank? ? [fv] : fv.split(@mvdelim) + row[@field] = fieldvals.map{ |fv| "#{@value}#{fv}" }.join(@mvdelim) row end end diff --git a/lib/kiba/extend/version.rb b/lib/kiba/extend/version.rb index 782b32a59..78de251fb 100644 --- a/lib/kiba/extend/version.rb +++ b/lib/kiba/extend/version.rb @@ -1,5 +1,5 @@ module Kiba module Extend - VERSION = "1.13.0" + VERSION = "1.14.0" end end diff --git a/spec/kiba/extend/transforms/prepend_spec.rb b/spec/kiba/extend/transforms/prepend_spec.rb index 9bd01b828..d0431288f 100644 --- a/spec/kiba/extend/transforms/prepend_spec.rb +++ b/spec/kiba/extend/transforms/prepend_spec.rb @@ -1,6 +1,77 @@ require 'spec_helper' RSpec.describe Kiba::Extend::Transforms::Prepend do + describe 'FieldToFieldValue' do + test_csv = 'tmp/test.csv' + rows = [ + ['name', 'prependval'], + ['Weddy', 'm'], + [nil, 'u'], + ['', 'u'], + ['Kernel', nil], + ['Divebomber|Hunter', 'm'] + ] + + context 'when delete_prepended = false' do + before do + generate_csv(test_csv, rows) + @result = execute_job(filename: test_csv, + xform: Prepend::FieldToFieldValue, + xformopt: {target_field: :name, prepended_field: :prependval, sep: ': ', + mvdelim: '|'}) + end + it 'prepends value of given field to existing field values' do + expected = {name: 'm: Weddy', prependval: 'm'} + expect(@result[0]).to eq(expected) + end + it 'leaves nil values alone' do + expected = {name: nil, prependval: 'u'} + expect(@result[1]).to eq(expected) + end + it 'leaves blank values alone' do + expected = {name: '', prependval: 'u'} + expect(@result[2]).to eq(expected) + end + it 'does not prepend blank field' do + expected = {name: 'Kernel', prependval: nil} + expect(@result[3]).to eq(expected) + end + it 'prepends to each multivalue in target field' do + expected = {name: 'm: Divebomber|m: Hunter', prependval: 'm'} + expect(@result[4]).to eq(expected) + end + end + context 'when delete_prepended = true' do + before do + generate_csv(test_csv, rows) + @result = execute_job(filename: test_csv, + xform: Prepend::FieldToFieldValue, + xformopt: {target_field: :name, prepended_field: :prependval, sep: ': ', delete_prepended: true, + mvdelim: '|'}) + end + it 'prepends value of given field to existing field values' do + expected = {name: 'm: Weddy'} + expect(@result[0]).to eq(expected) + end + it 'leaves nil values alone' do + expected = {name: nil} + expect(@result[1]).to eq(expected) + end + it 'leaves blank values alone' do + expected = {name: ''} + expect(@result[2]).to eq(expected) + end + it 'does not prepend blank field' do + expected = {name: 'Kernel'} + expect(@result[3]).to eq(expected) + end + it 'prepends to each multivalue in target field' do + expected = {name: 'm: Divebomber|m: Hunter'} + expect(@result[4]).to eq(expected) + end + end + end + describe 'ToFieldValue' do test_csv = 'tmp/test.csv' rows = [ @@ -13,8 +84,8 @@ before do generate_csv(test_csv, rows) @result = execute_job(filename: test_csv, - xform: Prepend::ToFieldValue, - xformopt: {field: :name, value: 'name: '}) + xform: Prepend::ToFieldValue, + xformopt: {field: :name, value: 'name: '}) end it 'prepends given value to existing field values' do expected = {id: '1', name: 'name: Weddy'}