Search code examples
rubymethodscapitalizationcapitalize

Creating a modified capitalize method in Ruby from scratch


I am learning methods in Ruby and thought that the best way to learn them was to create a method that already exists. However, there are two problems that I am running in to:

  1. I do not know what the capitalize method looks like
  2. My solution (it does more than the original method does) seems like it can be refactored into something more elegant.

This is what I have come up with:

# method that capitalizes a word
def new_capitalize(string)
  if string[0].downcase == "m" && string[1].downcase == "c"
    puts "#{string[0].upcase}#{string[1].downcase}#{string[2].upcase}#{string[3..-1].downcase}"
  else
    puts "#{string[0].upcase}#{string[1..-1].downcase}"
  end
end

name1 = "ryan"
name2 = "jane"

new_capitalize(name1) # prints "Ryan"
new_capitalize(name2) # prints "Jane"

str = "mCnealy"
puts str.capitalize 
       # prints "Mcnealy"

new_capitalize(str) 
       # prints "McNealy"

It seems as if the first part of my if statement could be made much more efficient. It does not need to be even close to my solution as long as it prints the second capital if the name begins with "mc"

Also, if someone could point me to where the built in capitalize method's code could be found that would be great too!

Thank you in advance!


Solution

  • Alright, how about:

    module NameRules
      refine String do
        def capitalize
          if self[0..1].downcase == 'mc'
            "Mc#{self[2..-1].capitalize}"
          else
            super
          end
        end
      end
    end
    

    Then to use it:

    class ThingWithNames
      using NameRules
    
      def self.test(string)
       string.capitalize
      end
    end
    
    ThingWithNames.test('mclemon') # => "McLemon"
    ThingWithNames.test('lemon') # => "Lemon"
    

    If we were starting from scratch and not using the C implemented code:

    module NameRules
      refine String do
        def capitalize
          if self[0..1].downcase == 'mc'
            "Mc#{self[2..-1].capitalize}"
          else
            new_string = self.downcase
            new_string[0] = new_string[0].upcase
            new_string
          end
        end
      end
    end
    

    Reference materials:

    String#capitalize source
    A really good presentation on refinements