DRY up Ruby ternary

谁说我不能喝 提交于 2019-12-06 23:07:16

问题


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)

回答1:


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.




回答2:


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.




回答3:


I know this doesn't look too pretty, but it does make things a bit DRYer.

a = "ABC"
b = (temp = a.downcase).length < 3 ? "---" : temp

If you don't want to create temp variable for whatever reason, you could reuse something that already exists like $_.



来源:https://stackoverflow.com/questions/4630854/dry-up-ruby-ternary

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!