Class: Kiba::Extend::Transforms::Collapse::FieldsToRepeatableFieldGroup
- Inherits:
-
Object
- Object
- Kiba::Extend::Transforms::Collapse::FieldsToRepeatableFieldGroup
- Defined in:
- lib/kiba/extend/transforms/collapse/fields_to_repeatable_field_group.rb
Overview
Combines data from multiple fields following an expected naming pattern (shown in examples below) into final fields that are part of a repeatable fieldgroup.
This transform can be seen as a more opinionated, structured shorthand for FieldsWithCustomFieldmap, which does not make the same assumptions about the field names/patterns involved, nor about field groups and field group evenness.
Goes through the following steps:
- Runs Replace::EmptyFieldValues to replace source fields values
that are nil or empty (the full field value) with value of given for
null_placeholder
. This avoids odd situations where dropping fields because they are empty at this point introduces unevenness. - If
enforce_evenness: true
, ensure all fields from a given source have the same number of values by running Kiba::Extend::Transforms::Clean::EvenFieldValues withevener: even_val
,treat_as_null: null_placeholder
, andwarn: warn_if_uneven
- Uses Helpers::FieldValueGetter with
discard: []
(i.e. keep all values) to gather and combine values from source fields for a given target into the target value - Deletes source fields
- Runs Replace::EmptyFieldValues on target fields, with
delim: delim
(turns on replacement of individual empty values in a multi-value string) andvalue: null_placeholder
- If
empty_groups: delete
, runs Delete::EmptyFieldGroups on target fields withtreat_as_null: [null_placeholder, even_val].uniq
- Runs Delete::DelimiterOnlyFieldValues on target fields with
treat_as_null: null_placeholder
General example
As an example, let’s use example original source data:
{
displayideas: 'blah',
ideadate: '2022-07-07',
creditline: 'from someone'
}
We want data from :displayideas and :creditline to both get mapped to annotation note fields, and we want the annotation type and annotation date fields set as appropriate.
In order to apply this transform, we must first get the source data into the expected format (This must be achieved via other transforms before applying this one):
{
idea_annotationtype: 'display idea',
idea_annotationdate: '2022-07-07',
idea_annotationnote: 'blah',
cl_annotationtype: 'credit line',
cl_annotationnote: 'from someone'
}
Requirements of this pattern:
- consistent prefix indicating orig source data
- suffix is the eventual target field that the values will be combined into
- prefix and suffix separated by underscore
Then we can use this transform as follows:
transform Collapse::FieldsToRepeatableFieldGroup,
sources: %i[cl idea],
targets: %i[annotationtype annotationnote annotationdate],
delim: '|'
And the result will be:
{
annotationtype: 'credit line|display idea',
annotationnote: 'from someone|blah',
annotationdate: '%NULLVALUE%'|2022-07-07'
}
Specific examples/parameter effects
Blank/null values (:null_placeholder
parameter)
Prior to any other processing, empty or nil whole-field values are converted to a string representing a null value. After target fields are compiled, any individual null/empty values within a joined String is also converted to this null-value representing string. This behavior cannot be disabled.
The null placeholder string used by default is the value of
Kiba::Extend.nullvalue
(default = ‘%NULLVALUE%’)
You can change this as follows:
Source data:
[
{
a_foo: 'a|f', a_bar: 'a',
b_foo: 'bf', b_bar: 'b',
c_foo: '', c_bar: 'c',
d_foo: 'd|', d_bar: nil
}
]
Use this transform as follows:
transform Collapse::FieldsToRepeatableFieldGroup,
sources: %i[a b c d],
targets: %i[foo bar],
delim: '|',
null_placeholder: 'BLANK'
And the result will be:
[
{
foo: 'a|f|bf|BLANK|d',
bar: 'a|%NULLVALUE%|b|c|BLANK'
}
]
Note that there are still some ‘%NULLVALUE%’s in there. This is
because we did not change the even_val
parameter from its default
value. The ‘%NULLVALUE%’s were added to achieve even field values.
Automatic removal of grouped field with no values in group
By default, empty_groups: :delete
. This causes the
Kiba::Extend::Transforms::Clean::EmptyFieldGroups transform (with use_nullvalue: true
) to
be applied after the target fields are compiled, so that, with the
following source data:
[
{a_foo: 'afoo', a_bar: 'abar', b_foo: 'bfoo', b_bar: 'bbar'},
{a_foo: 'afoo', a_bar: 'abar', b_foo: nil, b_bar: ''},
{a_foo: 'afoo', a_bar: 'abar', b_foo: nil, b_bar: '%NULLVALUE%'},
{a_foo: 'afoo', a_bar: '%NULLVALUE%', b_foo: '%NULLVALUE%',
b_bar: 'bbar'},
{a_foo: nil, a_bar: nil, b_foo: nil, b_bar: ''},
{a_foo: 'afoo', a_bar: 'abar', b_foo: 'bfoo'},
]
And this usage:
transform Collapse::FieldsToRepeatableFieldGroup,
sources: %i[a b],
targets: %i[foo bar],
delim: '|'
The result will be:
[
{foo: 'afoo|bfoo', bar: 'abar|bbar'},
{foo: 'afoo', bar: 'abar'},
{foo: 'afoo', bar: 'abar'},
{foo: 'afoo|%NULLVALUE%', bar: '%NULLVALUE%|bbar'},
{foo: nil, bar: nil},
{foo: 'afoo|bfoo', bar: 'abar|%NULLVALUE%'}
]
If you do not want empty field groups removed, do:
transform Cspace::FieldsToRepeatableFieldGroup,
sources: %i[a b],
targets: %i[foo bar],
delim: '|',
empty_groups: :retain
The result will be:
[
{foo: 'afoo|bfoo', bar: 'abar|bbar'},
{foo: 'afoo|%NULLVALUE%', bar: 'abar|%NULLVALUE%'},
{foo: 'afoo|%NULLVALUE%', bar: 'abar|%NULLVALUE%'},
{foo: 'afoo|%NULLVALUE%', bar: '%NULLVALUE%|bbar'},
{foo: nil, bar: nil},
{foo: 'afoo|bfoo', bar: 'abar|%NULLVALUE%'}
]
Enforcing evenness
See Warn::UnevenFields for explanation of what is meant by evenness.
See Kiba::Extend::Transforms::Clean::EvenFieldValues for details on how fields are evened if
enforce_evenness: true
.
With source data:
[
{
a_foo: 'a|f', a_bar: 'a',
b_foo: 'bf', b_bar: 'b',
c_foo: '', c_bar: 'c',
d_foo: 'd|', d_bar: nil
}
]
And tranform:
transform Cspace::FieldsToRepeatableFieldGroup,
sources: %i[a b],
targets: %i[foo bar],
delim: '|',
enforce_evenness: false
The result will be:
[
{
foo: 'a|f|bf|%NULLVALUE%|d|%NULLVALUE%',
bar: 'a|b|c|%NULLVALUE%'
}
]
Note that we did not pass in empty_groups: retain
, but we get an
empty group (the 4th value in foo
and the 4th/final value in
bar
)
This is because Kiba::Extend::Transforms::Clean::EmptyFieldGroups avoids making any changes when it detects uneven fields, because how the values should actually line up (and thus what is actually empty) is ambiguous.
Instance Method Summary collapse
-
#initialize(sources:, targets:, delim: Kiba::Extend.delim, null_placeholder: Kiba::Extend.nullvalue, even_val: Kiba::Extend.nullvalue, empty_groups: :delete, enforce_evenness: true, warn_if_uneven: true) ⇒ FieldsToRepeatableFieldGroup
constructor
A new instance of FieldsToRepeatableFieldGroup.
-
#process(row) ⇒ Object
Constructor Details
#initialize(sources:, targets:, delim: Kiba::Extend.delim, null_placeholder: Kiba::Extend.nullvalue, even_val: Kiba::Extend.nullvalue, empty_groups: :delete, enforce_evenness: true, warn_if_uneven: true) ⇒ FieldsToRepeatableFieldGroup
Returns a new instance of FieldsToRepeatableFieldGroup.
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 |
# File 'lib/kiba/extend/transforms/collapse/fields_to_repeatable_field_group.rb', line 278 def initialize( sources:, targets:, delim: Kiba::Extend.delim, null_placeholder: Kiba::Extend.nullvalue, even_val: Kiba::Extend.nullvalue, empty_groups: :delete, enforce_evenness: true, warn_if_uneven: true ) @sources = sources @targets = targets @delim = delim @null_placeholder = null_placeholder @even_val = even_val @empty_groups = empty_groups @enforce_evenness = enforce_evenness @warn_if_uneven = warn_if_uneven @srcfieldgroups = sources.map do |source| targets.map do |target| field_name(source, target) end end @srcemptyreplacers = srcfieldgroups.map do |grp| Kiba::Extend::Transforms::Replace::EmptyFieldValues.new( fields: grp, value: null_placeholder ) end @srceveners = srcfieldgroups.map do |grp| Kiba::Extend::Transforms::Clean::EvenFieldValues.new( fields: grp, evener: even_val, delim: delim, warn: warn_if_uneven, treat_as_null: null_placeholder ) end @to_combine = targets.map do |target| [target, Kiba::Extend::Transforms::Helpers::FieldValueGetter.new( fields: sources.map { |src| field_name(src, target) }, delim: delim, discard: [] )] end.to_h @field_group_cleaner = Delete::EmptyFieldGroups.new( groups: [targets], delim: delim, treat_as_null: empty_field_group_treat_as_null ) @delim_only_cleaner = Delete::DelimiterOnlyFieldValues.new( fields: targets, delim: delim, treat_as_null: null_placeholder ) @empty_replacer = Replace::EmptyFieldValues.new( fields: targets, delim: delim, value: null_placeholder ) end |
Instance Method Details
#process(row) ⇒ Object
340 341 342 343 344 345 346 347 348 349 350 351 352 353 |
# File 'lib/kiba/extend/transforms/collapse/fields_to_repeatable_field_group.rb', line 340 def process(row) srcemptyreplacers.each { |replacer| replacer.process(row) } if enforce_evenness srceveners.each { |e| e.process(row) } end to_combine.each do |target, getter| row[target] = getter.call(row).values.join(delim) end delete_sources(row) empty_replacer.process(row) field_group_cleaner.process(row) if empty_groups == :delete delim_only_cleaner.process(row) row end |