0

So it's apparent this question has been asked before, but what I'm actually asking is specific to the code I am writing. Basically I'm capitalizing the words (titleizing). My method is not optimized, and it does go in circles so just bear with me. I can't seem to recapitalize the first word of the title once I made it lowercased again. I have written comments in the code, so you can just breeze through it without analyzing the entire thing. I'm not asking you to write a new code because I can just google that. I'm more interested in why my solutions aren't working..

input: "the hamster and the mouse"
output: "the Hamster and the Mouse"
WHAT I WANT: "The Hamster and the Mouse"


class String
  def titleize
    #regex reads: either beginning of string or whitespace followed by alpha
    self.gsub(/(\A|\s)[a-z]/) do |letter|
      letter.upcase!
    end
  end
end

class Book
  attr_accessor :title

  def title=(title)
    @title = title.titleize #makes every word capitalized

    small_words = %w[In The And A An Of]
    words = @title.split(" ")

    #makes all the "small_words" uncapitalized again

    words.each do |word|
      if small_words.include?(word)
        word.downcase!
      end
    end

    words[0][0].upcase! #doesnt work
    @title = words.join(" ")

    #NEED TO MAKE FIRST WORD CAPITALIZED EVEN IF ITS A "small_word"
    @title[0].upcase! #also doesnt work

  end

end

b4hand
  • 9,550
  • 4
  • 44
  • 49
Jeff
  • 650
  • 5
  • 16
  • 1
    words[0][0] is returning the first letter of the first word in the array, but upcase! is only affecting the returned value from words[0][0] -- it is not changing words[0]. Try words[0][0] = words[0][0].upcase. words[0].upcase! would change words, but words[0][0].upcase! does not. – Joseph May 16 '15 at 01:08
  • I could have sworn I tried this but this method worked! I think what I did earlier was words[0][0] = words[0][0].upcase!. I guess the ! was the issue. I dont need to call ! if I am not changing it in place do I? – Jeff May 16 '15 at 01:20
  • With this approach it doesn't really matter if you use the ! or not, but it isn't necessary. as you are re-assigning a value (words[0][0] to words[0][0].upcase). The difference between words[0] and words[0][0] is that words[0] references an array element which happens to be a string and can thus be changed with upcase!. words[0][0] references a string, but it is not an array element in words. words[0] is calling the index of an array, which returns a string. words[0][0] is calling the index of a string and returning a new string that is not associated with the array element. – Joseph May 16 '15 at 01:26

2 Answers2

1

Replace words[0][0].upcase! with words[0] = words[0].titleize. This will titleize the first word in the title, which is what you want.

You also don't need @title[0].upcase!.

steve klein
  • 2,566
  • 1
  • 14
  • 27
0

Change the last line from:

@title[0].upcase!

To:

@title.capitalize!

EDIT: I rewrote the class. Fewer lines and you don't need RegEx or String#titleize method.

class Book
    attr_reader :title

    def title=(title)
        small_words = ["in", "the", "and", "a", "an", "of"]

        @title = title.split.each do |word|
            small_words.include?(word.downcase) ? word.downcase! : word.capitalize!
        end

        @title[0].capitalize!
        @title = @title.join(" ")
    end
end

new_book = Book.new
new_book.title="the hamster and the mouse"
new_book.title # => "The Hamster and the Mouse"
  • I do not think that this method would work. If I call capitalize on the title again, wouldn't that just re-capitalize all the words I just made into lowercase? – Jeff May 16 '15 at 01:24
  • Nope. It wouldn't recapitalize all words. [capitalize](http://ruby-doc.org/core-2.2.0/String.html#method-i-capitalize) method capitalizes only the first letter of the first word. Anyway, I edited with a completely different solution which cuts down lines of code significantly. It's much shorter and it returns your desired outcome – Edgar Mkaka Joel May 16 '15 at 02:21
  • Sorry, Im quite new to this. Doesnt reader only allow you to read the title? You need accessor to be able to .capitalize! or .join it, dont you? – Jeff May 16 '15 at 17:14
  • That's quite alright @Jeff . `attr_accessor` reads & writes. `attr_reader` reads only. `attr_writer` writes only. In this case, `attr_accessor` is not needed because we already have a setter/writer method: `def title=(title) ... end`. Here's a great answer about accessor methods with good examples: [What is attr_accessor in Ruby?](http://stackoverflow.com/questions/4370960/what-is-attr-accessor-in-ruby/4371458#4371458) – Edgar Mkaka Joel May 16 '15 at 18:58