41

I have a rake task that is called from another rake task.

In this rake task I need to ask the user for some text input, and then, depending on the answer either continue, or stop everything from continuing (including the calling rake task).

How can I do this?

Neil Middleton
  • 22,105
  • 18
  • 80
  • 134

4 Answers4

62
task :input_test do
  input = ''
  STDOUT.puts "What is the airspeed velocity of a swallow?"
  input = STDIN.gets.chomp
  raise "bah, humbug!" unless input == "an african or european swallow?"
end
task :blah_blah => :input_test do 
end

i think that should work

loosecannon
  • 7,683
  • 3
  • 32
  • 43
  • 1
    pls use STDIN.gets.chomp, to truncate the new line character.. for an exact string match.. – boddhisattva Jun 08 '12 at 13:10
  • 1
    @kaiser , just decide what to do with a if/then/else or unless or even a case type of control structure. In this case I'm raising an exception ( to stop execution as in OP's question ) but you can do anything with the input just change the question to be clear you want a yes no in it, one of the other answers does this i think – loosecannon Dec 10 '12 at 22:25
  • Thanks. I'm already doing a Ruby course on CodCademy. I'm just too much PHP for `elsif` and `unless`... :P – kaiser Dec 11 '12 at 00:10
  • any idea when this code would show "^M" when the enter key is pressed after typing "no" ?? – Chris Hough Jun 15 '14 at 00:33
11
task :ask_question do
  puts "Do you want to go through with the task(Y/N)?"
  get_input
end

task :continue do
  puts "Task starting..."
  # the task is executed here
end

def get_input
  STDOUT.flush
  input = STDIN.gets.chomp
  case input.upcase
  when "Y"
    puts "going through with the task.."
    Rake::Task['continue'].invoke
  when "N"
    puts "aborting the task.."
  else
    puts "Please enter Y or N"
    get_input
  end
end 
rubyprince
  • 17,559
  • 11
  • 64
  • 104
8

The HighLine gem makes this easy.

For a simple yes or no question you can use agree:

require "highline/import"
task :agree do
  if agree("Shall we continue? ( yes or no )")
    puts "Ok, lets go"
  else
    puts "Exiting"
  end
end

If you want to do something more complex use ask:

require "highline/import"
task :ask do
  answer = ask("Go left or right?") { |q|
    q.default   = "left"
    q.validate  = /^(left|right)$/i
  }
  if answer.match(/^right$/i)
    puts "Going to the right"
  else
    puts "Going to the left"
  end
end

Here's the gem's description:

A HighLine object is a "high-level line oriented" shell over an input and an output stream. HighLine simplifies common console interaction, effectively replacing puts() and gets(). User code can simply specify the question to ask and any details about user interaction, then leave the rest of the work to HighLine. When HighLine.ask() returns, you‘ll have the answer you requested, even if HighLine had to ask many times, validate results, perform range checking, convert types, etc.

For more information you can read the docs.

mcls
  • 9,071
  • 2
  • 29
  • 28
5

Although the question is quite old, this might still be an interesting (and perhaps little known) alternative for simple prompting without an external gem:

require 'rubygems/user_interaction'
include Gem::UserInteraction

task :input_test do
  input = ask("What is the airspeed velocity of a swallow?")
  raise "bah, humbug!" unless input == "an african or european swallow?"
end
task :blah_blah => :input_test do 
end
zor-el
  • 320
  • 2
  • 11