views:

87

answers:

3

Is there a pretty way to make a series of method calls in ruby UNTIL one returns true?

This was my first thought, but was thinking there might be a nicer way:

if method_one
elsif method_two
elsif method_three
else
  puts "none worked"
end
+4  A: 

Try this:

[:m1, :m2, :m3, ...].find{ |m| send(m) } != nil || "none worked"

Returns true if one of the methods returns true otherwise returns none worked.

KandadaBoggu
nice! I like this one
Brian Armstrong
Also, technically this runs *all* of the methods even if one of them returns true. It could be easily modified though to something like: `[:m1, :m2, :m3, ...].find{ |m| return if send(m) }` or something like that.
Brian Armstrong
I tested the code and it works as expected. Code should work as long as the methods return `non nil` value/`true` upon success and `nil`/`false` upon failure.
KandadaBoggu
+5  A: 

There are number of Ruby-ish options. One interesting is:

method_one || method_two || method_three || Proc.new { puts "none worked" }.call

or

method_one || method_two || method_three || lambda { puts "none worked" }.call
Dmytrii Nagirniak
No need to even use a proc/lambda with this technique.`method_one || method_two || "none worked"`
Jimmy Cuadra
yep, the proc is just a nice extra I think
Brian Armstrong
@Jimmy, with the code you provided the expression will return `false`, `true` or `"none worked"` which is not the same as OP asked. You cannot also prepend all with `puts` as it will also print boolean values.
Dmytrii Nagirniak
I don't think the "puts" part is significant to the logic, it's just the way he wrote it in his example. In a real application of this type of logic, I'd imagine the return value of the expression would be assigned to something and not blindly printing it out.
Jimmy Cuadra
@Jimmy, well the question was to find a nicer way to do the same. So in this context `puts` is significant. It depends on the context of course and is likely that puts is not significant.
Dmytrii Nagirniak
+4  A: 

You can use Enumerable#any? as well.

[ :m1, :m2, :m3 ].any?{ |method| object.send( method )} || "None Worked"
Farrel
This is I think the most elegant and exactly the method I was looking for (any?)
Brian Armstrong