wsb3383
wsb3383

Reputation: 3891

Converting upper-case string into title-case using Ruby

I'm trying to convert an all-uppercase string in Ruby into a lower case one, but with each word's first character being upper case. Example:

convert "MY STRING HERE" to "My String Here".

I know I can use the .downcase method, but that would make everything lower case ("my string here"). I'm scanning all lines in a file and doing this change, so is there a regular expression I can use through ruby to achieve this?

Thanks!

Upvotes: 61

Views: 52468

Answers (11)

Francis Uloko
Francis Uloko

Reputation: 21

To catch any edge case such as:

str = "rUby on rAils"

Don't use:

str.titleize

Output: R Uby On R Ails

Use instead:

str.downcase.titleize

Output: Ruby On Rails

Upvotes: 1

James A. Rosen
James A. Rosen

Reputation: 65282

If you're using Rails (really all you need is ActiveSupport, which is part of Rails), you can use titleize:

"MY STRING HERE".titleize
# => "My String Here"

If you're using plain Ruby but don't mind loading a small amount of ActiveSupport you can require it first:

require 'active_support/core_ext/string/inflections'
# => true
"MY STRING HERE".titleize
# => "My String Here"

N.B. By default titleize doesn't handle acronyms well and will split camelCaseStrings into separate words. This may or may not be desirable:

"Always use SSL on your iPhone".titleize
# => "Always Use Ssl On Your I Phone"

You can (partially) address this by adding "acronyms":

require 'active_support/core_ext/string/inflections' # If not using Rails
ActiveSupport::Inflector.inflections do |inflect|
  inflect.acronym 'SSL'
  inflect.acronym 'iPhone'
end
"Always use SSL on your iPhone".titleize
# => "Always Use SSL On Your IPhone"

For those who speak the Queen's English (or who struggle to spell titleize), there's no .titleise alias but you can use .titlecase instead.

Upvotes: 105

magynhard
magynhard

Reputation: 238

The ruby core itself has no support to convert a string from upper (word) case to capitalized word 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 capital word case as string
LuckyCase.capital_word_case('MY STRING HERE')    # => 'My String Here'
# or the opposite way
LuckyCase.upper_word_case('Capital Word Case')   # => 'MY STRING HERE'

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

require 'lucky_case/string'

'MY STRING HERE'.capital_word_case  # => 'My String Here'
'MY STRING HERE'.capital_word_case! # => 'My String Here' and overwriting original

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

https://github.com/magynhard/lucky_case

Upvotes: 0

Adobe
Adobe

Reputation: 13487

Unicode-aware titlecase for Ruby 2.4.0+:

class String
  def titlecase
    split(/([[:alpha:]]+)/).map(&:capitalize).join
  end
end
>> "я только что посмотрел \"леди исчезает\", и это чума!".titlecase
=> "Я Только Что Посмотрел \"Леди Исчезает\", И Это Чума!"

(based on https://stackoverflow.com/a/1792102/788700)

Upvotes: 3

marcindobry
marcindobry

Reputation: 176

"MY STRING HERE".titlecase

Does the job (it's a method in the Rails gem, however) http://apidock.com/rails/String/titlecase

Upvotes: 2

K.S.A.
K.S.A.

Reputation: 1

I've try to improve code... ready for critics and suggestions.

class Book
    attr_accessor :title
    def title=(new_title)
    notcap=%w(and the a in of an)
    str=''
    new_title.gsub(/(\w|\s)\w+/) do |word|
        word.strip!
        if not notcap.include? word
               word.capitalize! 
        end
       str += ' ' + word 
    end
    str.strip!
    str = str[0].upcase + str[1..-1]
    @title = str
   end
end

Upvotes: 0

Connor Leech
Connor Leech

Reputation: 18873

Capitalizes every word in a sentence using ruby, without regex.. because unfortunately those scare me

class Book
    attr_accessor :title
    def title=(new_title)
        result = []
        words = new_title.split(' ')
        words.each do |word|
            capitalized = word[0].upcase + word[1..word.length].downcase
            result.push(capitalized)
        end

        @title = result.join(' ')
    end
end

Upvotes: -1

Jörg W Mittag
Jörg W Mittag

Reputation: 369594

While trying to come up with my own method (included below for reference), I realized that there's some pretty nasty corner cases. Better just use the method already provided in Facets, the mostest awesomest Ruby library evar:

require 'facets/string/titlecase'

class String
  def titleize
    split(/(\W)/).map(&:capitalize).join
  end
end

require 'test/unit'
class TestStringTitlecaseAndTitleize < Test::Unit::TestCase
  def setup
    @str = "i just saw \"twilight: new moon\", and man!   it's crap."
    @res = "I Just Saw \"Twilight: New Moon\", And Man!   It's Crap."
  end
  def test_that_facets_string_titlecase_works
    assert_equal @res, @str.titlecase
  end
  def test_that_my_own_broken_string_titleize_works
    assert_equal @res, @str.titleize # FAIL
  end
end

If you want something that more closely complies to typical writing style guidelines (i.e. does not capitalize words like "and"), there are a couple of "titleize" gems on GitHub.

Upvotes: 37

bantic
bantic

Reputation: 4964

string = "MY STRING HERE"
string.split(" ").map {|word| word.capitalize}.join(" ")

The way this works: The .split(" ") splits it on spaces, so now we have an array that looks like ["my", "string", "here"]. The map call iterates over each element of the array, assigning it to temporary variable word, which we then call capitalize on. Now we have an array that looks like ["My", "String", "Here"], and finally we turn that array back into a string by joining each element with a space (" ").

Upvotes: 5

Simone Carletti
Simone Carletti

Reputation: 176552

From ActiveSupport

"MY STRING HERE".gsub(/\b('?[a-z])/) { $1.capitalize }

If you are using Rails/ActiveSupport, the method is already available for free.

Upvotes: 9

sepp2k
sepp2k

Reputation: 370425

"HELLO WORLD HOW ARE YOU".gsub(/\w+/) do |word|
  word.capitalize
end
#=> "Hello World How Are You"

Upvotes: 63

Related Questions