I'd like a hook to specify default values more dynamically. The use case is that I created a glue layer between Magritte and NeoCSV so one can meta-describe how to extract CSV fields into objects. For example: ``` descriptionDate <magritteDescription> ^ MADateDescription new accessor: #date; priority: 400; propertyAt: #csvFieldName put: 'Date'; propertyAt: #csvReader put: [ :s | (s, '/2017') asDate ]; default: Date today; yourself ``` The problem is that there doesn't seem to be a way to plug #default: above into NeoCSV because other hooks like #addField:converter: seem to be skipped for nil values, shortcutting to a statically described per-csv-file emptyFieldValue. ----- Cheers, Sean -- Sent from: http://forum.world.st/Pharo-Smalltalk-Developers-f1294837.html
Sean,
On 13 Feb 2018, at 14:39, Sean P. DeNigris <sean@clipperadams.com> wrote:
I'd like a hook to specify default values more dynamically. The use case is that I created a glue layer between Magritte and NeoCSV so one can meta-describe how to extract CSV fields into objects.
For example: ``` descriptionDate <magritteDescription>
^ MADateDescription new accessor: #date; priority: 400; propertyAt: #csvFieldName put: 'Date'; propertyAt: #csvReader put: [ :s | (s, '/2017') asDate ]; default: Date today; yourself ```
The problem is that there doesn't seem to be a way to plug #default: above into NeoCSV because other hooks like #addField:converter: seem to be skipped for nil values, shortcutting to a statically described per-csv-file emptyFieldValue.
The initial idea of the empty value (defaulting to nil) and the short circuiting of further conversion, is precisely to help in the writing of the converter blocks, so that [ :s | s asDate ] will never receive nil or an empty string and consequently does not have to test on it. I suppose I could imagine an option like #passEmptyFieldsToConverters, which would allow (and force you) to write converter blocks like [ :s | s isEmptyOrNil ifTrue: [ Date doomsDay ] ifFalse: [ s asDate ] ] so that you can specify your own custom empty value per field. What do you think ? Sven
Sven Van Caekenberghe-2 wrote
What do you think ?
Could #emptyFieldValue: accept a block instead of the actual value? Or be per-field? Or both? Then the default could still be set via the current mechanism, keeping the usual API simple, but the user would have a bit more control. ----- Cheers, Sean -- Sent from: http://forum.world.st/Pharo-Smalltalk-Developers-f1294837.html
Sean,
On 19 Feb 2018, at 02:33, Sean P. DeNigris <sean@clipperadams.com> wrote:
Sven Van Caekenberghe-2 wrote
What do you think ?
Could #emptyFieldValue: accept a block instead of the actual value? Or be per-field? Or both? Then the default could still be set via the current mechanism, keeping the usual API simple, but the user would have a bit more control.
Have a look at the following: === Name: Neo-CSV-Core-SvenVanCaekenberghe.27 Author: SvenVanCaekenberghe Time: 19 February 2018, 10:28:24.688684 pm UUID: a08d6c1c-f921-0d00-aaa4-29b9044088b7 Ancestors: Neo-CSV-Core-SvenVanCaekenberghe.26 Add special option #passNil for NeoCSVReader>>#emptyFieldValue: so that converter blocks do get nil passed in for empty/missing fields and can act accordingly Add NeoCSVReaderTests>>#testEmptyFieldValuePassNil === Name: Neo-CSV-Tests-SvenVanCaekenberghe.24 Author: SvenVanCaekenberghe Time: 19 February 2018, 10:28:03.52381 pm UUID: 1598291b-f921-0d00-aaa3-c7c0044088b7 Ancestors: Neo-CSV-Tests-SvenVanCaekenberghe.23 Add special option #passNil for NeoCSVReader>>#emptyFieldValue: so that converter blocks do get nil passed in for empty/missing fields and can act accordingly Add NeoCSVReaderTests>>#testEmptyFieldValuePassNil === Now you can do as follows: | date1 date2 | date1 := '1900-01-01' asDate. date2 := '2000-12-31' asDate. self assert: ((NeoCSVReader on: 'date1,date2\2018-01-01,2018-02-01\2018-01-01,\,2018-02-01\\' withCRs readStream) emptyFieldValue: #passNil; addFieldConverter: [ :input | input ifNil: [ date1 ] ifNotNil: [ input asDate ] ]; addFieldConverter: [ :input | input ifNil: [ date2 ] ifNotNil: [ input asDate ] ]; skipHeader; upToEnd) equals: (Array with: (Array with: '2018-01-01' asDate with: '2018-02-01' asDate) with: (Array with: '2018-01-01' asDate with: date2) with: (Array with: date1 with: '2018-02-01' asDate) with: (Array with: date1 with: date2)). Note how the first field's default empty value is now date1 and second field's is date2. Sven
participants (2)
-
Sean P. DeNigris -
Sven Van Caekenberghe