Search code examples
javascriptrubyconditional-operatoror-operator

How should I handle a conditional in Ruby where the test could result in an error?


I have a situation like this:

# self refers to an instance of a Book class
self.author = instance_of_author_class                    #returns instance
self.author.name = instance_variable_in_author_instance   #returns string

# this is an instance method of the Book class:
def author_name
    self.author ? self.author.name : nil                  #returns string or nil
end

This code works fine, as it first checks to see if there is an author set, then returns its name, or nil if no author is set.

However, I would love to be able to do this with a bit less code, as I find I'm often in the situation where I want to "just return the thing if it exists". I don't love having to test the thing before simply returning it. The || OR expression seems like it would work perfect.

def author_name
    self.author.name || nil
end

This would work great if self.author.name was somehow pre-initialized as false or nil, but unfortunately if the author isn't set to some valid instance (and that valid instance also has the name method defined), then I'll get:

NoMethodError:
       undefined method `name' for nil:NilClass

And unfortunately, ruby doesn't seem to treat errors like this as false, it stops execution.

Any ideas on how I can achieve this goal?

(javascript stackoverflow tag added as well, because I'd welcome javascript solutions too!)


Solution

  • You can just use the safe navigation operator which was introduced to Ruby in 2.3:

    def author_name
      author&.name
    end
    

    Note that self is not needed in your example.

    Or when you are on Ruby on Rails then you might want to use delegate:

    delegate :name, to: :author, prefix: true, allow_nil: true