25

I have a string called word and a function called infinitive such that
word.infinitive would return another string on some occasions and an empty string otherwise
I am trying to find an elegant ruby one line expression for the code-snippet below

if word.infinitive == ""
      return word
else return word.infinitive

Had infinitive returned nil instead of "", I could have done something like

(word.infinitive or word)

But since it does not, I can't take advantage of the short-circuit OR
Ideally I would want
1) a single expression that I could easily embed in other code
2) the function infinitive being called only once
3) to not add any custom gems or plugins into my code

2
  • Note that "or" and || do the same thing, but || has much higher precedence Commented Mar 15, 2009 at 8:33
  • in other words, they both short-circuit, is what I was trying to say Commented Mar 15, 2009 at 8:34

6 Answers 6

129

The ActiveSupport presence method converts an empty (or blank?) string to nil. It's designed for your exact use case:

word.infinitive.presence || word

Note that you can easily use ActiveSupport outside of rails:

require 'active_support/core_ext/object/blank'
Sign up to request clarification or add additional context in comments.

1 Comment

@Intrepidd I can't either, so I'll upvote your comment instead.
11

You can use a regex like this article suggests

(word.infinitive[/.+/m] or word) #Fancy way to convert "" to nil

Comments

7

If you're not ashamed of monkeypatching and abusing syntax, this would work:

class String
  def | x
    if empty? then x else self end
  end
end

Then you can say word.infinitive | word, which actually scans fairly naturally, if you ask me.

However, I think a better idea would be to modify the infinitive method, or add a version of it that returns the word unchanged.

Edit: Here's a possibly more elegant solution:

[word.infinitive, word].find {|x| not x.empty?}

6 Comments

That's clever, but the OP sounds like he's leaning towards something minimally invasive.
this is invasive... but considering the fact that I have to do something like this on multiple occasions, its a pretty useful trick.. can't imagine how this would screw up any code in other places.. thanks
@adi92 I would really suggest rewriting the infinitive method if you could.
its part of a package my code is importing.. other people's code also use those packages.. so modifying infinitive is not really an option.
((vv=<something>)!='' || nil) && vv turns <something> into nil if its value is ''
|
6

Do the right thing - fix infinitive so that it returns nils instead of blank strings, or wrap it with your own interface if you really can't touch it.

Comments

5

Or you can monkeypatch a new function to String without having to abuse syntax.

class String
  def squash
    self.empty? ? nil : self
  end
end

Now you can do

puts var.squash or "default text"

I'm not a native english speaker so I don't know if squash is the best word. Is there a word that would better convey the idea of "turn into nil only if empty"?

2 Comments

I like it, I think I'll be using this some: class String def nillify self.empty? ? nil : self end end "".nillify or "foo" => "foo"
@DGM I named it to_nil, although it doesn't change non-empty strings.
4

You could use the ternary operator (boolean ? true-val : false-val) with String#empty?

return word.infinitive.empty? ? word : word.infinitive

if you only want to call infinitive once:

return (inf = word.infinitive).empty? ? word : inf

You may also want to consider adding some memoization to your code.

Comments

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.