Converting string from snake_case to CamelCase in Ruby

Ruby on-RailsRubyString

Ruby on-Rails Problem Overview


I am trying to convert a name from snake case to camel case. Are there any built-in methods?

Eg: "app_user" to "AppUser"

(I have a string "app_user" I want to convert that to model AppUser).

Ruby on-Rails Solutions


Solution 1 - Ruby on-Rails

If you're using Rails, String#camelize is what you're looking for.

  "active_record".camelize                # => "ActiveRecord"
  "active_record".camelize(:lower)        # => "activeRecord"

If you want to get an actual class, you should use String#constantize on top of that.

"app_user".camelize.constantize

Solution 2 - Ruby on-Rails

How about this one?

"hello_world".split('_').collect(&:capitalize).join #=> "HelloWorld"

Found in the comments here: https://stackoverflow.com/questions/4072159/classify-a-ruby-string

See comment by Wayne Conrad

Solution 3 - Ruby on-Rails

If you use Rails, Use classify. It handles edge cases well.

"app_user".classify # => AppUser
"user_links".classify   # => UserLink

Note:

This answer is specific to the description given in the question(it is not specific to the question title). If one is trying to convert a string to camel-case they should use Sergio's answer. The questioner states that he wants to convert app_user to AppUser (not App_user), hence this answer..

Solution 4 - Ruby on-Rails

Source: http://rubydoc.info/gems/extlib/0.9.15/String#camel_case-instance_method

For learning purposes:

class String
  def camel_case
    return self if self !~ /_/ && self =~ /[A-Z]+.*/
    split('_').map{|e| e.capitalize}.join
  end
end

"foo_bar".camel_case          #=> "FooBar"

And for the lowerCase variant:

class String
  def camel_case_lower
    self.split('_').inject([]){ |buffer,e| buffer.push(buffer.empty? ? e : e.capitalize) }.join
  end
end

"foo_bar".camel_case_lower          #=> "fooBar"

Solution 5 - Ruby on-Rails

Benchmark for pure Ruby solutions

I took every possibilities I had in mind to do it with pure ruby code, here they are :

  • capitalize and gsub

      'app_user'.capitalize.gsub(/_(\w)/){$1.upcase}
    
  • split and map using & shorthand (thanks to user3869936’s answer)

      'app_user'.split('_').map(&:capitalize).join
    
  • split and map (thanks to Mr. Black’s answer)

      'app_user'.split('_').map{|e| e.capitalize}.join
    

And here is the Benchmark for all of these, we can see that gsub is quite bad for this. I used 126 080 words.

                              user     system      total        real
capitalize and gsub  :      0.360000   0.000000   0.360000 (  0.357472)
split and map, with &:      0.190000   0.000000   0.190000 (  0.189493)
split and map        :      0.170000   0.000000   0.170000 (  0.171859)

Solution 6 - Ruby on-Rails

I got here looking for the inverse of your question, going from camel case to snake case. Use underscore for that (not decamelize):

AppUser.name.underscore # => "app_user"

or, if you already have a camel case string:

"AppUser".underscore # => "app_user"

or, if you want to get the table name, which is probably why you'd want the snake case:

AppUser.name.tableize # => "app_users"

Solution 7 - Ruby on-Rails

I feel a little uneasy to add more answers here. Decided to go for the most readable and minimal pure ruby approach, disregarding the nice benchmark from @ulysse-bn. While :class mode is a copy of @user3869936, the :method mode I don't see in any other answer here.

  def snake_to_camel_case(str, mode: :class)
    case mode
    when :class
      str.split('_').map(&:capitalize).join
    when :method
      str.split('_').inject { |m, p| m + p.capitalize }
    else
      raise "unknown mode #{mode.inspect}"
    end
  end

Result is:

[28] pry(main)> snake_to_camel_case("asd_dsa_fds", mode: :class)
=> "AsdDsaFds"
[29] pry(main)> snake_to_camel_case("asd_dsa_fds", mode: :method)
=> "asdDsaFds"

Solution 8 - Ruby on-Rails

Extend String to Add Camelize

In pure Ruby you could extend the string class using code lifted from Rails .camelize

class String
  def camelize(uppercase_first_letter = true)
    string = self
    if uppercase_first_letter
      string = string.sub(/^[a-z\d]*/) { |match| match.capitalize }
    else
      string = string.sub(/^(?:(?=\b|[A-Z_])|\w)/) { |match| match.downcase }
    end
    string.gsub(/(?:_|(\/))([a-z\d]*)/) { "#{$1}#{$2.capitalize}" }.gsub("/", "::")
  end
end

Solution 9 - Ruby on-Rails

The ruby core itself has no support to convert a string from snake case to (upper) camel case (also known as pascal 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'

# to get upper camel case (pascal case) as string
LuckyCase.pascal_case('app_user') # => 'AppUser'
# to get the pascal case constant
LuckyCase.constantize('app_user') # => AppUser
# or the opposite way
LuckyCase.snake_case('AppUser')   # => app_user

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

require 'lucky_case/string'

'app_user'.pascal_case # => 'AppUser'
'app_user'.constantize # => AppUser
# ...

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

https://github.com/magynhard/lucky_case

Solution 10 - Ruby on-Rails

Most of the other methods listed here are Rails specific. If you want do do this with pure Ruby, the following is the most concise way I've come up with (thanks to @ulysse-bn for the suggested improvement)

x="this_should_be_camel_case"
x.gsub(/(?:_|^)(\w)/){$1.upcase}
    #=> "ThisShouldBeCamelCase"

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
QuestionLohith MVView Question on Stackoverflow
Solution 1 - Ruby on-RailsSergio TulentsevView Answer on Stackoverflow
Solution 2 - Ruby on-Railsuser3869936View Answer on Stackoverflow
Solution 3 - Ruby on-RailsHarish ShettyView Answer on Stackoverflow
Solution 4 - Ruby on-RailsMr. BlackView Answer on Stackoverflow
Solution 5 - Ruby on-RailsUlysse BNView Answer on Stackoverflow
Solution 6 - Ruby on-RailsmikeView Answer on Stackoverflow
Solution 7 - Ruby on-RailsakostadinovView Answer on Stackoverflow
Solution 8 - Ruby on-RailsCameron Lowell PalmerView Answer on Stackoverflow
Solution 9 - Ruby on-RailsmagynhardView Answer on Stackoverflow
Solution 10 - Ruby on-RailsmasukomiView Answer on Stackoverflow