Converting camel case to underscore case in ruby

Ruby on-RailsRubyStringFormattingCase Conversion

Ruby on-Rails Problem Overview


Is there any ready function which converts camel case Strings into underscore separated string?

I want something like this:

"CamelCaseString".to_underscore      

to return "camel_case_string".

...

Ruby on-Rails Solutions


Solution 1 - Ruby on-Rails

Rails' ActiveSupport adds underscore to the String using the following:

class String
  def underscore
    self.gsub(/::/, '/').
    gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
    gsub(/([a-z\d])([A-Z])/,'\1_\2').
    tr("-", "_").
    downcase
  end
end

Then you can do fun stuff:

"CamelCase".underscore
=> "camel_case"

Solution 2 - Ruby on-Rails

You can use

"CamelCasedName".tableize.singularize

Or just

"CamelCasedName".underscore

Both options ways will yield "camel_cased_name". You can check more details it here.

Solution 3 - Ruby on-Rails

One-liner Ruby implementation:

class String
   # ruby mutation methods have the expectation to return self if a mutation occurred, nil otherwise. (see http://www.ruby-doc.org/core-1.9.3/String.html#method-i-gsub-21)
   def to_underscore!
     gsub!(/(.)([A-Z])/,'\1_\2')
     downcase!
   end

   def to_underscore
     dup.tap { |s| s.to_underscore! }
   end
end

So "SomeCamelCase".to_underscore # =>"some_camel_case"

Solution 4 - Ruby on-Rails

There is a Rails inbuilt method called 'underscore' that you can use for this purpose

"CamelCaseString".underscore #=> "camel_case_string" 

The 'underscore' method can typically be considered as inverse of 'camelize'

Solution 5 - Ruby on-Rails

Here's how Rails does it:

   def underscore(camel_cased_word)
     camel_cased_word.to_s.gsub(/::/, '/').
       gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
       gsub(/([a-z\d])([A-Z])/,'\1_\2').
       tr("-", "_").
       downcase
   end

Solution 6 - Ruby on-Rails

In case someone looking for case when he need to apply underscore to string with spaces and want to convert them to underscores as well you can use something like this

'your String will be converted To underscore'.parameterize.underscore
#your_string_will_be_converted_to_underscore

Or just use .parameterize('_') but keep in mind that this one is deprecated

'your String will be converted To underscore'.parameterize('_')
#your_string_will_be_converted_to_underscore

Solution 7 - Ruby on-Rails

Short oneliner for CamelCases when you have spaces also included (doesn't work correctly if you have a word inbetween with small starting-letter):

a = "Test String"
a.gsub(' ', '').underscore
  
  => "test_string"

EDIT: As pointed out by @dft then this method is not part of Ruby but Rails.

Solution 8 - Ruby on-Rails

Check out snakecase from Ruby Facets

The following cases are handled, as seen below:

"SnakeCase".snakecase         #=> "snake_case"
"Snake-Case".snakecase        #=> "snake_case"
"Snake Case".snakecase        #=> "snake_case"
"Snake  -  Case".snakecase    #=> "snake_case"

From: https://github.com/rubyworks/facets/blob/master/lib/core/facets/string/snakecase.rb

class String

  # Underscore a string such that camelcase, dashes and spaces are
  # replaced by underscores. This is the reverse of {#camelcase},
  # albeit not an exact inverse.
  #
  #   "SnakeCase".snakecase         #=> "snake_case"
  #   "Snake-Case".snakecase        #=> "snake_case"
  #   "Snake Case".snakecase        #=> "snake_case"
  #   "Snake  -  Case".snakecase    #=> "snake_case"
  #
  # Note, this method no longer converts `::` to `/`, in that case
  # use the {#pathize} method instead.

  def snakecase
    #gsub(/::/, '/').
    gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
    gsub(/([a-z\d])([A-Z])/,'\1_\2').
    tr('-', '_').
    gsub(/\s/, '_').
    gsub(/__+/, '_').
    downcase
  end

  #
  alias_method :underscore, :snakecase

  # TODO: Add *separators to #snakecase, like camelcase.

end

Solution 9 - Ruby on-Rails

Receiver converted to snake case: http://rubydoc.info/gems/extlib/0.9.15/String#snake_case-instance_method

This is the Support library for DataMapper and Merb. (http://rubygems.org/gems/extlib)

def snake_case
return downcase if match(/\A[A-Z]+\z/)
gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').
gsub(/([a-z])([A-Z])/, '\1_\2').
downcase
end




"FooBar".snake_case           #=> "foo_bar"
"HeadlineCNNNews".snake_case  #=> "headline_cnn_news"
"CNN".snake_case              #=> "cnn"

"FooBar".snake_case #=> "foo_bar" "HeadlineCNNNews".snake_case #=> "headline_cnn_news" "CNN".snake_case #=> "cnn"

Solution 10 - Ruby on-Rails

I would like this:

class String

  # \n returns the capture group of "n" index
  def snakize
    self.gsub(/::/, '/')
    .gsub(/([a-z\d])([A-Z])/, "\1_\2")
    .downcase
  end

  # or

  def snakize
    self.gsub(/::/, '/')
    .gsub(/([a-z\d])([A-Z])/) do
      "#{$1}_#{$2}"
    end
    .downcase
  end

end

Monkey patch of String class. There are class that begin with two or more letters in uppercase.

Solution 11 - Ruby on-Rails

The ruby core itself has no support to convert a string from (upper) camel case to (also known as pascal case) to underscore (also known as snake case).

So you need either to make your own implementation or use an existing gem.

There is a small ruby gem called lucky_case which allows you to convert a string from any of the 10+ supported cases to another case easily:

require 'lucky_case'

# convert to snake case string
LuckyCase.snake_case('CamelCaseString')      # => 'camel_case_string'
# or the opposite way
LuckyCase.pascal_case('camel_case_string')   # => 'CamelCaseString'

You can even monkey patch the String class if you want to:

require 'lucky_case/string'

'CamelCaseString'.snake_case  # => 'camel_case_string'
'CamelCaseString'.snake_case! # => 'camel_case_string' and overwriting original

Have a look at the offical repository for more examples and documentation:

https://github.com/magynhard/lucky_case

Solution 12 - Ruby on-Rails

I had trouble running "CamelCaseString".underscore in a rake task. This helped me:

ActiveSupport::Inflector.underscore "CamelCaseString"
=> "camel_case_string"

Of course, you need to require ActiveSupport

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDaniel CukierView Question on Stackoverflow
Solution 1 - Ruby on-RailsjrhicksView Answer on Stackoverflow
Solution 2 - Ruby on-Railsabo-elleefView Answer on Stackoverflow
Solution 3 - Ruby on-RailskirushikView Answer on Stackoverflow
Solution 4 - Ruby on-RailsAaditi JainView Answer on Stackoverflow
Solution 5 - Ruby on-RailsPestoView Answer on Stackoverflow
Solution 6 - Ruby on-RailsArman PetrosyanView Answer on Stackoverflow
Solution 7 - Ruby on-RailsAndresView Answer on Stackoverflow
Solution 8 - Ruby on-RailsAbramView Answer on Stackoverflow
Solution 9 - Ruby on-RailsMr. BlackView Answer on Stackoverflow
Solution 10 - Ruby on-RailsrplaurindoView Answer on Stackoverflow
Solution 11 - Ruby on-RailsmagynhardView Answer on Stackoverflow
Solution 12 - Ruby on-RailsRimianView Answer on Stackoverflow