Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DRY up Ruby ternary

I often have a situation where I want to do some conditional logic and then return a part of the condition. How can I do this without repeating the part of the condition in the true or false expression?

For example:

ClassName.method.blank? ? false : ClassName.method

Is there any way to avoid repeating ClassName.method?

Here is a real-world example:

PROFESSIONAL_ROLES.key(self.professional_role).nil? ? 
    948460516 : PROFESSIONAL_ROLES.key(self.professional_role)
like image 272
Reed G. Law Avatar asked Jan 07 '11 22:01

Reed G. Law


2 Answers

Assuming you're okay with false being treated the same way as nil, you use ||:

PROFESSIONAL_ROLES.key(self.professional_role) || 948460516

This will return 948460516 if key returns nil or false and the return value of the call to key otherwise.

Note that this will only return 948460516 if key returns nil or false, not if it returns an empty array or string. Since you used nil? in your second example, I assume that's okay. However you used blank? in the first example (and blank? returns true for empty arrays and strings), so I'm not sure.

like image 193
sepp2k Avatar answered Sep 24 '22 06:09

sepp2k


If you just want to DRY, then you can use a temp variable:

x = ClassName.method
x.blank? ? false : x

x = PROFESSIONAL_ROLES.key(self.professional_role)
x.nil? ? 948460516 : x

If you don't want to use a temp variable, you can use a block:

Proc.new do |x| x.blank? ? false : x end.call(ClassName.method)
Proc.new do |x| x.nil? ? 948460516 : x end.call(PROFESSIONAL_ROLES.key(self.professional_role))

For the cases you describe (where you just want to use the original value when a default-check fails), it'd be straightforward to write a helper method:

def x_or_default(x, defval, checker = :nil?)
  if x.send(checker) then defval else x end
end
x_or_default(ClassName.method, false, :blank?)
x_or_default(PROFESSIONAL_ROLES.key(self.professional_role), 94840516)

which is very similar to the || method described, but would also work with your blank? example.

I usually use temporary variables for this sort of thing.

like image 25
Aidan Cully Avatar answered Sep 20 '22 06:09

Aidan Cully