Question

In Ruby, you can use Array#join to simple join together multiple strings with an optional delimiter.

[ "a", "b", "c" ].join        #=> "abc"
[ "a", "b", "c" ].join("-")   #=> "a-b-c"

I'm wondering if there is nice syntactic sugar to do something similar with a bunch of boolean expressions. For example, I need to && a bunch of expressions together. However, which expressions will be used is determined by user input. So instead of doing a bunch of

cumulative_value &&= expression[:a] if user[:input][:a]

I want to collect all the expressions first based on the input, then && them all together in one fell swoop. Something like:

be1 = x > y
be2 = Proc.new {|string, regex| string =~ regex}
be3 = z < 5 && my_object.is_valid?
[be1,be2.call("abc",/*bc/),be3].eval_join(&&)

Is there any such device in Ruby by default? I just want some syntatic sugar to make the code cleaner if possible.

Was it helpful?

Solution

Try Array#all?. If arr is an Array of booleans, this works by itself:

arr.all?

will return true if every element in arr is true, or false otherwise.

You can use Array#any? in the same manner for joining the array on ||, that is, it returns true if any element in the array is true and false otherwise.

This will also work if arr is an array of Procs, as long as you make sure to pass the correct variables to Proc#call in the block (or use class, instance, or global variables).

OTHER TIPS

You can use #all?, #any? and #none? to achieve this:

[true, false].any?
=> true

[true, false].all?
=> false

And don't forget, that all values other than nul and false evaluate to true.

['', [], {}].all?
=> true

In this particular case, you just want to filter your expressions hash by those which the user has selected, and then test if all those expressions are truthy:

cumulative_value = expression.select {|k, v| user[:input][k] }.values.all?

This will first select all members from expression for which there is a matching user[:input] key, then it will use Array#all? to test if all the values from the selected expressions are truthy. Your cumulative_value is then either true or false.

Since your expression values may be procs, you would then have to evaluate all procs from the filtered expression list, and build a results array from that, which you can call all? on:

cumulative_value = expression.select {|k, v| user[:input][k] }.
  values.map {|value| value.is_a?(Proc) ? value.call : value }.all?

Hardly "syntactic sugar", but it gets the job done without being horribly complex.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top