简体   繁体   中英

Evaluating list of boolean methods ruby

I have a list of methods who if any of them evaluated to true, I have to trigger an action on the model, in this case it's model audit.

So for example :

def a?
  false # in reality this is some code
end

def b?
  true # in reality this is some code
end

def c?
  true # in reality this is some code
end

Now I can group this into like a parent method like :

def parent_method
  a? || b? || c?
end

This will short-circuit the code, and c? will never be executed which is great. I can execute my .audit method.

But if I wanted to pass in custom message to my .audit method, and I wanted to have different message for every method how can I do that?

My first though to have a hash with keys being the methods and values being the messages or something along that line. But in that case the short circuiting doesn't work as all methods are evaluated in advance. How can I make this work better and more efficient/elegant?

Instead of true your method could return a trueish value like a symbol.

def a?
  false # in reality this is some code
end

def b?
  :b # in reality this is some code
end

def c?
  :c # in reality this is some code
end

That you still allow to short-circuit the code in

def parent_method
  a? || b? || c?
end

But now parent_method will not only return true or false but it would return a symbol that your allow returning a message that might be stored in a hash:

key = parent_method
audit(key) if key

You can always break these out into a simple array if you're not passing in any arguments. A minimal example looks like:

TESTS = [ :a?, :b?, :c? ]

def parent_method
  failed = TESTS.find do |test|
    !send(test)
  end

  if (failed)
    # The failed variable contains the name of the method that failed
    # to return `true`. Do whatever you need to do here.
    errors << "Test #{failed} returned false!"

    false
  else
    true
  end
end

if I wanted to pass in custom message to my .audit method, and I wanted to have different message for every method how can I do that?

You could use a case expression :

case
when a? then audit(:a)
when b? then audit(:b)
when c? then audit(:c)
end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM