ruby
38 lines · 5 steps
Parsing fixed-width records in Ruby
A data-driven parser turns fixed-width text lines into typed hashes using a declarative field table.
Explained by
highlit
1module FixedWidthParser
2 FIELDS = [
3 { name: :record_type, range: 0...2 },
4 { name: :account_id, range: 2...12, type: :integer },
5 { name: :last_name, range: 12...42, type: :string },
6 { name: :first_name, range: 42...62, type: :string },
7 { name: :balance, range: 62...74, type: :cents },
8 { name: :opened_on, range: 74...82, type: :date },
9 { name: :active, range: 82...83, type: :flag }
10 ].freeze
11
12 module_function
13
14 def parse(io)
15 io.each_line.filter_map do |line|
16 next if line.strip.empty?
17 parse_line(line.chomp)
18 end
19 end
20
21 def parse_line(line)
22 FIELDS.each_with_object({}) do |field, record|
23 raw = line[field[:range]].to_s
24 record[field[:name]] = cast(raw, field[:type])
25 end
26 end
27
28 def cast(raw, type)
29 case type
30 when :integer then Integer(raw.strip, 10)
31 when :string then raw.strip
32 when :cents then Integer(raw.strip, 10) / 100.0
33 when :date then Date.strptime(raw.strip, "%Y%m%d")
34 when :flag then raw.strip == "Y"
35 else raw
36 end
37 end
38end
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1Describing structure as data lets one small engine handle every field without branching per column.
- 2Ruby ranges over strings slice fixed-width columns cleanly, and filter_map drops blanks in one pass.
- 3Centralizing type coercion in a case statement keeps parsing logic in one place and easy to extend.
Related explainers
ruby
class ToastBroadcaster include ActionView::RecordIdentifier def self.broadcast_to(user, message:, type: :notice)
How Turbo Stream toasts broadcast in Rails
turbo-streams
service-object
real-time
Intermediate
6 steps
ruby
class TemplateInterpolator PLACEHOLDER = /\{\{\s*([\w.]+)\s*\}\}/ def initialize(strict: false)
Interpolating templates with dotted keys in Ruby
regex
string-interpolation
hash-traversal
Intermediate
6 steps
ruby
class KeyTransformer def self.camelize(data) new.camelize(data) end
Recursively camelizing nested Ruby data
recursion
data-transformation
pattern-matching
Intermediate
7 steps
ruby
module Paginatable extend ActiveSupport::Concern private
A reusable pagination concern in Rails
pagination
concerns
http-headers
Intermediate
8 steps
rust
use std::net::Ipv4Addr; use std::str::FromStr; #[derive(Debug, Clone, Copy)]
Parsing and matching IPv4 CIDR ranges in Rust
bitwise-operations
parsing
error-handling
Intermediate
8 steps
ruby
class Api::MessagesController < ApiController before_action :authenticate_api_key! rate_limit to: 100,
Layered API rate limiting in Rails
rate-limiting
api-authentication
throttling
Intermediate
9 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/parsing-fixed-width-records-in-ruby-explained-ruby-dc3c/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.