MechDog
MechDog

Reputation: 548

Ruby concatenating best practice

I need to solve a simple issue in Ruby, but want to do it in a smart way. I have a function:

def fullname
  first + " " + mi + last
end

That will crash if one or more of the variables is nil, let's say mi for this example since it's in the center.

Error:

can't convert nil into String

If I change the function to:

def fullname
  first + " " + mi.to_s + last
end

or

def fullname
  first + " " + (mi || "") + last
end

It will fix it. Now I want to add an additional space after the mi (middle initial) if it is present and I'm stumped for some silly reason. What would be the cleanest way to do something like this, as I will be having to do it a lot and sometimes adding say a comma.

Example of that need:

def fullname
  first + " " + (mi || "") + last + suffix 
  # want a ", " afer the last name if there is a suffix
end

Upvotes: 3

Views: 1324

Answers (3)

Shoe
Shoe

Reputation: 76240

I'd suggest you to use string interpolation to make it clear that you are returning a string from that method (and will also ignore nil values):

def fullname
    s = "#{first} #{mi} #{last}".lstrip.rstrip.squeeze(' ')
    s += ", #{suffix}" if suffix
end

Upvotes: 1

sawa
sawa

Reputation: 168081

def fullname
  [[first, *mi, last].join(" "), *suffix].join(", ")
end

Upvotes: 7

Dan Tao
Dan Tao

Reputation: 128317

First: I would actually say that the most "Ruby" way of handling this—avoiding the nil issue, that is—would be to use string interpolation:

"#{first} #{mi} #{last}"

This works just fine in case any of the above variables is nil, because it will simply result in blank space in the string.

As for the conditional space issue: There are plenty of ways to skin that cat. I really like sawa's idea. Here's another, which I've seen variants of, though it's not particularly efficient (but 9 times out of 10 that doesn't matter):

[first, mi, last].compact.join(" ")

Lastly: for the "plus comma + suffix if present" requirement, that's complicated enough that I'd recommend writing a little method to separate that logic out:

def suffix_if_necessary(name)
  suffix ? "#{name}, #{suffix}" : name
end

def fullname
  suffix_if_necessary([first, *mi, last].join(" "))
end

But again, there are multiple ways to get the job done here. Whatever works for you.

Upvotes: 9

Related Questions