189

I need to make the first character of every word uppercase, and make the rest lowercase...

manufacturer.MFA_BRAND.first.upcase

is only setting the first letter uppercase, but I need this:

ALFA ROMEO => Alfa Romeo
AUDI => Audi
BMW => Bmw
ONETWO THREE FOUR => Onetwo Three Four
eebbesen
  • 5,070
  • 8
  • 48
  • 70
byCoder
  • 3,462
  • 6
  • 28
  • 49

8 Answers8

339

In Rails:

"kirk douglas".titleize => "Kirk Douglas"
#this also works for 'kirk_douglas'

w/o Rails:

"kirk douglas".split(/ |\_/).map(&:capitalize).join(" ")

#OBJECT IT OUT
def titleize(str)
  str.split(/ |\_/).map(&:capitalize).join(" ")
end

#OR MONKEY PATCH IT
class String  
  def titleize
    self.split(/ |\_/).map(&:capitalize).join(" ")
  end
end

w/o Rails (load rails's ActiveSupport to patch #titleize method to String)

require 'active_support/core_ext'
"kirk douglas".titleize #=> "Kirk Douglas"

(some) string use cases handled by #titleize

  • "kirk douglas"
  • "kirk_douglas"
  • "kirk-douglas"
  • "kirkDouglas"
  • "KirkDouglas"

#titleize gotchas

Rails's titleize will convert things like dashes and underscores into spaces and can produce other unexpected results, especially with case-sensitive situations as pointed out by @JamesMcMahon:

"hEy lOok".titleize #=> "H Ey Lo Ok"

because it is meant to handle camel-cased code like:

"kirkDouglas".titleize #=> "Kirk Douglas"

To deal with this edge case you could clean your string with #downcase first before running #titleize. Of course if you do that you will wipe out any camelCased word separations:

"kirkDouglas".downcase.titleize #=> "Kirkdouglas"
boulder_ruby
  • 38,457
  • 9
  • 79
  • 100
230

try this:

puts 'one TWO three foUR'.split.map(&:capitalize).join(' ')

#=> One Two Three Four

or

puts 'one TWO three foUR'.split.map(&:capitalize)*' '
  • 9
    `split` will split on space by default, so you can make it even shorter: `'one TWO three foUR'.split.map(&:capitalize).join(' ')` – Mischa Jun 13 '13 at 06:53
  • 1
    @waltee Could you possibly explain the `.map(&:capitalize)` or at least point to where in the doc you found it? I can't find any reference to that. Also, what is the deal with the `*' '` at the end of the second code snippet? – macsplean Oct 21 '13 at 07:02
  • 7
    @macsplean the `&:method` syntax in `map` is a [concise way to call a method on each item in the array](http://stackoverflow.com/questions/1217088/what-does-ampersand-colon-pretzel-colon-mean-in-ruby). You can then call `join` to turn that array into a string. The `* ' '` is an [alternative way to call join](http://brettu.com/ruby-ruby-tips-236-alternative-arrayjoin-syntax/). You can think of it as multiplying the items in the array together to create a string. – Andrew Nov 15 '13 at 21:13
38

"hello world".titleize which should output "Hello World".

Andrei Stefan
  • 51,654
  • 6
  • 98
  • 89
24

Another option is to use a regex and gsub, which takes a block:

'one TWO three foUR'.gsub(/\w+/, &:capitalize)
Bob Nadler
  • 1,247
  • 14
  • 18
5
"hello world".split.each{|i| i.capitalize!}.join(' ')
Himanshu
  • 31,810
  • 31
  • 111
  • 133
Muhamamd Awais
  • 2,385
  • 14
  • 25
  • 1
    there's no reason to use a bang (!) operator if you're not working with a variable – boulder_ruby Jul 19 '13 at 15:06
  • 2
    @boulder_ruby It's not true that *"there's no reason to use a bang operator if you're not working with a variable."* The return value of each iteration of the `each` block is being discarded. The `!` is modifying the strings produced by `split` in-place. Without the `!`, `capitalize` would be creating one new capitalized string per iteration, and then immediately discarding it. The final result would be `"hello world"`, just the same as the original string. With the `!`, each string in the `split`'d array is being changed, and therefore the result of `each` is an array of capitalized strings. – user513951 Feb 25 '14 at 00:06
  • 1
    Yeah you're just supposed to use `map`. Interesting hack though. Points – boulder_ruby Feb 25 '14 at 00:20
4

Look into the String#capitalize method.

http://www.ruby-doc.org/core-1.9.3/String.html#method-i-capitalize

  • 1
    String#capitalize downcases the rest of the string after the first letter. For names like "McGee", that is an undesired result, but it is partly useful in this case. – Br.Bill Apr 04 '18 at 02:00
1

If you are trying to capitalize the first letter of each word in an array you can simply put this:

array_name.map(&:capitalize)

astee
  • 13
  • 4
1

I used this for a similar problem:

'catherine mc-nulty joséphina'.capitalize.gsub(/(\s+\w)/) { |stuff| stuff.upcase }

This handles the following weird cases I saw trying the previous answers:

  • non-word characters like -
  • accented characters common in names like é
  • capital characters in the middle of the string