class Zizia::Parser

A generic parser.

`Parser` implementations provide a stream of `InputRecord`s, derived from an input object (`file`), through `Parser#records`. This method should be implemented efficiently for repeated access, generating records lazily if possible, and caching if appropriate.

Input validation is handled by an array of `#validators`, which are run in sequence when `#validate` (or `#validate!`) is called. Errors caught in validation are accessible via `#errors`, and inputs generating errors result in `#valid? # => false`.

A factory method `.for` is provided, and each implementation should provides a `.match?(**)` which returns `true` if the options passed indicate the parser can handle the given input. Parsers are checked for `#match?` in the reverse of load order (i.e. the most recently loaded `Parser` classes are given precedence).

@example Getting a parser for a file input

file = File.open('path/to/import/manifest.csv')

Parser.for(file: file).records

@example Validating a parser

parser = Parser.for(file: invalid_input)

parser.valid?   # => true (always true before validation)
parser.validate # => false
parser.valid?   # => false
parser.errors   # => an array of Validation::Error-like structs

parser.validate! # ValidationError

rubocop:disable Style/ClassVars

Constants

DEFAULT_VALIDATORS

Attributes

errors[R]
file[RW]

@!attribute [rw] file

@return [File]

@!attribute [rw] validators

@return [Array<Validator>]

@!attribute [r] errors

@return [Array]
validators[RW]

@!attribute [rw] file

@return [File]

@!attribute [rw] validators

@return [Array<Validator>]

@!attribute [r] errors

@return [Array]

Public Class Methods

for(file:) click to toggle source

@param file [Object]

@return [Zizia::Parser] a parser instance appropriate for

the arguments

@raise [NoParserError]

# File lib/zizia/parser.rb, line 71
def for(file:)
  klass =
    @@subclasses.find { |k| k.match?(file: file) } ||
    raise(NoParserError)

  klass.new(file: file)
end
match?(**_opts) click to toggle source

@abstract @return [Boolean]

# File lib/zizia/parser.rb, line 82
def match?(**_opts); end
new(file:, **_opts) { |self| ... } click to toggle source

@param file [File]

# File lib/zizia/parser.rb, line 55
def initialize(file:, **_opts)
  self.file     = file
  @errors       = []
  @validators ||= self.class::DEFAULT_VALIDATORS

  yield self if block_given?
end

Private Class Methods

inherited(subclass) click to toggle source

@private Register a new class when inherited

Calls superclass method
# File lib/zizia/parser.rb, line 88
def inherited(subclass)
  @@subclasses.unshift subclass
  super
end

Public Instance Methods

records() click to toggle source

@abstract

@yield [record] gives each record in the file to the block @yieldparam record [ImportRecord]

@return [Enumerable<ImportRecord>]

# File lib/zizia/parser.rb, line 101
def records
  raise NotImplementedError
end
valid?() click to toggle source

@return [Boolean] true if the file input is valid

# File lib/zizia/parser.rb, line 107
def valid?
  errors.empty?
end
validate() click to toggle source

@return [Boolean] true if the file input is valid

# File lib/zizia/parser.rb, line 113
def validate
  validators.each_with_object(errors) do |validator, errs|
    errs.concat(validator.validate(parser: self))
  end

  valid?
end
validate!() click to toggle source

@return [true] always true, unless an error is raised.

@raise [ValidationError] if the file to parse is invalid

# File lib/zizia/parser.rb, line 125
def validate!
  validate || raise(ValidationError)
end