Example #1
func TestTabSync(t *testing.T) {
	actual := &bytes.Buffer{}
	writer := csvEncoding.NewWriter(actual)
	writer.Comma = '\t'
	assert.Nil(t, NewWithCsvWriter(writer)(csv.New(bytes.NewBufferString(csvData))))
	assert.Equal(t, actual.String(), tabData)
Example #2
Example_transformCSVdata will
1) read in data from CSV
2) filter and transform that data in a simple way
3) write the data to JSON
4) output the number of rows we read in and the number of rows after filtering

It's possible make an even simpler example, but this is a little more interesting.
func Example_transformCSVData() {
	var data = `url,ssl,count
	// create the "source" we pull from
	// note that this automatically handles the conversion from a CSV row to an optimus "row"
	cSource := csvSource.New(bytes.NewBufferString(data)) // gopkg.in/Clever/optimus.v3/sources/csv

	// create the "sink" we push to
	// note that this automatically handles marshalling to JSON
	var output bytes.Buffer
	jSink := jsonSink.New(&output) // gopkg.in/Clever/optimus.v3/sinks/json

	// let's set up some counting variables for fun
	beforeCounter := 0
	afterCounter := 0

	// selectOnlyCleverSSL will only output entries where ssl is true
	// and the host is either clever.com or a subdomain
	// if SSL or URL are missing, don't bother erroring and instead drop the row
	selectOnlyCleverSSL := func(row optimus.Row) (bool, error) {
		rawURL, ok := row["url"]
		if !ok {
			return false, nil
		parsedURL, err := url.Parse(rawURL.(string))
		if err != nil || !regexp.MustCompile(`(\w*\.)?clever.com`).MatchString(parsedURL.Host) {
			return false, nil

		// yes, yes, you could parse it from the protocol, but this is an example!
		ssl, err := strconv.ParseBool(row["ssl"].(string))
		if err != nil || ssl == false {
			return false, nil

		return true, nil

	// addProtocol prepends the URL with "https://" if SSL=true, else "http://" if false
	// also removes the SSL item from the row
	addProtocol := func(row optimus.Row) (optimus.Row, error) {
		url, ok := row["url"]
		if !ok {
			return nil, fmt.Errorf("Error getting URL from row, row: %s", row)
		ssl, err := strconv.ParseBool(row["ssl"].(string))
		if err != nil {
			return nil, fmt.Errorf("Issue parsing ssl for row with URL: %s", url)

		protocol := "http"
		if ssl {
			protocol = "https"

		// note that rows are maps, and are therefore mutable
		// strictly speaking, you would not have to return the row
		// and this can bite you if you're not careful with Each or other
		// transforms that don't suggest the table is modified
		row["url"] = fmt.Sprintf("%s://%s", protocol, url)
		delete(row, "ssl")
		return row, nil

	// set up and start the transform
	err := New(cSource).
		// start by counting how many we read
		Each(func(r optimus.Row) error {
			return nil
		// as a simple case, let's only match "clever.com" hosts with SSL true
		// then let's just append "https" onto those urls
		// finish by counting how many we end up writing
		Each(func(r optimus.Row) error {
			return nil
		// set up the sink

	if err != nil {
	} else {
		fmt.Printf("Done processing, ingested %d items, wrote %d items out.", beforeCounter, afterCounter)

	// Output:
	// {"count":"5","url":"https://https://clever.com/foo"}
	// {"count":"2","url":"https://https://api.clever.com/bar"}
	// Done processing, ingested 5 items, wrote 2 items out.
Example #3
func TestNilValues(t *testing.T) {
	rows := []optimus.Row{{"field1": "val1", "field2": nil}}
	actual := &bytes.Buffer{}
	assert.Nil(t, New(actual)(slice.New(rows)))
	assert.Equal(t, tests.GetRows(csv.New(actual)), rows)
Example #4
func TestCSVSink(t *testing.T) {
	actual := &bytes.Buffer{}
	assert.Nil(t, New(actual)(csv.New(bytes.NewBufferString(csvData))))
	assert.Equal(t, actual.String(), csvData)