I want to run a Rake task that asks the user for input.
I know that I can supply input on the command line, but I want to ask the user if they are sure they wa
A handy feature for user input is to put it in a do..while
loop, to only continue when a user has supplied valid input. Ruby doesn't explicitly have this construct, but you can achieve the same thing with begin
and until
. That would add to the accepted answer as follows:
task :action do
STDOUT.puts "I'm acting!"
end
task :check do
# Loop until the user supplies a valid option
begin
STDOUT.puts "Are you sure? (y/n)"
input = STDIN.gets.strip.downcase
end until %w(y n).include?(input)
if input == 'y'
Rake::Task["action"].reenable
Rake::Task["action"].invoke
else
# We know at this point that they've explicitly said no,
# rather than fumble the keyboard
STDOUT.puts "So sorry for the confusion"
end
end
You could also wrap this up in a service class so it can be unit-tested and used across your rake tasks:
# frozen_string_literal: true
class RakeConfirmDialog
def initialize(question)
@question = "#{question} (y/n)"
@answer = "".inquiry
end
def confirm!
prompt until (proceed? || abort?)
respond
proceed?
end
private
def prompt
STDOUT.puts @question
@answer = STDIN.gets.strip.downcase.inquiry
end
def respond
STDOUT.puts proceed? ? "Proceeding." : "Aborting."
end
def proceed?
@answer.y?
end
def abort?
@answer.n?
end
end
Then use it like so in your task:
next unless RakeConfirmDialog.new(
"About to close the Hellmouth forever. Are you sure you want 'Buffy the Vampire Slayer' to have a happy ending?"
).confirm!
Here's an example without using another task.
task :solve_earth_problems => :environment do
STDOUT.puts "This is risky. Are you sure? (y/n)"
begin
input = STDIN.gets.strip.downcase
end until %w(y n).include?(input)
if input != 'y'
STDOUT.puts "So sorry for the confusion"
return
end
# user accepted, carry on
Humanity.wipe_out!
end
Something like this might work
task :action do
STDOUT.puts "I'm acting!"
end
task :check do
STDOUT.puts "Are you sure? (y/n)"
input = STDIN.gets.strip
if input == 'y'
Rake::Task["action"].reenable
Rake::Task["action"].invoke
else
STDOUT.puts "So sorry for the confusion"
end
end
Task reenabling and invoking from How to run Rake tasks from within Rake tasks?