3

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
3
  • 1
    You shouldn't rely on fullnames having a defined schema: w3.org/International/questions/qa-personal-names Commented Jul 23, 2013 at 15:45
  • 2
    @DamienMATHIEU: Baby steps, my friend. The OP is a self-described newbie; don't overwhelm him ;) Commented Jul 23, 2013 at 15:46
  • Thank-you and 110% understand that this isn't internationalized at all yet. Need to get some of these basics down before I can cross that bridge I think. Thank-you for the article, definitely something I need to read and understand! Commented Jul 23, 2013 at 15:50

3 Answers 3

9

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.

Sign up to request clarification or add additional context in comments.

3 Comments

That does look cleaner for sure. Am I thinking correctly that if there is no mi variable there would be 2 spaces between the first and last name instead of just one?
@MechDog: Yep, that's correct. I just updated the answer to address your requirement for conditional spacing. As I concede, it isn't particularly efficient; but since these are just three little strings the performance and memory impact should be negligible.
Thanks for the help! Both solutions seem to work and I'm sure each one will have its place. Thanks for helping to get this newbie out of a jam point! Learned a bunch from you and @sawa and I thank-you both for your time and effort!!!
7
def fullname
  [[first, *mi, last].join(" "), *suffix].join(", ")
end

14 Comments

That works great for the spaces, thank-you! Is there a tweak that would allow for it to be a space sometimes or other times a comma? I will update my question to reflect that better.
Sorry for the confusion, deleted my comment. I was building on your great examples and it probably looked like I was asking if your code was bad, when I was asking if mine was bad. Thank you for the help!!!!!
Despite it being a solution for this particular case. You shouldn't really use this kind of cryptic code. You can't tell at first sight that this produces a string and therefore might be confusing for those that will read the code after you. Please take a look at string interpolation instead.
@Jeffrey Would you post an answer using string interpolation?
Lol, thought I could accept more then one. Sorry, need to learn more about the interface is all. There's just no point in being stupid if you can't show it;-)
|
1

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

4 Comments

How does that handle the optional suffix?
And you say that this is not cryptic?
@sawa, The most cryptic thing about this is the String#+= method. Go figure. Also this is not iterating over any array (especially multidimensional) and therefore has, theoretically little complexity over, your solution for example.
I thought you posted this to show you can have an answer with interpolation that is not "cryptic" as mine.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.