Why Does Rails Titlecase Add a Space to a Name

Why does Rails titlecase add a space to a name?

You can always do it yourself if Rails isn't good enough:

class String
    def another_titlecase
        self.split(" ").collect{|word| word[0] = word[0].upcase; word}.join(" ")
    end
end

"john mark McMillan".another_titlecase
=> "John Mark McMillan"

This method is a small fraction of a second faster than the regex solution:

My solution:

ruby-1.9.2-p136 :034 > Benchmark.ms do
ruby-1.9.2-p136 :035 > "john mark McMillan".split(" ").collect{|word|word[0] = word[0].upcase; word}.join(" ")
ruby-1.9.2-p136 :036?> end
=> 0.019311904907226562

Regex solution:

ruby-1.9.2-p136 :042 > Benchmark.ms do
ruby-1.9.2-p136 :043 > "john mark McMillan".gsub(/\b\w/) { |w| w.upcase }
ruby-1.9.2-p136 :044?> end
=> 0.04482269287109375

Why does Rails titlecase add a space to a name?

You can always do it yourself if Rails isn't good enough:

class String
    def another_titlecase
        self.split(" ").collect{|word| word[0] = word[0].upcase; word}.join(" ")
    end
end

"john mark McMillan".another_titlecase
=> "John Mark McMillan"

This method is a small fraction of a second faster than the regex solution:

My solution:

ruby-1.9.2-p136 :034 > Benchmark.ms do
ruby-1.9.2-p136 :035 > "john mark McMillan".split(" ").collect{|word|word[0] = word[0].upcase; word}.join(" ")
ruby-1.9.2-p136 :036?> end
=> 0.019311904907226562

Regex solution:

ruby-1.9.2-p136 :042 > Benchmark.ms do
ruby-1.9.2-p136 :043 > "john mark McMillan".gsub(/\b\w/) { |w| w.upcase }
ruby-1.9.2-p136 :044?> end
=> 0.04482269287109375

Converting upper-case string into title-case using Ruby

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.

Adding a space between variables

The gets.chomp method itself does not catch any spaces. You will have to add them yourself.

Another Ruby way how to do that is through the join method.

puts "So your full name is, #{[forename, middlename, surname].join(' ')}."

With David's suggestion to form a complete answer, use compact before the joining, in order to avoid empty middlename and doubling of space.

puts "So your full name is, #{[forename, middlename, surname].compact.join(' ')}."

Ruby on Rails: Converting SomeWordHere to some word here

alt text

The methods underscore and humanize are designed for conversions between tables, class/package names, etc. You are better off using your own code to do the replacement to avoid surprises. See comments.

"SomeWordHere".underscore => "some_word_here"

"SomeWordHere".underscore.humanize => "Some word here"

"SomeWordHere".underscore.humanize.downcase => "some word here"

Insert space before capital letters

You can just add a space before every uppercase character and trim off the leading and trailing spaces

s = s.replace(/([A-Z])/g, ' $1').trim()

Ruby creating title case method, can't handle words like McDuff or McComb

There are several issues with your "Mc" code:

if (word.include?("mc"))

This will always return false, because you have already capitalized word. It has to be:

if word.include?('Mc')

This line doesn't work either:

letter_array = word.split!("")

because there is no split! method, just split. There is however no reason to use a character array at all. String#[] allows you to access a string's characters (or sub-strings), so the next line becomes:

if (word[0] == 'M') && (word[1] == 'c')

or just:

if word[0, 2] == 'Mc'

or even better using start_with?:

if word.start_with?('Mc')

In fact, we can replace the first if with this one.

The next line is a bit tricky:

letter_array[2].capitalize!

Using String#[] this becomes:

word[2].capitalize!

But unfortunately, both don't work as expected. This is because [] returns a new object, so the bang method doesn't change the original object. Instead you have to call the element assignment method []=:

word[2] = word[2].upcase

Everything put together:

if word.start_with?('Mc')
word[2] = word[2].upcase
end

Or in a single line:

word[2] = word[2].upcase if word.start_with?('Mc')

Devise: Capitalize First Name

I think you should put capitalization of first and last names in your User model. Every time a user is saved, you can capitalize the first and last name. In addition, all validation (or attribute pre-processing/sanitization) can be done at the model level as well.

class User < ActiveRecord::Base
before_save :capitalize_names

def capitalize_names
self.firstname = firstname.camelcase
self.lastname = lastname.camelcase
end
end


Related Topics



Leave a reply



Submit