/ Tags: RUBY-CODE / Categories: SOLUTIONS

Convert Strings Between Snake_case And Camelcase In Ruby

When bridging Ruby code (which uses snake_case) with JavaScript APIs or JSON payloads (which often use camelCase), you regularly need to convert between the two formats. Ruby and Rails provide clean ways to do both directions.

Description

Rails ActiveSupport adds camelize and underscore to String for converting between snake_case and CamelCase. In plain Ruby without ActiveSupport, a few targeted gsub calls handle both directions cleanly. camelize by default produces UpperCamelCase (PascalCase). Pass false or :lower to get lowerCamelCase for JSON keys. These conversions are essential when serializing Ruby hashes to JSON for JavaScript frontends, or when parsing incoming camelCase params from a JavaScript client into Rails-friendly snake_case keys.

Sample input:

  "user_first_name"   # snake β†’ camel
  "userFirstName"     # camel β†’ snake


Sample Output:

  "UserFirstName"     # UpperCamelCase
  "userFirstName"     # lowerCamelCase
  "user_first_name"   # snake_case

Answer

  # With ActiveSupport (Rails)
  "user_first_name".camelize          # => "UserFirstName"
  "user_first_name".camelize(:lower)  # => "userFirstName"
  "userFirstName".underscore          # => "user_first_name"

  # Plain Ruby β€” no ActiveSupport
  def to_camel_case(str, upper: true)
    result = str.gsub(/_([a-z])/) { $1.upcase }
    upper ? result.sub(/^(.)/) { $1.upcase } : result
  end

  def to_snake_case(str)
    str.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
       .gsub(/([a-z\d])([A-Z])/, '\1_\2')
       .downcase
  end

  to_camel_case("user_first_name")          # => "UserFirstName"
  to_camel_case("user_first_name", upper: false)  # => "userFirstName"
  to_snake_case("UserFirstName")            # => "user_first_name"

Learn More

cdrrazan

Rajan Bhattarai

Full Stack Software Developer! πŸ’» 🏑 Grad. Student, MCS. πŸŽ“ Class of '23. GitKraken Ambassador πŸ‡³πŸ‡΅ 2021/22. Works with Ruby / Rails. Photography when no coding. Also tweets a lot at TW / @cdrrazan!

Read More