ruby
44 lines · 8 steps
Parsing YAML front matter in Ruby
A small class that splits a document's leading YAML block from its body and exposes the metadata as symbol keys.
Explained by
highlit
1require "yaml"
2
3class FrontMatter
4 DELIMITER = /\A---\s*\n(.*?)\n---\s*\n?(.*)\z/m
5
6 attr_reader :metadata, :body
7
8 def self.parse(source)
9 new(source).tap(&:parse)
10 end
11
12 def initialize(source)
13 @source = source.to_s
14 @metadata = {}
15 @body = @source
16 end
17
18 def parse
19 match = @source.match(DELIMITER)
20 return self unless match
21
22 raw_yaml, @body = match.captures
23 @metadata = symbolize(YAML.safe_load(raw_yaml, permitted_classes: [Date, Time]) || {})
24 self
25 rescue Psych::SyntaxError => e
26 raise ArgumentError, "Invalid front matter: #{e.message}"
27 end
28
29 def [](key)
30 @metadata[key.to_sym]
31 end
32
33 def to_h
34 { metadata: @metadata, body: @body }
35 end
36
37 private
38
39 def symbolize(hash)
40 hash.each_with_object({}) do |(key, value), acc|
41 acc[key.to_sym] = value.is_a?(Hash) ? symbolize(value) : value
42 end
43 end
44end
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1A single multiline regex with captures can cleanly separate a structured header from free-form content.
- 2Wrapping a class-level factory around instance setup keeps callers to one tidy entry point.
- 3Recursing into nested hashes lets you normalize keys all the way down, not just at the top level.
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
java
import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map;
Building a trie for autocomplete in Java
trie
prefix-tree
recursion
Intermediate
8 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
go
package config import ( "fmt"
A thread-safe config singleton in Go
singleton
concurrency
environment-variables
Intermediate
7 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-yaml-front-matter-in-ruby-explained-ruby-66ae/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.