Log Values Inside Ramda.js Pipelines to the Console

It can be difficult to debug by examining intermediate values inside Ramda pipelines with console.log.

The Ramda function tap comes in handy here and is like a wiretap: we can use it to tap into a functional pipeline to insert some behaviour in between steps, while letting the pipeline continue to work as usual. We can insert R.tap in between functions inside pipelines built with R.compose or R.pipe.

In diagram form:

A -> B -> C
A -> B -> R.tap(fn) -> C

(pipeline proceeds as usual, passing output from B to the input of C)

The following simple example reverses a list and then takes the average (mean).

const R = require('ramda')
 
const f = R.compose(
  R.mean, // Take average.
  R.reverse // Reverse elements.
)

const result = f([1, 2, 3])

console.log(result)

This prints:

2

Suppose we want to debug this function composition and print out the intermediate reversed list.

We can insert the “wiretap” with R.tap with a function to log the input to see the intermediate value flowing through:

const R = require('ramda')
 
const f = R.compose(
  R.mean, // Take average.
  R.tap(x => console.log(x)), // Print and continue.
  R.reverse // Reverse elements.
)

const result = f([1, 2, 3])

console.log(result)

Result:

[ 3, 2, 1 ]
2

This technique can be very handy to debug more complex code using pipe and compose by inserting R.tap.

References

https://ramdajs.com/docs/#tap

 

Require an Object to Contain at Least One Key in a Joi Schema

When validating JSON objects with Joi in JavaScript we sometimes need an object to have any one of a set of possible keys, i.e. one or more of the specific keys given.

The schema below achieves this with the or() function.

const customerSchema = Joi.object().keys({
  id: Joi.string().optional(),
  accountNumber: Joi.number().optional(),
  emailAddress: Joi.string().optional()
})
.or('id', 'accountNumber', 'emailAddress') // At least one of these keys must be in the object to be valid.
.required()

If we supply a JSON object like below to the Joi schema validate function, we will see a Joi schema validation error similar to the example.

{
  "name": "test"
}

Joi validation error:

"message": "object must contain at least one of [id, accountNumber, emailAddress]"

However, any of the following are valid examples:

{
  "id": "1234"
}
{
  "id": "1234",
  "emailAddress": "test@test.com"
}

Note that we can also use the related functions and(), xor(), nand(), and others to achieve other logical requirements on object keys.

 

Spread Operator Applied to Strings in JavaScript

The spread operator () can be used to get an array of characters easily from a string in ES6 and higher JavaScript.

The following code shows how this works:

const str = "hello"

const chars = [...str]

console.log(chars)

The result is:

[ 'h', 'e', 'l', 'l', 'o' ]

 

Interestingly, we can also use the spread the inside an object instead of an array, in which case the operator will assign the characters of the string at each index from 0 to the length of the string minus one, using the indexes as keys in the object. The example below shows this.

const str = "hello"

const arr = { ...str }

console.log(arr)

Result:

{ 
  '0': 'h', 
  '1': 'e', 
  '2': 'l', 
  '3': 'l', 
  '4': 'o' 
}