Rubyist Rubyist - 1 year ago 56
Ruby Question

How to return to the calling method?

I have a program that uses a method for verification, if that verification failed I would like to return to the method it was called from, for example:

def obtain_pokemon_name
print 'Enter Pokemon: '
pokemon = gets.chomp.capitalize
obtain_basic_attack(pokemon)
end

def obtain_basic_attack(poke)
print 'Enter basic attack: '
basic_attack = gets.chomp.downcase
check_attacks(poke, basic_attack)
obtain_spec_attack(poke)
end

def obtain_spec_attack(poke)
print 'Enter special attack: '
spec_attack = gets.chomp.downcase
check_attacks(poke, spec_attack)
end

def check_attacks(pokemon, attack)
if POKEMON_ATTACKS[pokemon][attack] == nil
puts "#{attack} is not one of #{pokemon}'s attacks, try again.."
return # to where this function was called
else
attack
end
end

begin
obtain_pokemon_name
rescue => e
puts "Failed with error code: #{e}"
end


When this is run:

Enter Pokemon: arbok
Enter basic attack: eat
eat is not one of Arbok's attacks, try again..
Enter special attack: test
test is not one of Arbok's attacks, try again..


Attack list:

POKEMON_ATTACKS = {
'Bulbasaur' => {'tackle' => 10.9, 'vine whip' => 15.4, 'power whip' => 21.4, 'seed bomb' => 12.5, 'sludge bomb' => 19.2},
'Ivysaur' => {'razor leaf' => 10.3, 'vine whip' => 15.4, 'power whip' => 21.4, 'sludge bomb' => 19.2, 'solar beam' => 13.3},
'Kakuna' => {'bug bite' => 13.3, 'poison sting' => 10.3, 'struggle' => 8.8},
'Beedrill' => {'bug bite' => 13.3, 'poison jab' => 14.3, 'aerial ace' => 8.6, 'sludge bomb' => 19.2, 'x-scissor' => 14.3},
'Pidgey' => {'quick attack' => 7.5, 'tackle' => 10.9, 'aerial ace' => 8.6, 'air cutter' => 7.6, 'twister' => 5.6},
'Ekans' => {'acid' => 9.5, 'poison sting' => 10.3, 'gunk shot' => 20.0, 'sludge bomb' => 19.2, 'wrap' => 3.8},
'Arbok' => {'acid' => 9.5, 'bite' => 12.0, 'dark pulse' => 12.9, 'gunk shot' => 20.0, 'sludge wave' => 17.6},
}


So my question is, if the attack is not present in the data, how can I return back to the calling method? So for instance if I call
arbok
and his attack is
tackle
if it doesn't exist in the hash, how would I return to the
obtain_basic_attack(poke)
method?

Answer Source

RIght here:

   puts "#{attack} is not one of #{pokemon}'s attacks, try again.."
    return # to where this function was called

you should call the original method again. i.e.

  if POKEMON_ATTACKS[pokemon][attack] == nil
    puts "#{attack} is not one of #{pokemon}'s attacks, try again.."
    return obtain_spec_attack(poke)

You could alternatively add this logic to obtain_spec_attack:

def obtain_spec_attack(poke)
  loop do
    print 'Enter special attack: '
    spec_attack = gets.chomp.downcase
    attack_found = check_attacks(poke, spec_attack)
    if attack_found
      break attack_found # this will return attack_found from the loop
    else
      puts "attack not found"
   end
end

edit

looking at your question again, I realize you want to return to a method multiple levels up. You could use the approaches I've already outlined, or alternatively use rescue:

def obtain_basic_attack(poke)
  begin
    print 'Enter basic attack: '
    basic_attack = gets.chomp.downcase
    check_attacks(poke, basic_attack)
    obtain_spec_attack(poke)
  rescue AttackNotFoundError
    retry # runs the 'begin' block again
  end
end

def obtain_spec_attack(poke)
  print 'Enter special attack: '
  spec_attack = gets.chomp.downcase
  check_attacks(poke, spec_attack)
end

def check_attacks(pokemon, attack)
  if POKEMON_ATTACKS[pokemon][attack] == nil
    puts "#{attack} is not one of #{pokemon}'s attacks, try again.."
    raise AttackNotFoundError
  else
    attack
  end
end

In order to use a custom error like AttackNotFoundError, you need to define the error class somewhere:

class AttackNotFoundError < StandardError; end

You could use any error really, such as raise StandardError, but it's better to restrict what errors you're rescuing so that you don't accidentally rescue an unrelated error.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download