ruby capitalize doesnt work for the first word of the title

the code below is to capitalize all words except for 'littleWords' and the first word of the title. (even if it belongs to the littleWords, the first word should be capitalized.)

 def titleize (word)
    littleWords = ["and", "the", "over", "or"]

    words = Array.new
    words = word.split(" ")
    titleWords = Array.new

    words.each {|word, index| 
        if index == 0
            word = word.capitalize
        else
            unless littleWords.include?(word)
                word = word.capitalize
            end
        end
        titleWords << word
    }
    return titleWords.join(" ")
end 

and test code is the below.

it "does capitalize 'little words' at the start of a title" do
    expect(titleize("the bridge over the river chao praya")).to eq("The Bridge over         the River chao praya")
  end

but it keeps to capitalize the first 'the' as just 'the' instead of 'The'. I wonder which part of my code is wrong. help me... TT


ANSWERS:


You should use each_with_index instead of each to get the index


As you can see from the documentation of Array#each, it only yields one argument to the block:

each { |item| block } → ary
#      ↑↑↑↑↑↑

However, your block takes two parameters:

words.each {|word, index| 
#           ↑↑↑↑↑↑↑↑↑↑↑↑↑

Since each only yields one argument to the block, the second parameter will always be nil. (Unless the element just happens to be an Array, then word will be bound to the first element of the array and index to the second.) And since index is always nil, it will never equal 0 and thus never enter the first branch of the conditional.

There is, however, another iteration method which actually yields two arguments to the block, the element and its index, it is called Enumerable#each_with_index:

words.each_with_index {|word, index| 
#         ↑↑↑↑↑↑↑↑↑↑↑

That's all you need to change to make your code work.


Here, another way without using each or each_with_index.

def titleize (word)
    littleWords = ["and", "the", "over", "or"]
    words = word.split(" ")
    words[0].capitalize + " " + words[1..-1].map do |w|
        littleWords.include?(w) ? w : w.capitalize
    end.join(" ")
end

You could use String#gsub with a regular expression and a block.

def titlesize(str, little_words)
  str.gsub(/[[:alpha:]]+/) { |w| little_words.include?(w) &
   (Regexp.last_match.begin(0) > 0) ? w : w.capitalize }
end

When little_words equals the array ["and", "the", "over", "of"],

titlesize "the days of wine and roses", little_words
  #=> "The Days of Wine and Roses"

See Regexp::last_match and MatchData#begin. Regexp.last_match can be replaced by the global variable $~.



 MORE:


 ? How i can Capitalize without using toUpperCase
 ? Replace all non capitalised words with ruby
 ? Capitalize ALL words in a triple String
 ? Ruby - remove underscores and capitalize
 ? How do I make the first letter of a string uppercase in JavaScript?
 ? How do I make the first letter of a string uppercase in JavaScript?
 ? How do I make the first letter of a string uppercase in JavaScript?
 ? How do I make the first letter of a string uppercase?
 ? How do I make the first letter of a string uppercase?
 ? How do I make the first letter of a string uppercase?