Search code examples
rubystringvariablesmenuhighline

How can we set a variable after the user chooses from a HighLine menu in Ruby?


The HighLine documentation shows that we can display a string after the user selects an option from the list, like follows:

choose do |menu|
  menu.prompt = "Please choose your favorite programming language?  "

  menu.choice(:ruby) { say("Good choice!") }
  menu.choices(:python, :perl) { say("Not from around here, are you?") }
end

How can we set a variable in addition to (or in place of) showing text? Replacing say("Good choice!") with variable = 1 did not work and instead returned an "undefined local variable or method" error.


Solution

  • Local variables are destroyed when a method/block/proc finishes executing. But, you can make it so that variable is not a local variable of the block:

    variable = nil
    
    choose do |menu|
      variable = 1
      menu.prompt = "Please choose your favorite programming language?  "
    
      menu.choice(:ruby) { say("Good choice!") }
      menu.choices(:python, :perl) { say("Not from around here, are you?") }
    end
    
    puts variable
    

    A block creates what's called a closure, which means that it can see the variables that were in existence outside the block when the block was CREATED. On the other hand, a block cannot see the variables outside the block at the time it is EXECUTED--even if the variables have the same names as the variables the block can see. For instance,

    def do_stuff(&block)
      x = 1
      block.call
    end
    
    x = 10
    do_stuff {puts x}
    
    --output:--
    10