CLAUDE.md Example for Rails and Ruby (2026)
Using Claude with Markdown documentation in Rails and Ruby applications transforms how developers approach documentation, testing, and code generation. This guide provides concrete examples of integrating Claude into your Ruby workflow, showing practical patterns you can implement immediately. Whether you are working on a greenfield Rails 7 API or maintaining a decade-old monolith, the patterns here apply directly.
Setting Up Claude for Ruby Projects
The first step involves configuring your Rails project to work effectively with Claude. Create a CLAUDE.md file in your project root. This file acts as persistent project context that Claude reads at the start of every session. It tells Claude about your Rails version, Ruby version, key dependencies, and team conventions. reducing back-and-forth and improving the accuracy of every code suggestion.
A minimal but effective CLAUDE.md for a Rails project looks like this:
Project: MyApp
Stack
- Ruby 3.3.0
- Rails 7.1
- PostgreSQL 16
- Sidekiq for background jobs
- RSpec + Factory Bot for testing
- Pundit for authorization
- Devise for authentication
Conventions
- Service objects live in app/services/
- Presenters live in app/presenters/
- Use Interactor gem for multi-step business logic
- All controllers should be thin; push logic to service objects
- Prefer named scopes over raw where clauses in controllers
Testing rules
- Minimum 80% coverage enforced in CI
- Use FactoryBot, never fixtures
- Use shared_examples for repeated behavior
- Avoid stubbing ActiveRecord. prefer database-backed tests
Off-limits
- Do not use .all without a limit or scope
- Do not call external APIs directly from controllers
Pair this with a Gemfile that includes your development tooling so Claude understands what helpers are available:
group :development, :test do
gem 'rspec-rails'
gem 'factory_bot_rails'
gem 'faker'
gem 'shoulda-matchers'
gem 'simplecov', require: false
end
group :development do
gem 'annotate' # adds schema comments to models
gem 'bullet' # detects N+1 queries
gem 'brakeman' # security scanning
end
When Claude understands your stack at session start, it generates more accurate code suggestions and documentation. It will stop recommending gems you do not use and will follow the naming conventions you have defined.
Generating Model Documentation with Claude
One of the most valuable use cases involves using Claude to document your ActiveRecord models. Instead of manually writing documentation, you can describe your models and let Claude generate comprehensive Markdown files that explain associations, validations, enums, scopes, and business rules.
app/models/user.rb
class User < ApplicationRecord
has_many :posts, dependent: :destroy
has_many :comments, dependent: :destroy
has_one :profile, dependent: :destroy
validates :email, presence: true, uniqueness: { case_sensitive: false }
validates :username, presence: true, uniqueness: true, length: { minimum: 3, maximum: 30 }
enum role: { user: 0, admin: 1, moderator: 2 }
scope :active, -> { where(active: true) }
scope :admins, -> { where(role: :admin) }
scope :recent, -> { order(created_at: :desc) }
before_save :normalize_email
private
def normalize_email
self.email = email.downcase.strip
end
end
For this model, ask Claude: “Generate full documentation for this ActiveRecord model including all associations, validations, enums, scopes, and any gotchas.” Claude will produce a Markdown document suitable for your internal wiki or a docs/models/user.md file.
Claude is also useful for reviewing models against common Rails antipatterns. Ask it to check for missing indexes on foreign keys, N+1-prone associations, or validations that should be at the database level as well.
| Claude task | What to ask |
|---|---|
| Document model | “Generate Markdown docs for this model” |
| Audit for N+1 risk | “Which associations here risk N+1 queries?” |
| Suggest indexes | “What indexes should this table have?” |
| Review validations | “Are there validations that should also be DB constraints?” |
Test-Driven Development with the TDD Skill
The tdd skill enhances your testing workflow significantly. When working on a new feature, describe the expected behavior and let Claude generate RSpec examples before you write the implementation. This forces you to think about the interface first and catches edge cases early.
Here is a realistic set of model specs for a Post model:
spec/models/post_spec.rb
RSpec.describe Post, type: :model do
describe 'associations' do
it { should belong_to(:user) }
it { should have_many(:comments).dependent(:destroy) }
it { should have_many(:taggings) }
it { should have_many(:tags).through(:taggings) }
end
describe 'validations' do
it { should validate_presence_of(:title) }
it { should validate_length_of(:title).is_at_most(200) }
it { should validate_presence_of(:body) }
it 'requires a unique slug' do
create(:post, slug: 'existing-slug')
duplicate = build(:post, slug: 'existing-slug')
expect(duplicate).not_to be_valid
expect(duplicate.errors[:slug]).to include('has already been taken')
end
end
describe 'scopes' do
describe '.published' do
it 'returns only posts with published_at in the past' do
published = create(:post, published_at: 1.day.ago)
unpublished = create(:post, published_at: nil)
scheduled = create(:post, published_at: 1.day.from_now)
expect(Post.published).to include(published)
expect(Post.published).not_to include(unpublished, scheduled)
end
end
end
describe '#reading_time' do
it 'estimates 200 words per minute' do
post = build(:post, body: ('word ' * 400).strip)
expect(post.reading_time).to eq(2)
end
end
end
The tdd skill understands Rails conventions and generates tests that follow RSpec best practices. It suggests using Factory Bot effectively, recommends shoulda-matchers for boilerplate association and validation specs, and avoids common testing antipatterns like over-mocking or testing implementation details.
For request specs and controller-level tests, ask Claude to write specs that hit the full stack including authentication and authorization checks:
spec/requests/api/v1/posts_spec.rb
RSpec.describe "Api::V1::Posts", type: :request do
let(:user) { create(:user) }
let(:headers) { auth_headers_for(user) }
describe "GET /api/v1/posts" do
it "returns paginated published posts" do
create_list(:post, 15, :published)
get "/api/v1/posts", headers: headers
expect(response).to have_http_status(:ok)
json = JSON.parse(response.body)
expect(json['data'].length).to eq(10)
expect(json['meta']['total']).to eq(15)
end
end
describe "POST /api/v1/posts" do
context "with valid params" do
it "creates a post and returns 201" do
post_params = { post: { title: "Hello", body: "World" * 10 } }
post "/api/v1/posts", params: post_params, headers: headers
expect(response).to have_http_status(:created)
end
end
context "without authentication" do
it "returns 401" do
post "/api/v1/posts", params: {}
expect(response).to have_http_status(:unauthorized)
end
end
end
end
Creating API Documentation
Rails API documentation benefits greatly from Claude’s ability to generate OpenAPI specifications from controller code. Describe your endpoints and Claude helps create comprehensive documentation:
app/controllers/api/v1/posts_controller.rb
module Api
module V1
class PostsController < ApplicationController
before_action :authenticate_user!, except: [:index, :show]
before_action :set_post, only: [:show, :update, :destroy]
before_action :authorize_post!, only: [:update, :destroy]
def index
@posts = Post.published.includes(:user, :tags).page(params[:page]).per(10)
render json: PostSerializer.new(@posts, meta: pagination_meta(@posts)).serializable_hash
end
def show
render json: PostSerializer.new(@post, include: [:user, :comments]).serializable_hash
end
def create
@post = current_user.posts.build(post_params)
if @post.save
render json: PostSerializer.new(@post).serializable_hash, status: :created
else
render json: { errors: @post.errors.full_messages }, status: :unprocessable_entity
end
end
private
def set_post
@post = Post.friendly.find(params[:id])
rescue ActiveRecord::RecordNotFound
render json: { error: "Post not found" }, status: :not_found
end
def authorize_post!
render json: { error: "Forbidden" }, status: :forbidden unless @post.user == current_user
end
def post_params
params.require(:post).permit(:title, :body, :published_at, tag_ids: [])
end
end
end
end
When you paste this controller into a Claude session and ask for OpenAPI YAML, it produces a spec covering all four endpoints, response schemas, error responses, and authentication requirements. For documentation that goes to stakeholders, use the pdf skill to generate downloadable documentation files or the docx skill to create formatted documentation for non-technical reviewers.
Database Migration Documentation
Documenting migrations helps future developers understand schema evolution. When writing migrations, include descriptive comments that explain the business reason for the change, not just the mechanical operation:
db/migrate/20260314000000_add_role_to_users.rb
class AddRoleToUsers < ActiveRecord::Migration[7.1]
# Adds role-based access control to support the moderation system
# introduced in v2.1. Replaces the boolean `admin` column with an
# integer enum that Pundit policies read via User#role.
#
# Rollback: re-adds `admin` boolean and removes `role` column.
# Data: existing admin users are backfilled to role = 1 before
# the old column is dropped.
def change
add_column :users, :role, :integer, default: 0, null: false
add_index :users, :role
reversible do |dir|
dir.up do
User.reset_column_information
User.where(admin: true).update_all(role: 1)
end
dir.down do
User.reset_column_information
User.where(role: 1).update_all(admin: true)
end
end
remove_column :users, :admin, :boolean
end
end
A few migration patterns where Claude adds the most value:
- Backfill safety: ask Claude to generate a migration that runs data backfills in batches to avoid locking large tables
- Index strategy: paste your migration and ask “what indexes are missing?”
- Reversibility audit: ask “is this migration safely reversible? What would happen on rollback?”
- Down method: ask Claude to fill in the
downmethod when you have written onlyup
Managing Project Context with Super Memory
The supermemory skill proves invaluable for maintaining project context across sessions. Store architectural decisions, coding standards, and team conventions so that every Claude session starts with full awareness of how your project is structured:
Project Conventions
Naming
- Use snake_case for methods and variables
- Use PascalCase for classes and modules
- Use SCREAMING_SNAKE_CASE for constants
- Service objects end in a verb: UserRegistrationService, OrderCancellationService
Controller Patterns
- Use service objects for any logic beyond simple CRUD
- Return meaningful HTTP status codes. never return 200 with an error in the body
- Include pagination for all collection endpoints using Kaminari
- Serializers go in app/serializers/ using jsonapi-serializer
Testing
- Minimum 80% coverage enforced in CI
- Focus on request specs for API endpoints; unit specs for models and services
- Use shared examples for policy authorization tests
- Do not test private methods directly
Background Jobs
- All jobs go through Sidekiq
- Jobs should be idempotent. safe to run twice
- Use unique jobs (sidekiq-unique-jobs) for user-triggered actions
This context persists across Claude sessions, ensuring consistent responses aligned with your project standards. When you add a new convention, update the memory and Claude will immediately follow it in the next session.
Frontend Integration Documentation
When your Rails application includes JavaScript frontend code, Claude helps maintain consistency across the stack. Document component interactions and ask Claude to review Stimulus controllers against your application’s patterns:
// javascript/controllers/post_form_controller.js
import { Controller } from "@hotwired/stimulus"
import { marked } from "marked"
import debounce from "debounce"
export default class extends Controller {
static targets = ["title", "body", "preview", "charCount", "submitBtn"]
static values = { minLength: { type: Number, default: 50 } }
connect() {
this.updatePreview = debounce(this._updatePreview.bind(this), 300)
this._validate()
}
onBodyInput() {
this.updatePreview()
this._updateCharCount()
this._validate()
}
_updatePreview() {
this.previewTarget.innerHTML = marked.parse(this.bodyTarget.value)
}
_updateCharCount() {
this.charCountTarget.textContent = `${this.bodyTarget.value.length} characters`
}
_validate() {
const valid = this.titleTarget.value.length > 0 &&
this.bodyTarget.value.length >= this.minLengthValue
this.submitBtnTarget.disabled = !valid
}
}
Claude understands Stimulus patterns and can suggest improvements to your frontend architecture. When you paste a Stimulus controller and ask “what could go wrong with this on mobile?” or “how would I add optimistic UI updates here?”, the answers are grounded in your actual stack rather than generic JavaScript advice.
Deployment and Environment Documentation
Document your deployment process using Markdown that Claude can reference. When an incident happens at 2am, clear documentation saves time. Claude can help generate runbooks from your Capistrano or Kamal configuration:
config/deploy.rb
set :application, 'myapp'
set :repo_url, '[email protected]:company/myapp.git'
set :deploy_to, '/var/www/myapp'
set :linked_files, %w[config/database.yml config/master.key .env.production]
set :linked_dirs, %w[log tmp/pids tmp/cache storage]
namespace :deploy do
after :publishing, :restart
task :restart do
on roles(:app), in: :sequence, wait: 5 do
execute :sudo, :systemctl, :restart, 'puma'
end
end
task :seed do
on roles(:db), primary: true do
within release_path do
with rails_env: fetch(:rails_env) do
execute :rake, 'db:seed'
end
end
end
end
end
Paste this into Claude with your deployment steps and ask: “Write a deployment runbook in Markdown covering normal deploys, rollback procedure, and database migration failures.” The result is a structured document you can commit to your repo under docs/deployment.md.
Practical Workflow: The Full Loop
The highest-value workflow combines all of these pieces into a repeatable loop for every new feature:
- Update
CLAUDE.mdwith any new patterns introduced by the feature - Ask Claude to generate the migration and review it for safety
- Ask Claude to generate the model with validations, associations, and scopes
- Use the tdd skill to generate RSpec examples before writing implementation
- Write the service object and ask Claude to review it against your conventions
- Paste the controller and ask Claude to generate request specs and OpenAPI docs
- Commit the updated
CLAUDE.mdalong with the feature code
This loop keeps documentation current automatically, because the conventions you add to CLAUDE.md during a feature become the context that improves the next feature.
Conclusion
Integrating Claude into your Rails and Ruby workflow dramatically improves documentation quality, testing coverage, and code consistency. The key lies in providing rich context through CLAUDE.md, maintaining conventions in the supermemory skill, and using specialized skills like tdd for testing, pdf for generated documentation, and supermemory for maintaining project knowledge. Start with one area. model documentation or test generation. and expand the workflow as your team becomes comfortable. The compound effect of consistent context means every session gets more useful over time.
Try it: Paste your error into our Error Diagnostic for an instant fix.
Related Reading
- Claude MD Example for Flutter Mobile Application
- Claude Code Code Example Generation Workflow
- Claude Code RSpec Ruby BDD Workflow Guide
Built by theluckystrike. More at zovo.one
Find the right skill → Browse 155+ skills in our Skill Finder.