Nekkoru
Nekkoru

Reputation: 1165

Multiple Ruby chomp! statements

I'm writing a simple method to detect and strip tags from text strings. Given this input string:

{{foobar}}

The function has to return

foobar

I thought I could just chain multiple chomp! methods, like so:

"{{foobar}}".chomp!("{{").chomp!("}}")

but this won't work, because the first chomp! returns a NilClass. I can do it with regular chomp statements, but I'm really looking for a one-line solution.

The String class documentation says that chomp! returns a Str if modifications have been made - therefore, the second chomp! should work. It doesn't, however. I'm at a loss at what's happening here.

For the purposes of this question, you can assume that the input string is always a tag which begins and ends with double curly braces.

Upvotes: 0

Views: 910

Answers (3)

Pascal
Pascal

Reputation: 8637

Try tr:

'{{foobar}}'.tr('{{', '').tr('}}', '')

You can also use gsub or sub but if the replacement is not needed as pattern, then tr should be faster.

If there are always curly braces, then you can just slice the string:

'{{foobar}}'[2...-2]

If you plan to make a method which returns the string without curly braces then DO NOT use bang versions. Modifying the input parameter of a method will be suprising!

def strip(string)
  string.tr!('{{', '').tr!('}}', '')
end
a = '{{foobar}}'
b = strip(a)
puts b #=> foobar
puts a #=> foobar

Upvotes: 0

max pleaner
max pleaner

Reputation: 26758

Testing this out, it's clear that chomp! will return nil if the separator it's provided as an argument is not present at the end of the string.

So "{{text}}".chomp!("}}") returns a string, but "{{text}}".chomp!("{{") reurns nil.

See here for an answer of how to chomp at the beginning of a string. But recognize that chomp only looks at the end of the string. So you can call str.reverse.chomp!("{{").reverse to remove the opening brackets.

You could also use a regex:

string = "{{text}}"
puts [/^\{\{(.+)\}\}$/, 1]
# => "text"

Upvotes: 0

Simone Carletti
Simone Carletti

Reputation: 176372

You can definitely chain multiple chomp statements (the non-bang version), still having a one-line solution as you wanted:

 "{{foobar}}".chomp("{{").chomp("}}")

However, it will not work as expected because both chomp! and chomp removes the separator only from the end of the string, not from the beginning.

You can use sub

"{{foobar}}".sub(/{{(.+)}}/, '\1')
# => "foobar"

"alfa {{foobar}} beta".sub(/{{(.+)}}/, '\1')
# => "alfa foobar beta"

# more restrictive
"{{foobar}}".sub(/^{{(.+)}}$/, '\1')
# => "foobar"

Upvotes: 2

Related Questions