Reputation: 17410
The upcase
method capitalizes the entire string, but I need to capitalize only the first letter.
Also, I need to support several popular languages, like German and Russian.
How do I do it?
Upvotes: 171
Views: 172073
Reputation: 11824
If you want to capitalize only the first character in a string in ruby, as the author requested, you should just do exactly that:
word[0] = word[0].upcase
This works for all languages and only touches the first letter of the entire string.
word = "мария"
# => "мария"
word[0] = word[0].upcase
# => "М"
word
# => "Мария"
It does not require Rails or any other libary.
Upvotes: 1
Reputation: 39695
capitalize first letter of first word of string
"kirk douglas".capitalize
#=> "Kirk douglas"
capitalize first letter of each word
In rails:
"kirk douglas".titleize
=> "Kirk Douglas"
OR
"kirk_douglas".titleize
=> "Kirk Douglas"
In ruby:
"kirk douglas".split(/ |\_|\-/).map(&:capitalize).join(" ")
#=> "Kirk Douglas"
OR
require 'active_support/core_ext'
"kirk douglas".titleize
Upvotes: 76
Reputation: 1240
My version:
class String
def upcase_first
return self if empty?
dup.tap {|s| s[0] = s[0].upcase }
end
def upcase_first!
replace upcase_first
end
end
['NASA title', 'MHz', 'sputnik'].map &:upcase_first #=> ["NASA title", "MHz", "Sputnik"]
Check also:
https://www.rubydoc.info/gems/activesupport/5.0.0.1/String%3Aupcase_first
https://www.rubydoc.info/gems/activesupport/5.0.0.1/ActiveSupport/Inflector#upcase_first-instance_method
Upvotes: 4
Reputation:
Use capitalize
. From the String documentation:
Returns a copy of str with the first character converted to uppercase and the remainder to lowercase.
"hello".capitalize #=> "Hello"
"HELLO".capitalize #=> "Hello"
"123ABC".capitalize #=> "123abc"
Upvotes: 6
Reputation: 2354
As of Active Support and Rails 5.0.0.beta4 you can use one of both methods: String#upcase_first
or ActiveSupport::Inflector#upcase_first
.
"my API is great".upcase_first #=> "My API is great"
"мария".upcase_first #=> "Мария"
"мария".upcase_first #=> "Мария"
"NASA".upcase_first #=> "NASA"
"MHz".upcase_first #=> "MHz"
"sputnik".upcase_first #=> "Sputnik"
Check "Rails 5: New upcase_first Method" for more info.
Upvotes: 26
Reputation: 1527
Well, just so we know how to capitalize only the first letter and leave the rest of them alone, because sometimes that is what is desired:
['NASA', 'MHz', 'sputnik'].collect do |word|
letters = word.split('')
letters.first.upcase!
letters.join
end
=> ["NASA", "MHz", "Sputnik"]
Calling capitalize
would result in ["Nasa", "Mhz", "Sputnik"]
.
Upvotes: 21
Reputation: 6564
It depends on which Ruby version you use:
Ruby 2.4 and higher:
It just works, as since Ruby v2.4.0 supports Unicode case mapping:
"мария".capitalize #=> Мария
Ruby 2.3 and lower:
"maria".capitalize #=> "Maria"
"мария".capitalize #=> мария
The problem is, it just doesn't do what you want it to, it outputs мария
instead of Мария
.
If you're using Rails there's an easy workaround:
"мария".mb_chars.capitalize.to_s # requires ActiveSupport::Multibyte
Otherwise, you'll have to install the unicode gem and use it like this:
require 'unicode'
Unicode::capitalize("мария") #=> Мария
Ruby 1.8:
Be sure to use the coding magic comment:
#!/usr/bin/env ruby
puts "мария".capitalize
gives invalid multibyte char (US-ASCII)
, while:
#!/usr/bin/env ruby
#coding: utf-8
puts "мария".capitalize
works without errors, but also see the "Ruby 2.3 and lower" section for real capitalization.
Upvotes: 299
Reputation: 8863
Below is another way to capitalize each word in a string. \w
doesn't match Cyrillic characters or Latin characters with diacritics but [[:word:]]
does. upcase
, downcase
, capitalize
, and swapcase
didn't apply to non-ASCII characters until Ruby 2.4.0 which was released in 2016.
"aAa-BBB ä мария _a a_a".gsub(/\w+/,&:capitalize)
=> "Aaa-Bbb ä мария _a A_a"
"aAa-BBB ä мария _a a_a".gsub(/[[:word:]]+/,&:capitalize)
=> "Aaa-Bbb Ä Мария _a A_a"
[[:word:]]
matches characters in these categories:
Ll (Letter, Lowercase)
Lu (Letter, Uppercase)
Lt (Letter, Titlecase)
Lo (Letter, Other)
Lm (Letter, Modifier)
Nd (Number, Decimal Digit)
Pc (Punctuation, Connector)
[[:word:]]
matches all 10 of the characters in the "Punctuation, Connector" (Pc
) category:
005F _ LOW LINE
203F ‿ UNDERTIE
2040 ⁀ CHARACTER TIE
2054 ⁔ INVERTED UNDERTIE
FE33 ︳ PRESENTATION FORM FOR VERTICAL LOW LINE
FE34 ︴ PRESENTATION FORM FOR VERTICAL WAVY LOW LINE
FE4D ﹍ DASHED LOW LINE
FE4E ﹎ CENTRELINE LOW LINE
FE4F ﹏ WAVY LOW LINE
FF3F _ FULLWIDTH LOW LINE
This is another way to only convert the first character of a string to uppercase:
"striNG".sub(/./,&:upcase)
=> "StriNG"
Upvotes: 2
Reputation: 2732
You can use mb_chars
. This respects umlaute:
class String
# Only capitalize first letter of a string
def capitalize_first
self[0] = self[0].mb_chars.upcase
self
end
end
Example:
"ümlaute".capitalize_first
#=> "Ümlaute"
Upvotes: 3
Reputation: 369428
Unfortunately, it is impossible for a machine to upcase/downcase/capitalize properly. It needs way too much contextual information for a computer to understand.
That's why Ruby's String
class only supports capitalization for ASCII characters, because there it's at least somewhat well-defined.
What do I mean by "contextual information"?
For example, to capitalize i
properly, you need to know which language the text is in. English, for example, has only two i
s: capital I
without a dot and small i
with a dot. But Turkish has four i
s: capital I
without a dot, capital İ
with a dot, small ı
without a dot, small i
with a dot. So, in English 'i'.upcase # => 'I'
and in Turkish 'i'.upcase # => 'İ'
. In other words: since 'i'.upcase
can return two different results, depending on the language, it is obviously impossible to correctly capitalize a word without knowing its language.
But Ruby doesn't know the language, it only knows the encoding. Therefore it is impossible to properly capitalize a string with Ruby's built-in functionality.
It gets worse: even with knowing the language, it is sometimes impossible to do capitalization properly. For example, in German, 'Maße'.upcase # => 'MASSE'
(Maße is the plural of Maß meaning measurement). However, 'Masse'.upcase # => 'MASSE'
(meaning mass). So, what is 'MASSE'.capitalize
? In other words: correctly capitalizing requires a full-blown Artificial Intelligence.
So, instead of sometimes giving the wrong answer, Ruby chooses to sometimes give no answer at all, which is why non-ASCII characters simply get ignored in downcase/upcase/capitalize operations. (Which of course also reads to wrong results, but at least it's easy to check.)
Upvotes: 20