JEG2 / highline

A higher level command-line oriented interface.
Other
1.29k stars 137 forks source link

Issue #246 - Add custom validation class option to `Question#validate` #258

Closed abinoam closed 1 year ago

abinoam commented 1 year ago

Fix #246

Implement multiple answers in one line (one ask) by using a combination of a custom parser (already possible in previous HighLine version) and a custom validation (possible from this PR on).

As a bonus point this PR makes it possible to use Dry::Types (https://github.com/dry-rb/dry-types) as custom validation class because we followed their convention of #valid? method.

Added an example at https://github.com/JEG2/highline/blob/master/examples/custom_parser_custom_validator.rb

require 'highline'

cli = HighLine.new

# The parser
class ArrayOfNumbersFromString
  def self.parse(string)
    string.scan(/\d+/).map(&:to_i)
  end
end

# The validator
class ArrayOfNumbersFromStringInRange
  def self.in?(range)
    new(range)
  end

  attr_reader :range

  def initialize(range)
    @range = range
  end

  def valid?(answer)
    ary = ArrayOfNumbersFromString.parse(answer)
    ary.all? ->(number) { range.include? number }
  end

  def inspect
    "in range #@range validator"
  end
end

answer = cli.ask("Which number? (0 or <Enter> to skip): ", ArrayOfNumbersFromString) { |q|
  q.validate = ArrayOfNumbersFromStringInRange.in?(0..10)
  q.default = 0
}

puts "Your answer was: #{answer} and it was correctly validated and coerced into an #{answer.class}"
abinoam commented 1 year ago

Thanks @Joshfindit and @rubyFeedback