Class: Reading::Parsing::CSV
Overview
Validates a path or lines (string, file, etc.) of a CSV reading log, then parses it into an array of Items.
Parsing happens in two steps:
(1) Parse a row string into an intermediate hash representing the columns.
- See parsing/parser.rb, which uses parsing/rows/*
(2) Transform the intermediate hash into an array of hashes structured
around item attributes rather than CSV columns.
- See parsing/transformer.rb, which uses parsing/attributes/*
Keeping these steps separate makes the code easier to understand. It was inspired by the Parslet gem: kschiess.github.io/parslet/transform.html
Instance Method Summary collapse
-
#initialize(path: nil, lines: nil, config: nil, hash_output: false, item_view: Item::View, error_handler: nil) ⇒ CSV
constructor
Validates a path or lines (string, file, etc.) of a CSV reading log, builds the config, and initializes the parser and transformer.
-
#parse ⇒ Array<Item>
Parses and transforms the reading log into item data.
Constructor Details
#initialize(path: nil, lines: nil, config: nil, hash_output: false, item_view: Item::View, error_handler: nil) ⇒ CSV
Validates a path or lines (string, file, etc.) of a CSV reading log, builds the config, and initializes the parser and transformer.
39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/reading/parsing/csv.rb', line 39 def initialize(path: nil, lines: nil, config: nil, hash_output: false, item_view: Item::View, error_handler: nil) validate_path_or_lines(path, lines) Config.build(config) if config @path = path @lines = lines @hash_output = hash_output @item_view = item_view @parser = Parser.new @transformer = Transformer.new @error_handler = error_handler @pastel = Pastel.new end |
Instance Method Details
#parse ⇒ Array<Item>
Parses and transforms the reading log into item data.
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/reading/parsing/csv.rb', line 59 def parse input = @lines || File.open(@path) items = [] input.each_line do |line| begin intermediate = parser.parse_row_to_intermediate_hash(line) next if intermediate.empty? # When the row is blank or a comment. row_items = transformer.transform_intermediate_hash_to_item_hashes(intermediate) rescue Reading::Error => e colored_e = e.class.new("#{pastel.bright_red(e.)} in the row #{pastel.bright_yellow(line.chomp)}") if error_handler error_handler.call(colored_e) next else raise colored_e end end items += row_items end if hash_output items else items.map { |item_hash| Item.new(item_hash, view: item_view) } end ensure input&.close if input.respond_to?(:close) end |