-2

I'm learning Ruby through Test-First-Ruby and I'm having a problem with some code I wrote for the program to translate words into pig latin. Instead of returning the translated word, I'm ending up with an empty string. Here in order are my code, the spec file to test it, and the failure/error code I get when I try to run the spec file in terminal (Mac OS 10.12, Ruby 2.5.0)

Here's the code:

def translate(string)
array = string.split(" ")
pigged_array = array.map! {|x| pigify(x)}
result = pigged_array.join(" ")
return result
end

def pigify(word)
vowels = ["a", "e", "i", "o", "u"]

  if vowels.include? word[0].downcase
    puts word + "ay"

 # two cases for "qu"
  elsif word[0..1] == "qu"
    puts word[2..-1] + "quay"
  elsif word[1..2] == "qu"
    puts word[3..-1] + word[0..2] + "ay"

# for words that start with 3 consonants
  elsif !(vowels.include? word[0]) && !(vowels.include? word[1]) && !(vowels.include? word[2])
    puts word[3..-1] + word[0..2] + "ay"

# for words that start with 2 consonants
  elsif !(vowels.include? word[0]) && !(vowels.include? word[1]) # for 2
    puts word[2..-1] + word[0..1] + "ay"

# for words that start with a single consonant
  else
    puts word[1..-1] + word[0] + "ay"
  end
end

and here's the spec file:

require "04_pig_latin"

describe "#translate" do
  it "translates a word beginning with a vowel" do
    s = translate("apple")
    expect(s).to eq("appleay")
  end

  it "translates a word beginning with a consonant" do
    s = translate("banana")
    expect(s).to eq("ananabay")
  end

  it "translates a word beginning with two consonants" do
    s = translate("cherry")
    expect(s).to eq("errychay")
  end

  it "translates two words" do
    s = translate("eat pie")
    expect(s).to eq("eatay iepay")
  end

  it "translates a word beginning with three consonants" do
    expect(translate("three")).to eq("eethray")
  end

  it "counts 'sch' as a single phoneme" do
    s = translate("school")
    expect(s).to eq("oolschay")
  end

  it "counts 'qu' as a single phoneme" do
    s = translate("quiet")
    expect(s).to eq("ietquay")
  end

  it "counts 'qu' as a consonant even when it's preceded by a consonant" do
    s = translate("square")
    expect(s).to eq("aresquay")
  end

  it "translates many words" do
    s = translate("the quick brown fox")
    expect(s).to eq("ethay ickquay ownbray oxfay")
  end

and finally, here's the message I get when I run the spec file in terminal:

#translate

appleay
  #translates a word beginning with a vowel (FAILED - 1)

Failures:

  1) #translate translates a word beginning with a vowel
     Failure/Error: expect(s).to eq("appleay")

       expected: "appleay"
            got: ""

       (compared using ==)
     # ./spec/04_pig_latin_spec.rb:29:in `block (2 levels) in <top 
(required)>'

Finished in 0.00168 seconds (files took 0.11091 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./spec/04_pig_latin_spec.rb:27 # #translate translates a word beginning with a vowel
Yowza
  • 1
  • 4
  • Sorry it wasn't clear for you, Sawa. The question was "Why am I getting an empty string instead of the translated word?" SimpleLime answered it perfectly! – Yowza Jan 24 '18 at 23:36

1 Answers1

1

Your pigify method is putsing the strings to the terminal, but not returning them to the caller. The puts method will return nil and ruby returns the result of the last evaluated line in a method. In your pigify, in each if/elsif/else branch the last line evaluated is puts, so pigify is returning nil. Then you join all the nil values together and get a long string of spaces (or, in the case of a single word string, a blank string back) as your value.

To fix this, simply remove the calls to puts in pigify and leave the strings:

def pigify(word)
  vowels = ["a", "e", "i", "o", "u"]

  if vowels.include? word[0].downcase
    word + "ay"
  # two cases for "qu"
  elsif word[0..1] == "qu"
    word[2..-1] + "quay"
  elsif word[1..2] == "qu"
    word[3..-1] + word[0..2] + "ay"
  # for words that start with 3 consonants
  elsif !(vowels.include? word[0]) && !(vowels.include? word[1]) && !(vowels.include? word[2])
    word[3..-1] + word[0..2] + "ay"
  # for words that start with 2 consonants
  elsif !(vowels.include? word[0]) && !(vowels.include? word[1]) # for 2
    word[2..-1] + word[0..1] + "ay"
  # for words that start with a single consonant
  else
    word[1..-1] + word[0] + "ay"
  end
end

Now the last line evaluated in each branch is the string being modified, so the modified string will be returned from the method.

Simple Lime
  • 10,790
  • 2
  • 17
  • 32
  • Thank you! your explanation was wonderfully clear and I totally see what you're talking about! I had forgotten that puts returns nil. – Yowza Jan 24 '18 at 06:19