gosseti gosseti - 8 days ago 5
Javascript Question

Call nested methods on object only if it exists using Ramda

I currently have a

user
object, which has a
currentRoom()
method on it, which might sometimes not exist or return
null
.

If the
currentRoom()
method returns something, I then need to call a
messages()
method on that. If nothing is returned from either, I’d like to return a default empty array
[]
.

I’d like to tackle this functionally using Ramda, so it’s neat and reusable. Currently, my (non Ramda) code looks like this:

const user = Users.findOne({ username: params.id })
const room = (user.currentRoom && user.currentRoom() || {})
const messages = (room.messages && room.messages() || [])


Some kind of logic I was thinking was to pass in the list of required methods, along with the default result if nothing comes out of it.

/* getMessages(defaultIfNull, methodsArray, object) */

getMessages([], ['currentRoom', 'messages'], user)


Basically something a bit similar to
pathOr
, but for methods on objects.

Answer

I guess I'd use the List monad like an Option:

const getRoom = user => "currentRoom" in user ? [user.currentRoom()] : [];
const getMessages = room => "messages" in room ? room.messages() : [];

const allTogether = R.compose(R.chain(getMessage), R.chain(getRoom), R.of);
console.log(allTogether(Users.findOne({ username: params.id })));