I've just complete a Pig Latin translator as a code kata and I was hoping someone would review it for me.Here is the kata:PigLatin Kata   Create a PigLatin class that is initialized with a string      - detail: The string is a list of words separated by spaces: 'hello world'      - detail: The string is accessed by a method named phrase      - detail: The string can be reset at any time without re-initializing      - example: PigLatin.new('hello world')completed (Y|n):   Translate Method      Create a translate method that translates the phrase from english to pig-latin.         - detail: The method will return a string.         - detail: The empty string will return nil.         - example:  translates to nilcompleted (Y|n):      Translate words that start with vowels.         - detail: Append ay to the word if it ends in a consonant.         - example: ask translates to askay         - detail: Append yay to the word if it ends with a vowel.         - example: apple translates to appleyay         - detail: Append nay to the word if it ends with y.         - example: any translates to anynaycompleted (Y|n):      Translate a word that starts with a single consonant.         - detail: Removing the consonant from the front of the word.         - detail: Add the consonant to the end of the word.         - detail: Append 'ay' to the resulting word.         - example: hello translates to ellohay         - example: world translates to orldwaycompleted (Y|n):      Translate words that start with multiple consonants.         - detail: Remove all leading consonants from the front of the word.         - detail: Add the consonants to the end of the word.         - detail: Append 'ay' to the resulting word.         - example: known translates to ownknay         - example: special translates to ecialspaycompleted (Y|n):      Support any number of words in the phrase.         - example: hello world translates to ellohay orldway         - detail: Each component of a hyphenated word is translated seperately.         - example: well-being translates to ellway-eingbaycompleted (Y|n):      Support capital letters.         - detail: If a word is captalized, the translated word should be capitalized.         - example: Bill translates to Illbay         - example: Andrew translates to Andrewaycompleted (Y|n):      Retain punctuation.         - detail: Punctuation marks should be retained from the source to the translated string         - example: fantastic! tranlates to anfasticfay!         - example: Three things: one, two, three. translates to Eethray ingsthay: oneyay, otway, eethray.completed (Y|n):Congratulations!- Create a PigLatin class that is initialized with a string                00:12:52- Create a translate method that translates the phrase from english to p   00:03:00- Translate words that start with vowels.                                  00:08:56- Translate a word that starts with a single consonant.                    00:04:32- Translate words that start with multiple consonants.                     00:08:08- Support any number of words in the phrase.                               00:25:19- Support capital letters.                                                 00:05:05- Retain punctuation.                                                      00:17:00----------------------------------------------------------------------Total Time taking PigLatin kata:                                           01:24:52And my specs:require 'spec_helper'require 'piglatin'describe PigLatin do  let(:pig_latin) { PigLatin.new(string) }  let(:string) { hello world }  describe new do    specify { expect { pig_latin }.to_not raise_error }  end  describe .phrase do    subject { pig_latin.phrase }    it { should eq(hello world) }    it can reset the phrase do      pig_latin      pig_latin.phrase = world hello      subject.should eq(world hello)    end  end  describe .translate do    subject { pig_latin.translate }    its(:class) { should eq(String) }    context empty string do      let(:string) {  }      it { should eq(nil) }    end    context words that start with vowels do      let(:string) { ask }      it { should eq(askay) }      context and also ends with a vowel do        let(:string) { apple }        it { should eq(appleyay) }      end      context and ends with y do        let(:string) { any }        it { should eq(anynay) }      end    end    context words that start with a single consonant do      let(:string) { hello }      it { should eq(ellohay) }    end    context words that start with multiple consonants do      context known do        let(:string) { known }        it { should eq(ownknay) }      end      context special do        let(:string) { special }        it { should eq(ecialspay) }      end    end    context multiple words do      let(:string) { hello world }      it { should eq(ellohay orldway) }      context hyphenated words do        let(:string) { well-being }        it { should eq(ellway-eingbay) }      end    end    context Capitalization do      context Bill do        let(:string) { Bill }        it { should eq(Illbay) }      end      context Andrew do        let(:string) { Andrew }        it { should eq(Andreway) }      end    end    context Retain Punctuation do      context fantastic! do        let(:string) { fantastic! }        it { should eq(antasticfay!) }      end      context Three things: one, two, three. do        let(:string) { Three things: one, two, three. }        it { should eq(Eethray ingsthay: oneyay, otway, eethray.) }      end    end  endendAnd, finally, the PigLatin class:class PigLatin  attr_accessor :phrase  def phrase=(string)    @phrase = string  end  alias :initialize :phrase=  def translate    return nil if (@phrase.empty?)    word_array = @phrase.split(/\s/)    word_array.collect! do |word|      translate_word(word)    end    translated_phrase = word_array.join( )    return translated_phrase  end  private  def translate_word word    words = word.split(-)    words.collect! do |word|      punctuation = word.slice!(/\W/)      if (word[0] =~ /[aeiou]/i)        case word[-1]        when /[aeiou]/          word += yay        when /y/          word += nay        else          word += ay        end      else        consonants = word.slice!(/^[^aeiou]*/)        word.capitalize! if (consonants.downcase!)        word += consonants + ay      end      if (punctuation)        word << punctuation      end      word    end    return words.join(-)  endend
Pig Latin Code Kata
ruby;rspec;pig latin
Good marks for:FormattingNamingEach spec tests just one thingCoverage of edge cases such as empty string.I think I would change the name from PigLatin to PigLatinTranslator.  I can't think of a pig latin as a thing.Was the API required by the challenge?  If not, I'd consider simplifying it.There's not much reason for the translator to have any state.  You can simplify it if the #translate method takes the string to be translated.  You won't need the accessors or the #initialize method.That #translate returns nil if the phrase is an empty string is a little surprising.  I expect it to return an empty string.Instead of splitting on white space, consider using gsub to scan for words and replace them.  If you do that, you can remove all of #translate_word's special handling of punctuation:  def translate    return nil if @phrase.empty?    @phrase.gsub(/\w+/) do |word|      translate_word(word)    end  endreturn word at the end of #translate_word can be simply word.  The only reason to use the return keyword is for a return before the end of the method.The sequence aeiou might deserve to be a constant:VOWEL = 'aeiou'  ...  if word[0] =~ /[#{VOWEL}]/i  ...    when /[#{VOWEL}]/  ...    consonants = word.slice!(/[^#{VOWEL}]*/)Handling of capitalization can be handled by, at the beginning of the function, noticing whether or not the word is capitalized, and then downcasing it:is_capitalized = word =~ /^A-Z/word = word.downcaseand at the end, capitalizing it again if needed.word = word.capitalized if is_capitalizedThis removes considerations of case from the rest of the function.Expressions like word[0] =~ /.../ can be replaced with word =~ /^.../.  Similarly, word[1] =~ /.../ can be replaced with `word =~ /...$/Taken altogether, these suggestions yield a #translate_word more like this:  def translate_word(word)    is_capitalized = word =~ /^[A-Z]/    word = word.downcase    if (word =~ /^#{VOWEL}/i)      case word      when /#{VOWEL}$/        word += yay      when /y$/        word += nay      else        word += ay      end    else      consonants = word.slice!(/^[^#{VOWEL}]*/)      word += consonants + ay    end    word = word.capitalize if is_capitalized    word  end