Benito Serna Tips and tools for Ruby on Rails developers

MdRecord: File-backed models for Rails

December 29, 2025

I just released md_record, a Ruby gem that provides an ActiveRecord-like interface for markdown files with YAML frontmatter.

Why?

I needed a simple way to manage content like blog posts and guides in my Rails apps without a database. I wanted something that felt like ActiveRecord but worked with markdown files.

Installation

gem "md_record"

Basic Usage

Create a model that inherits from MdRecord::Base:

class Post < MdRecord::Base
end

By default, files are loaded from app/views/posts/ (based on the model name).

Create markdown files with YAML frontmatter:

---
title: My First Post
description: A short description
published: true
published_at: 2024-12-29
position: 1
---

# Content here

Your markdown content...

Then use it like ActiveRecord:

Post.all        # All posts
Post.published  # Only published posts
Post.find(slug) # Find by slug or raise MdRecord::RecordNotFound

Custom Path

class Article < MdRecord::Base
  md_record_path "content/articles"
end

Categorized Content

For content organized in categories (like documentation or guides):

class Guide < MdRecord::Base
  include MdRecord::Categorizable

  md_record_categories(
    "getting-started" => { name: "Getting Started", position: 1 },
    "advanced" => { name: "Advanced", position: 2 }
  )
end

Files are organized in subfolders:

app/views/guides/
  getting-started/
    first-steps.md
  advanced/
    custom-config.md

Then you can use:

Guide.categories  # Returns array of MdRecord::Category objects
guide.category?("getting-started")  # Check if guide belongs to category
guide.category_name  # "Getting Started"

Rails Integration

The gem includes a Railtie that automatically maps MdRecord::RecordNotFound to a 404 response, just like ActiveRecord::RecordNotFound.

Post.find("non-existent") # raises MdRecord::RecordNotFound
# Rails returns 404

Rendering to HTML

Each record can render its markdown content to HTML:

post = Post.find("my-post")
post.to_html  # Returns HTML string

Links

Related articles

Subscribe to get future posts via email

Here I try to share knowledge and fixes to common problems and struggles for ruby on rails developers, like How to fetch the latest-N-of-each record or How to test that an specific mail was sent or a Capybara cheatsheet. You can see more examples on Most recent posts or all posts.