-2

I'm working with a large codebase where I see the following code a lot:

if foo.respond_to?(:bar)
  unless foo.bar.nil?
    # do stuff
  end
end

Is there a way to do that in one line?

[Final Answer]

if foo.respond_to?(:bar) and not foo.bar.nil?
  # do stuff
end
bitcycle
  • 7,632
  • 16
  • 70
  • 121
  • 1
    Other than the trivial case of using `&&` to combine the conditionals? – Max Dec 30 '13 at 21:45
  • 2
    For some reason it seems like a code smell to me if you see that *a lot*. Wouldn't it be better if all `foo`s had some implementation of `bar`, even if it possibly does nothing? Or maybe use the visitor pattern if "do stuff" changes. – millimoose Dec 30 '13 at 21:55
  • @millimoose lol. Yeah. Lots of things would be better if was used in the legacy code base. That's why its called "legacy". :) – bitcycle Dec 30 '13 at 21:57
  • @bitcycle Fair enough. My reasoning was: if you're already going to change all that code, it might be feasible to actually do it right. (Or it might not, no idea what other constraints you're operating under.) – millimoose Dec 30 '13 at 22:00

2 Answers2

1

One line or one method call? unless is simply a logically inverted if so you can put it on one line like this...

if foo.respond_to?(:bar) && !foo.bar.nil?
  # do stuff
end

Otherwise you can create a method on foo or some sort of helper that makes the checks in a single call.

dee-see
  • 23,668
  • 5
  • 58
  • 91
1

If you are using ActiveSupport >= 4.0, Object#try will return nil if the object does not respond to the method. As mentioned in the Rails 4 release notes.

Object#try will now return nil instead of raise a NoMethodError if the receiving object does not implement the method, but you can still get the old behavior by using the new Object#try!.

So, you could do what you want with unless foo.try(:bar). Maybe not useful in this case if you're not using ActiveSupport, but others who find this page might be interested to know this.

Logan Serman
  • 29,447
  • 27
  • 102
  • 141