Sami Pussinen Sami Pussinen - 4 months ago 44
Javascript Question

Ramda.js refactoring

I decided to code a simple todo app using Ramda, but I have been stuck with one refactoring related issue. Here're two functions that I think could be refactored:

const isItemCompleted = R.pipe(

const isItemEdited = R.pipe(

As you can see, there is some code duplication and this would get even messier if I had more states. I have been trying to isolate the duplicated functionality as such:

const statesContains = R.flip(R.pipe(

//I would like to use it like this:
const isItemCompleted = statesContains("completed")
const isItemEdited = statesContains("editing")

But I just cannot wrap my head around this. I can make it work with different argument ordering, but I would like to follow the data-last rule to create concise functions.

The data being passed to these isItemCompleted and isItemEdited functions could be something like this:

let item = {states:["editing", "complete"]};
isItemCompleted(item); //true

Any (functional) ideas?


There are several ways to go with this.

Perhaps the most straightforward is

const statesContains = R.curry(
  (state, item) => R.contains(state, R.prop('states', item))

const isItemCompleted = statesContains("completed");

But it's reasonable to want to abstract this a bit, to allow the property to be searched to vary as well. So you could write:

const propContains = R.curry(
  (propName, state, item) => R.contains(state, R.prop(propName, item))

const editorsContains = propContains('editors')
const edFred = editorsContains('fred');

// or edFred = propContains('editors', 'fred');

Both of these are reasonable. But Ramda has a function which reads really well, and will serve these needs pretty well, where. With this, you can simply write:

const isItemCompleted = R.where({states: R.contains('completed')});

This, I believe, is the simplest approach if you're looking for one-offs. But both of the above could help you create reusable functions.

You can see all this in action in the Ramda REPL