class String
def titlecap
newstr = self.dup
do_titlecap(newstr)
end
def titlecap!
newstr = self
do_titlecap(newstr)
end
def do_titlecap(newstr)
# First character will always be upcased
newstr[0] = newstr[0].upcase
# Go through each char - when finding a space, capitalize the following char
c = 0
until c == size
if newstr[c] == " "
newstr[c+1] = newstr[c+1].upcase
end
c += 1
end
newstr
end
end
str = "edgar allan poe"
capstr = str.titlecap
puts str # edgar allan poe
puts capstr # Edgar Allan Poe
str.titlecap!
puts str # Edgar Allan Poe
Refactorings
No refactoring yet !
d
October 5, 2010, October 05, 2010 21:36, permalink
look at titleize in activesupport (either include that or take a look at the source for Inflector.titleize)
sl_bug
October 5, 2010, October 05, 2010 21:48, permalink
try this method. there is only one problem. when string have 2 or more spaces in a row, result string will have only one space.
def titlecap
self.dup.split(' ').map{|e| e.capitalize}.join(' ')
end
Bryan Thompson
October 6, 2010, October 06, 2010 01:17, permalink
Your split can be made more tolerant of spacing weirdness by using regex. I'm sure it can probably be fancied up further by not running capitalize on non-word segments.
def titlecap
self.dup.split(/\W+/).map{|e| e.capitalize}.join(' ')
end
SmackTurtle
October 6, 2010, October 06, 2010 14:12, permalink
These are great - thanks! Seems like the 'dup' part doesn't make any difference. Without it, self still isn't modified in place. Not sure how to get my bang equivalent to work with the split/map/join. Interestingly, it works the way I originally did it, so I still have some scratchmarks on my head.
Adam
October 6, 2010, October 06, 2010 17:26, permalink
class String
def titlecap
dup.titlecap!
end
def titlecap!
gsub!(/(\S+)/) { $1.capitalize }
end
end
Rick DeNatale
October 6, 2010, October 06, 2010 18:39, permalink
This can be done with gsub and gsub! just upcase any letters immediately after a \b (word break)
This code matches your test cases, but there are some potential subtleties. For example in a title in English, articles like the, an, and a are normally NOT upcased unless they are the first word.
class String
def titlecap
gsub(/\b[a-z]/) {|m| m.upcase}
end
def titlecap!
gsub!(/\b[a-z]/) {|m| m.upcase}
self
end
end
str = "edgar allan poe"
capstr = str.titlecap
str # => "edgar allan poe"
capstr # => "Edgar Allan Poe"
str # => "edgar allan poe"
str.titlecap! # => "Edgar Allan Poe"
str # => "Edgar Allan Poe"
SmackTurtle
October 7, 2010, October 07, 2010 02:00, permalink
The gsub way looks (to quote my late grandmother) slick as a gut. Thank you for contributing to my Ruby literacy. I'm having fun. :-) I appreciate your time.
Capitalizes the first letter of each word in a string... I'm a complete Ruby neophyte and am interested in comments on this: I enjoy the upcase, downcase, and capitalize built-ins, but would also like a "titlecaps" function that capitalizes the first letter of each word in a string. (Words are separated by a space.) I'm just fiddling around. Better ways to do it? More Ruby-like ways?