Q:

How to display dynamic case statement in Ruby

How would I write a case statement that would list all elements in an array, allow the user to pick one, and do processing on that element?
I have an array:
array = [ 'a', 'b', 'c', 'd' ]

Ultimately I'd like it to behave like this:
Choices:
1) a
2) b
3) c
4) d

Choice => 

After the user picks 3, I would then do processing based off the choice of the user. I can do it in bash pretty easily.

A:

Ruby has no built-in menu stuff like shell scripting languages do.  When doing menus, I favor constructing a hash of possible options and operating on that:
def array_to_menu_hash arr
  Hash[arr.each_with_index.map { |e, i| [i+1, e] }]
end

def print_menu menu_hash
  puts 'Choices:'
  menu_hash.each { |k,v| puts "#{k}) #{v}" }
  puts
end

def get_user_menu_choice menu_hash
  print 'Choice => '
  number = STDIN.gets.strip.to_i
  menu_hash.fetch(number, nil)
end

def show_menu menu_hash
  print_menu menu_hash
  get_user_menu_choice menu_hash
end

def user_menu_choice choice_array
  until choice = show_menu(array_to_menu_hash(choice_array)); end
  choice
end

array = %w{a b c d}
choice = user_menu_choice(array)

puts "User choice was #{choice}"

The magic happens in array_to_menu_hash:
The [] method of Hash converts an array with the form [ [1, 2], [3, 4] ] to a hash {1 => 2, 3 => 4}. To get this array, we first call each_with_index on the original menu choice array.  This returns an Enumerator that emits [element, index_number] when iterated.  There are two problems with this Enumerator: the first is that Hash[] needs an array, not an Enumerator.  The second is that the arrays emitted by the Enumerator have the elements in the wrong order (we need [index_number, element]).  Both of these problems are solved with #map.  This converts the Enumerator from each_with_index into an array of arrays, and the block given to it allows us to alter the result.  In this case, we are adding one to the zero-based index and reversing the order of the sub-arrays.

