web-dev-qa-db-ja.com

インタラクティブなRakeタスクを作成することは可能ですか?

ユーザーに入力を求めるRakeタスクを実行したいと思います。

コマンドラインで入力を提供できることは知っていますが、ユーザーに、Rakeに提供された値の1つを誤って入力した場合に備えて、特定のアクションを続行するかどうかを尋ねたいと思いますsure仕事。

42
AKWF

このようなものがうまくいくかもしれません

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

タスクの再有効化と呼び出し元 Rakeタスク内からRakeタスクを実行する方法は?

88
ricaurte

これは、別のタスクを使用しない例です。

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
8
Kamil Sarna

ユーザー入力の便利な機能は、ユーザーが有効な入力を入力した場合にのみ続行するために、それをdo..whileループに入れることです。 Rubyにはこの構成が明示的にありませんが、beginuntilで同じことを実現できます。これにより、受け入れられる回答が次のように追加されます。

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
5
Jon Cairns

これをサービスクラスにまとめて、ユニットテストを行い、rakeタスク全体で使用できるようにすることもできます。

# 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

次に、タスクでそのように使用します。

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!
0
armchairdj