86

This works for any strings that have whitespaces in them

str.downcase.tr!(" ", "_")

but strings that dont have whitespaces just get deleted

So "New School" would change into "new_school" but "color" would be "", nothing!

1
  • 2
    Don't take my word for it, but I think it's str.gsub! /\s/, '_'
    – user2058002
    Commented Sep 25, 2011 at 17:06

8 Answers 8

159

Pass '_' as parameter to parameterize(separator: '-'). For Rails 4 and below, use str.parameterize('_')

Examples:

with space

str = "New School"
str.parameterize(separator: '_')

=> "new_school"

without space

str = "school"
str.parameterize(separator: '_')

=> "school"

You can also solve this by chaining underscore to parameterize.

Examples:

with space

str = "New School"
str.parameterize.underscore

=> "new_school"

without space

str = "school"
str.parameterize.underscore

=> "school"
4
  • 5
    Be careful. parameterize will convert more than spaces--many special characters will be converted too. The intent of parameterize is to make a string URL-friendly. Commented May 28, 2015 at 12:03
  • 5
    Be careful as there is no String#parameterize in Ruby. There is String#parameterize in Rails, though.
    – dskecse
    Commented Sep 7, 2015 at 15:19
  • 4
    And parameterize no longer takes an argument. Commented May 13, 2017 at 5:14
  • 4
    On Rails 5, use str.parameterize(separator: '_').
    – BrunoF
    Commented Jul 30, 2019 at 19:18
45

The docs for tr! say

Translates str in place, using the same rules as String#tr. Returns str, or nil if no changes were made.

I think you'll get the correct results if you use tr without the exclamation.

1
  • Indeed, ! changes whatever is calling it, whereas without the ! it returns a new string
    – erdostom
    Commented Dec 7, 2015 at 21:40
39

If you're interested in getting a string in snake case, then the proposed solution doesn't quite work, because you may get concatenated underscores and starting/trailing underscores.

For example

1.9.3-p0 :010 > str= "  John   Smith Beer "
  => "  John   Smith Beer " 
1.9.3-p0 :011 > str.downcase.tr(" ", "_")
  => "__john___smith_beer_"

This solution below would work better:

1.9.3-p0 :010 > str= "  John   Smith Beer "
  => "  John   Smith Beer " 
1.9.3-p0 :012 > str.squish.downcase.tr(" ","_")
  => "john_smith_beer" 

squish is a String method provided by Rails

1
  • 4
    I figure str.downcase.split.join('_') could also work if #squish is not available ;)
    – vidbina
    Commented Jun 29, 2014 at 0:36
17

If you are using rails 5 and above you can achieve the same thing with

str.parameterize(separator: '_')

Note, this is not the exact same as .parameterize.underscore:

"New School 1-2".parameterize( separator: "_" ) #=> "new_school_1-2"
"New School 1-2".parameterize.underscore        #=> "new_school_1_2"
9

Old question, but...

For all whitespace you probably want something more like this:

"hey\t there   world".gsub(/\s+/, '_') # hey_there_world

This gets tabs and new lines as well as spaces and replaces with a single _.

The regex can be modified to suit your needs. E.g:

"hey\t there   world".gsub(/\s/, '_') # hey__there___world
8
str.downcase.tr(" ", "_")

Note: No "!"

2

You can also do str.gsub(" ", "_")

2
str = "Foo Bar"
str.tr(' ','').underscore

=> "foo_bar"

Not the answer you're looking for? Browse other questions tagged or ask your own question.