Class: Zizia::Parser

Inherits:
Object
  • Object
show all
Defined in:
lib/zizia/parser.rb

Overview

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).

rubocop:disable Style/ClassVars

Examples:

Getting a parser for a file input

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

Parser.for(file: file).records

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

Direct Known Subclasses

FakeParser, CsvParser

Defined Under Namespace

Classes: NoParserError, ValidationError

Constant Summary collapse

DEFAULT_VALIDATORS =
[].freeze
@@subclasses =
[]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(file:, **_opts) {|_self| ... } ⇒ Parser

Returns a new instance of Parser.

Parameters:

  • file (File)

Yields:

  • (_self)

Yield Parameters:

  • _self (Zizia::Parser)

    the object that the method was called on



55
56
57
58
59
60
61
# 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

Instance Attribute Details

#errorsArray (readonly)

Returns:

  • (Array)


50
# File 'lib/zizia/parser.rb', line 50

attr_accessor :file, :validators

#fileFile

Returns:

  • (File)


50
51
52
# File 'lib/zizia/parser.rb', line 50

def file
  @file
end

#validatorsArray<Validator>

Returns:



50
# File 'lib/zizia/parser.rb', line 50

attr_accessor :file, :validators

Class Method Details

.for(file:) ⇒ Zizia::Parser

Returns a parser instance appropriate for the arguments.

Parameters:

  • file (Object)

Returns:

  • (Zizia::Parser)

    a parser instance appropriate for the arguments

Raises:



71
72
73
74
75
76
77
# 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) ⇒ Boolean

This method is abstract.

Returns:

  • (Boolean)


82
# File 'lib/zizia/parser.rb', line 82

def match?(**_opts); end

Instance Method Details

#records {|record| ... } ⇒ Enumerable<ImportRecord>

This method is abstract.

Yields:

  • (record)

    gives each record in the file to the block

Yield Parameters:

  • record (ImportRecord)

Returns:

  • (Enumerable<ImportRecord>)

Raises:

  • (NotImplementedError)


101
102
103
# File 'lib/zizia/parser.rb', line 101

def records
  raise NotImplementedError
end

#valid?Boolean

Returns true if the file input is valid.

Returns:

  • (Boolean)

    true if the file input is valid



107
108
109
# File 'lib/zizia/parser.rb', line 107

def valid?
  errors.empty?
end

#validateBoolean

Returns true if the file input is valid.

Returns:

  • (Boolean)

    true if the file input is valid



113
114
115
116
117
118
119
# 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!true

Returns always true, unless an error is raised.

Returns:

  • (true)

    always true, unless an error is raised.

Raises:



125
126
127
# File 'lib/zizia/parser.rb', line 125

def validate!
  validate || raise(ValidationError)
end