Ruby Ruby Blocks Ruby Blocks Calling Blocks

Problem with a code I wrote

this is a code I created based on the video course about blocks on the ruby tracks, here are the code, and the outputs..

My code:

def get_name(prompt, &block)
  print prompt + ": "
  name = gets.chomp
  print "age: "
  age = gets.chomp
  #block.call(nam,ag)
  yield name, age
  yield age
  name
end

my_name = get_name("enter your name") do |name, age|
  puts "That's a cool name, #{name}, #{age}"
end

my_name2 = get_name("enter your age") do |age|
  puts "That's a cool age, #{age}"
end

puts "my_name: #{my_name} #{my_name2}"

My Output:

treehouse:~/workspace$ ruby calling_blocks.rb                                                                             
enter your name: ahmed                                                                                                    
age: 25                                                                                                                   
That's a cool name, ahmed, 25                                                                                             
That's a cool name, 25,                                                                                                   
enter your age: 25                                                                                                        
age: 25                                                                                                                   
That's a cool age, 25                                                                                                     
That's a cool age, 25                                                                                                     
my_name: ahmed 25  

the problem with that code is that when tracing it, I find the output irrelevant, here's what I think must be happened:

1- the first get_name block sent a prompt with question "enter your name", and then the method get_name first print the phrase "enter your name" which comes as parameter called prompt, then the method takes the name as input and takes the age as input

2- the first yield "yield name,age" send back to the first get_name block the name and age, which got received in the block through |name, age| , then they both got displayed in
puts "That's a cool name, #{name}, #{age}" as this That's a cool name, ahmed, 25

3- the second yield "yield age" send back to the first get_name block the age only this time, which got received in the block through |name, age|, this time since we sent back to the block only one argument, while the block has two parameters, this time the name parameter on the block received the age argument coming from "yield name", while the age parameter on the block received nothing, so in the block, the #{name} only displays value while the #{age} displays nothing puts "That's a cool name, #{name}, #{age}" as this That's a cool name, 25,

is my tracing true ? because if it's true why in the second get_name block, which is my_name2 = get_name("enter your age") do |age| puts "That's a cool age, #{age}" end

the output was:

That's a cool age, 25
That's a cool age, 25

instead of:

That's a cool age, ahmed
That's a cool age, 25

another question:

why the value of #{my_name2} = 25, not = ahmed, knowing that the last line in the get_name method, I returns name, not age ?


( SHORT VERSION OF THIS QUESTION ) please trace my code for me, tell me what exactly's happening ?

2 Answers

Jay McGavren
STAFF
Jay McGavren
Treehouse Teacher

I'm confused as well. I think a big part of the problem is that you're trying to make your method do more than one thing. This isn't a problem with Ruby syntax, it's a problem for yourself and other human beings who are trying to understand what your method does. A method named get_name should not do anything with ages, it should only work with names.

If you want a method that passes both inputs to a block, then your method name should reflect what the method does. The method doesn't need to know that it's working with a name or an age, just some input and a block. So a name like get_input might work. How about this?

def get_input(prompt)
  print "#{prompt}: "
  input = gets.chomp
  yield input
  return input
end

# Notice that we're storing the return value!
name = get_input("Enter your name") do |input|
  puts "That's a cool name, #{input}"
end

get_input("Enter your age") do |input|
  # We use the return value from above here!
  puts "#{input} is a cool age, #{name}"
end
Jay McGavren
Jay McGavren
Treehouse Teacher

By the way, get_input should really either return a value or pass a value to block, not both. Again, it works in Ruby, it's just another point of confusion for developers.

Thanks Jay, and sorry for confusing, I'm just trying to figure out how things work :)

Jay McGavren
Jay McGavren
Treehouse Teacher

It's good that you're experimenting! This is how developers get started. :)