HiveBrain v1.2.0
Get Started
← Back to all entries
patternrubyModerate

Proper capitalization for book titles

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
booktitlesforpropercapitalization

Problem

I'm working through some exercises to sharpen my Ruby skills. The following code is how I solved this particular question. I'd like to know what other developers think of this solution. I'm self taught, which means: I'm not getting any feedback as I learn, so I just want to make sure that I'm learning the right way to do things. And I'd like to get a gauge of what professional developers think of my code.


Ranking System

[1-terrible] [2-not good] [3-ok] [4-good] [5-very good]

  • Is the answer code elegant? (score and feedback)



  • What tips can you suggest to improve the answer?



  • How's the readability of the code? (score and feedback)



  • Can you suggest a simpler and alternative answer?



Ruby

class Book
  def title
    @title
  end

  def title=(title)
  special_words = %w(and in the of a an)
  formatted_title = []

    @title = title.split.each_with_index do |w,i|
      case 
      when i == 0
        formatted_title  0 && !special_words.include?(w)
        formatted_title << w.capitalize

      when special_words.include?(w)
        formatted_title << w
      end
    end

  @title = formatted_title.join(" ")
  end
end


Rspec

```
describe Book do

before do
@book = Book.new
end

describe 'title' do
it 'should capitalize the first letter' do
@book.title = "inferno"
@book.title.should == "Inferno"
end

it 'should capitalize every word' do
@book.title = "stuart little"
@book.title.should == "Stuart Little"
end

describe 'should capitalize every word except...' do
describe 'articles' do
specify 'the' do
@book.title = "alexander the great"
@book.title.should == "Alexander the Great"
end

specify 'a' do
@book.title = "to kill a mockingbird"
@book.title.should == "To Kill a Mockingbird"
end

specify 'an' do
@book.title = "to eat an apple a day"
@book.title.should == "To Eat an Apple a Day"

Solution

Your code is readable, but it doesn't feel very "rubyish" to me. I think that's due to needing to setup and track some extra variables and track the index of the word in question -- having to case it depending on the index, etc.

It also bugs me a little bit that title= is doing so much. This is how I would have written it:

class Book
  def title
    @title
  end

  def title=(title)
    @title = titlieze(title)
  end

  private
  def titlieze(title)
    stop_words = %w(and in the of a an)
    title.capitalize.split.map{|w| stop_words.include?(w) ? w : w.capitalize}.join(' ')
  end

end


I used stop_words instead of special_words since that's a common naming scheme for search applications (ie. words you ignore when searching). I'd be tempted to move that into a constant or some other configuration, but it works fine for this.

Rspec output:

$ rspec -f d foo_spec.rb

Book
  title
    should capitalize the first letter
    should capitalize every word
    should capitalize every word except...
      conjunctions
      prepositions
      articles
        the
        a
        an
    should always capitalize...
      I
      the first word

Finished in 0.00261 seconds
9 examples, 0 failures

Code Snippets

class Book
  def title
    @title
  end

  def title=(title)
    @title = titlieze(title)
  end

  private
  def titlieze(title)
    stop_words = %w(and in the of a an)
    title.capitalize.split.map{|w| stop_words.include?(w) ? w : w.capitalize}.join(' ')
  end

end
$ rspec -f d foo_spec.rb

Book
  title
    should capitalize the first letter
    should capitalize every word
    should capitalize every word except...
      conjunctions
      prepositions
      articles
        the
        a
        an
    should always capitalize...
      I
      the first word

Finished in 0.00261 seconds
9 examples, 0 failures

Context

StackExchange Code Review Q#43331, answer score: 11

Revisions (0)

No revisions yet.