HighLine:ask の挙動、中身

以下のように引数は、Question に引き渡される

  def ask( question, answer_type = String, &details ) # :yields: question
    @question ||= Question.new(question, answer_type, &details)


gather への挙動

>> require "highline/import"
=> true
>> ask("foo?") { |q| q.gather = true }
=> []
>> ask("foo?") { |q| q.gather = true }
foo?
aaa
=> "aaa"

は、

class HighLine
  ...

  def ask( question, answer_type = String, &details ) # :yields: question
    @question ||= Question.new(question, answer_type, &details)
    
    return gather if @question.gather
 
  ...

  def gather(  )
    ...
    @answers          = [ ]
    ...

    @question.gather = false
    ...

    @answers
  end

から理解できた。

  • ask が呼ばれ Question.new, @question.gather は true に設定
  • gather が呼ばれ、@question.gather は false に設定、返り値は @answers に設定された []
  • ask が呼ばれ @question は既にあるので、Question.new は呼ばれず、@question.gather も true に設定されない
  • 「return gather if @question.gather」以降の通常のコードが実行される


全体の構造

  • Question.new
  • gather の処理
  • say
  • begin 〜 end で囲われた中で入力の判定。ダメな場合は例外を発生させ rescue して retry
  • gather で return しない場合以外は、ensure で @question = nil と reset


多少の疑問

  def ask( question, answer_type = String, &details ) # :yields: question
    ...
    begin
      @answer = @question.answer_or_default(get_response)
      unless @question.valid_answer?(@answer)
        explain_error(:not_valid)
        raise QuestionError
      end

なら、次の記述

      if @question.in_range?(@answer)
        ...
      else
        explain_error(:not_in_range)
        raise QuestionError
      end

はそう書かず、

      unless @question.in_range?(@answer)
        explain_error(:not_in_range)
        raise QuestionError
      end

        ...

でも良さそうな?


「if @question.in_range?(@answer)」内の @question.confirm まわりの処理が良く分からないや〜