RepoPilotOpen in app →

ctran/annotate_models

Annotate Rails classes with schema and routes info

Mixed

Stale — last commit 2y ago

worst of 4 axes
Use as dependencyConcerns

non-standard license (Other); last commit was 2y ago

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • 31+ active contributors
  • Distributed ownership (top contributor 22% of recent commits)
  • Other licensed
Show 4 more →
  • CI configured
  • Tests present
  • Stale — last commit 2y ago
  • Non-standard license (Other) — review terms
What would change the summary?
  • Use as dependency ConcernsMixed if: clarify license terms

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Forkable" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Forkable
[![RepoPilot: Forkable](https://repopilot.app/api/badge/ctran/annotate_models?axis=fork)](https://repopilot.app/r/ctran/annotate_models)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/ctran/annotate_models on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: ctran/annotate_models

Generated by RepoPilot · 2026-05-10 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/ctran/annotate_models shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

WAIT — Stale — last commit 2y ago

  • 31+ active contributors
  • Distributed ownership (top contributor 22% of recent commits)
  • Other licensed
  • CI configured
  • Tests present
  • ⚠ Stale — last commit 2y ago
  • ⚠ Non-standard license (Other) — review terms

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live ctran/annotate_models repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/ctran/annotate_models.

What it runs against: a local clone of ctran/annotate_models — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in ctran/annotate_models | Confirms the artifact applies here, not a fork | | 2 | License is still Other | Catches relicense before you depend on it | | 3 | Default branch develop exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 672 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>ctran/annotate_models</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of ctran/annotate_models. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/ctran/annotate_models.git
#   cd annotate_models
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of ctran/annotate_models and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "ctran/annotate_models(\\.git)?\\b" \\
  && ok "origin remote is ctran/annotate_models" \\
  || miss "origin remote is not ctran/annotate_models (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(Other)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"Other\"" package.json 2>/dev/null) \\
  && ok "license is Other" \\
  || miss "license drift — was Other at generation time"

# 3. Default branch
git rev-parse --verify develop >/dev/null 2>&1 \\
  && ok "default branch develop exists" \\
  || miss "default branch develop no longer exists"

# 4. Critical files exist
test -f "lib/annotate.rb" \\
  && ok "lib/annotate.rb" \\
  || miss "missing critical file: lib/annotate.rb"
test -f "lib/annotate/annotate_models.rb" \\
  && ok "lib/annotate/annotate_models.rb" \\
  || miss "missing critical file: lib/annotate/annotate_models.rb"
test -f "lib/annotate/annotate_routes.rb" \\
  && ok "lib/annotate/annotate_routes.rb" \\
  || miss "missing critical file: lib/annotate/annotate_routes.rb"
test -f "lib/annotate/parser.rb" \\
  && ok "lib/annotate/parser.rb" \\
  || miss "missing critical file: lib/annotate/parser.rb"
test -f "lib/annotate/tasks.rb" \\
  && ok "lib/annotate/tasks.rb" \\
  || miss "missing critical file: lib/annotate/tasks.rb"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 672 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~642d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/ctran/annotate_models"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

Annotate is a Ruby gem that automatically parses Rails database schemas and route definitions, then injects detailed comment blocks into model files, test factories, and routes.rb. It solves the problem of schema documentation drift by keeping inline comments synchronized with the actual database structure and Rails routing configuration. Single-gem monolith structure: lib/annotate/ contains the core engine with two primary modules—annotate_models/ for schema parsing and annotate_routes/ for route extraction. bin/annotate is the CLI entry point, lib/generators/annotate/ provides Rails generator integration (auto_annotate_models.rake template), and spec/ mirrors lib/ for test organization. Active Record is patched via lib/annotate/active_record_patch.rb to hook into Rails' schema introspection.

👥Who it's for

Rails developers and teams who want to maintain accurate, auto-generated documentation of their database schema directly in their model classes and routes without manual upkeep. Particularly useful for developers context-switching between models and needing quick reference of columns, types, and constraints.

🌱Maturity & risk

Production-ready and actively maintained. The project has substantial Ruby codebase (~259KB), comprehensive GitHub Actions CI/CD pipelines (ci.yml, codeql-analysis.yml, release automation), semantic versioning (CHANGELOG.md, RELEASE.md), and extensive test coverage under spec/. Recent activity visible in release-drafter and automated workflows indicates ongoing maintenance.

Low risk for core functionality but moderate risk from gem ecosystem fragility: single maintainer (ctran), no visible dependency lock file in provided file list, and relies on introspection of Rails and ActiveRecord internals which can break across major Rails versions. The 3.x breaking changes documented in README (models not annotated by default in #647) suggest migration friction for users upgrading.

Active areas of work

The project is in active maintenance mode with established release automation (release-drafter.yml, release.yml workflows). Version bumping and changelog management are automated. No specific feature branches visible in provided data, suggesting focus is on stability and compatibility with latest Rails versions rather than major new features.

🚀Get running

git clone https://github.com/ctran/annotate_models.git
cd annotate_models
bundle install
bundle exec rspec spec/

Daily commands:

bundle exec annotate --models
bundle exec annotate --routes
bundle exec rake annotate_models

Or in a Rails app after rails g annotate:install, auto-runs via Rake tasks on migrate hooks.

🗺️Map of the codebase

  • lib/annotate.rb — Main entry point that orchestrates the annotate gem and loads all core modules.
  • lib/annotate/annotate_models.rb — Core logic for parsing ActiveRecord models and generating schema annotations.
  • lib/annotate/annotate_routes.rb — Handles parsing and annotation of Rails routes.rb files with route information.
  • lib/annotate/parser.rb — Parses existing annotations and model files to detect and manage schema comments.
  • lib/annotate/tasks.rb — Rake task integration that provides the CLI interface for running annotations.
  • lib/generators/annotate/install_generator.rb — Rails generator that installs annotate and configures auto-annotation hooks.

🧩Components & responsibilities

  • annotate_models.rb (ActiveRecord, Regex, File I/O) — Introspects ActiveRecord models, generates schema comments, handles file I/O for model updates
    • Failure mode: Fails if database is unreachable, models have invalid syntax, or file permissions are insufficient
  • annotate_routes.rb (Rails Router introspection, Regex, File I/O) — Parses routes.rb, generates route documentation, manages route annotations
    • Failure mode: Fails if routes.rb is missing, malformed, or file cannot be written
  • parser.rb (Regex pattern matching) — Detects existing annotations in files, extracts boundaries, manages comment block lifecycle
    • Failure mode: May lose annotations if comment format deviates; cannot recover from malformed existing blocks
  • tasks.rb (Rake, OptionParser) — Orchestrates annotation engines, parses CLI options, manages Rake task execution
    • Failure mode: Invalid options or missing Rails environment will cause graceful error messages

🔀Data flow

  • Rails application modelsActiveRecord schema introspection — Reads column definitions, indexes, validations from loaded models
  • ActiveRecord schema introspectionannotate_models.rb — Supplies schema info to be formatted into comment blocks
  • Model files on diskparser.rb — Existing annotations are parsed to detect boundaries for update/replacement
  • annotate_models.rbModel files on disk — Updated schema comments are written back, preserving or replacing existing annotations
  • Rails routes.rbannotate_routes.rb — Routes are introspected from the running Rails router
  • annotate_routes.rbroutes.rb on disk — Route documentation is inserted as comments

🛠️How to make changes

Add support for a new file type to annotate

  1. Define the file pattern matcher in the file patterns configuration (lib/annotate/annotate_models/file_patterns.rb)
  2. Update the annotation logic to handle the new file type's syntax (lib/annotate/annotate_models.rb)
  3. Add corresponding spec test for the new file type (spec/lib/annotate/annotate_models_spec.rb)

Add a new command-line option to the annotate task

  1. Define the option in the task definition (lib/annotate/tasks.rb)
  2. Add the option to the constants configuration (lib/annotate/constants.rb)
  3. Implement the logic that uses the option in the appropriate engine (lib/annotate/annotate_models.rb)
  4. Add test coverage for the new option (spec/lib/tasks/annotate_models_spec.rb)

Customize annotation output format

  1. Review and modify the header/footer generation logic (lib/annotate/annotate_routes/header_generator.rb)
  2. Adjust formatting in the main annotation engine (lib/annotate/annotate_models.rb)
  3. Update parser to recognize your custom format (lib/annotate/parser.rb)

🔧Why these technologies

  • Ruby & ActiveRecord introspection — Allows deep inspection of Rails model schemas without parsing SQL, directly reading column definitions from ActiveRecord
  • Regex-based comment parsing — Lightweight approach to detect and manage existing annotation blocks without external parsing libraries
  • Rake tasks for integration — Standard Rails convention for integrating tooling; allows easy execution alongside other Rails tasks
  • Rails generators — Provides idiomatic installation and setup experience aligned with Rails conventions

⚖️Trade-offs already made

  • Write annotations as comments rather than generating separate documentation files

    • Why: Keeps schema information co-located with code for easy discovery and maintenance
    • Consequence: Annotations are project-specific and not easily shared; requires re-running on schema changes
  • Use regex for parsing existing annotations

    • Why: Simple and fast without external dependencies
    • Consequence: Fragile if comments deviate from expected format; edge cases with nested comments may fail
  • Introspect ActiveRecord models at runtime rather than parsing migrations

    • Why: Gives accurate current state of the database schema
    • Consequence: Requires database connection and proper Rails environment; does not work in isolation

🚫Non-goals (don't propose these)

  • Does not generate or validate database migrations
  • Does not provide real-time schema monitoring or change detection
  • Does not integrate with database management systems directly; relies on ActiveRecord
  • Does not handle non-Rails applications or non-SQL databases as primary targets

⚠️Anti-patterns to avoid

  • Regex-based parsing fragility (Medium)lib/annotate/parser.rb: Comment detection relies on regex patterns that may fail if developers manually edit annotations; no formal grammar or AST used
  • Runtime dependency on database connection (Medium)lib/annotate/annotate_models.rb: Annotation generation requires a live database connection via ActiveRecord; fails in offline or CI environments without proper setup
  • Hardcoded file patterns (Low)lib/annotate/annotate_models/file_patterns.rb: Factory, spec, and fixture patterns are defined statically; adding new patterns requires code changes rather than configuration

🔥Performance hotspots

  • lib/annotate/annotate_models.rb (I/O bound) — File I/O and regex operations scale linearly with number of model files; no parallel processing

🪤Traps & gotchas

  1. Annotate defaults changed in v3.x—must explicitly pass --models flag or configure 'models' => 'true' in auto_annotate_models.rake or it silently skips model annotation (see README). 2) Relies on Bundler/Rails being present; will fail in non-Rails contexts. 3) Schema annotation requires a connected database at annotation time (calls ActiveRecord.connection.columns, etc.), so CI must have db:setup run first. 4) PostGIS/geometry column support is opt-in and requires specific adapters (SpatialAdapter, PostgisAdapter, PostGISAdapter) to recognize geom columns. 5) File parsing is regex-based in parser.rb—malformed or unusual comment styles may break insertion logic.

🏗️Architecture

💡Concepts to learn

  • ActiveRecord Introspection — Annotate's core capability depends on accessing ActiveRecord.connection.columns() and migration history; understanding schema reflection is essential to debugging or extending the gem
  • Monkey-patching / Runtime Patching — lib/annotate/active_record_patch.rb modifies ActiveRecord at runtime; understanding Ruby's open classes and safe patching patterns is critical for contributing without breaking Rails internals
  • Comment Block Insertion with Regex — lib/annotate/parser.rb uses regex to detect, preserve, and replace schema comment blocks; understanding greedy vs non-greedy matching and edge cases is needed for bug fixes
  • Rake Task Hooks — Annotate integrates via lib/tasks/annotate_models_migrate.rake which hooks into Rails' after:migrate; understanding Rake dependencies and Rails task lifecycle is required for CI integration work
  • Rails Generators — lib/generators/annotate/install_generator.rb provides project scaffolding; understanding Thor and Rails generator patterns is needed to improve onboarding experience
  • Schema Versioning and Migrations — Annotate must track which columns exist at each migration point; understanding Rails migration schema_rb and column lifecycle is core to correct annotation
  • presidentbeef/brakeman — Another widely-used Rails static analysis gem; similar maintenance pattern and CLI/Rake integration approach
  • rubocop/rubocop — Parallel Rails code quality tool also using Rake tasks and CI automation; reference for best practices in gem architecture
  • thoughtbot/factory_bot — Directly supported by Annotate; users of factory_bot rely on Annotate for inline schema docs in factories
  • rails/rails — Core dependency—Annotate's entire value is introspecting Rails/ActiveRecord schema APIs

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add comprehensive test coverage for annotate_routes functionality

The spec file spec/lib/annotate/annotate_routes_spec.rb exists but lib/annotate/annotate_routes/ has a header_generator.rb and helpers.rb that likely lack dedicated unit tests. The routes annotation feature is a core capability mentioned in the README but appears to have minimal test coverage compared to the models annotation. This is a high-value addition because routes annotation is a first-class feature.

  • [ ] Review lib/annotate/annotate_routes/header_generator.rb and lib/annotate/annotate_routes/helpers.rb to identify untested methods
  • [ ] Create spec/lib/annotate/annotate_routes/header_generator_spec.rb with unit tests for header generation logic
  • [ ] Create spec/lib/annotate/annotate_routes/helpers_spec.rb with unit tests for route helper functions
  • [ ] Ensure test coverage includes edge cases like nested resources and custom route constraints

Add integration tests for the annotate generator with various Rails versions

The file lib/generators/annotate/install_generator.rb exists but there's no corresponding test file in spec/lib/generators/. The generator is a critical user-facing component that sets up annotation workflows. Testing it across different Rails versions (similar to how CI runs) would catch compatibility issues early and is currently missing.

  • [ ] Create spec/lib/generators/annotate/install_generator_spec.rb
  • [ ] Add tests verifying the generator creates lib/generators/annotate/templates/auto_annotate_models.rake correctly
  • [ ] Add tests for the generator's config merging logic with existing .rubocop.yml and other config files
  • [ ] Consider adding a CI workflow in .github/workflows/ to test the generator against Rails 6.0, 7.0, and 8.0 (see existing ci.yml)

Add missing documentation for file_patterns feature in README

The codebase includes lib/annotate/annotate_models/file_patterns.rb and corresponding spec/lib/annotate/annotate_models/file_patterns_spec.rb, indicating this is a configurable feature. However, the README snippet cuts off mid-sentence and doesn't document how users can customize file patterns for annotation. This is a concrete documentation gap that blocks users from leveraging an existing feature.

  • [ ] Review lib/annotate/annotate_models/file_patterns.rb to understand the pattern matching capabilities
  • [ ] Check lib/annotate/constants.rb for default file pattern definitions
  • [ ] Add a new 'File Patterns Configuration' section to README.md documenting how to customize patterns via config file
  • [ ] Include examples for common use cases (e.g., excluding certain model paths, including additional file types)

🌿Good first issues

  • Add test coverage for lib/annotate/annotate_models/file_patterns.rb—spec/lib/annotate/annotate_models/ exists but likely doesn't test all factory/fixture file pattern matching scenarios; add parameterized tests for Factory Bot, Machinist, and Fabrication patterns.
  • Document the --models flag requirement in lib/generators/annotate/templates/auto_annotate_models.rake template with an inline comment or validation—many users hit the v3 breaking change; adding a guard or warning would reduce support load.
  • Extract lib/annotate/parser.rb regex patterns into named constants (e.g., SCHEMA_BLOCK_START, SCHEMA_BLOCK_END) with documentation—current inline regexes are hard to understand and the file is a key point of failure.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 5d01c41 — Make with_comment_column work with Annotate.set_defaults (#999) (Adeynack)
  • e60a666 — Place column comments at the end of the line (#988) (Adeynack)
  • 3a78787 — fix: can't modify frozen String: "decimal" (#895) (n-rodriguez)
  • 22ab676 — chore: remove broken badges from README.md (ctran)
  • 10a7a76 — Support --frozen option for routing annotations (#979) (kg8m)
  • a28fef3 — Fix retrieve_indexes_from_table when indexes is empty and base table does not exist. (#849) (jjowdy)
  • 13b532d — Update codeql-analysis.yml (ctran)
  • ea4cd00 — Add support for annotating check constraints (#868) (lovro-bikic)
  • 76a1804 — Fix flaky specs (#980) (lovro-bikic)
  • ae0b79c — Make specs run in random order (#787) (drwl)

🔒Security observations

The annotate_models gem appears to be a utility tool with moderate security posture. Primary concerns are around dynamic file manipulation (code injection risks), input validation for regex patterns, and file path handling. No hardcoded secrets or critical misconfigurations were detected in the visible file structure. However, the lack of a security policy, missing dependency information, and potential injection vectors in file annotation logic warrant attention. The codebase would benefit from enhanced input validation, comprehensive security testing, and a clear vulnerability disclosure policy. For a tool that modifies source code files, security is critical.

  • Medium · Potential Code Injection via Dynamic File Annotation — lib/annotate/annotate_models.rb, lib/annotate/annotate_routes.rb. The annotate_models gem dynamically modifies Ruby source files by inserting schema comments. If user-controlled input is processed without proper sanitization, this could lead to code injection or malicious content being inserted into model files. Fix: Implement strict input validation and sanitization for all data that gets written to files. Use allowlists for schema attribute names and values. Ensure proper escaping of special characters before file insertion.
  • Medium · Insufficient Input Validation in File Pattern Matching — lib/annotate/annotate_models/file_patterns.rb. The file_patterns.rb module handles pattern matching for model files. Without proper validation, regex patterns could be exploited or malformed patterns could cause denial of service through ReDoS (Regular Expression Denial of Service) attacks. Fix: Review all regex patterns for ReDoS vulnerabilities. Use anchored patterns and avoid nested quantifiers. Consider using strict file extension matching instead of complex regex patterns where possible.
  • Low · Missing Dependency Manifest — annotate.gemspec, Gemfile. No Gemfile.lock or gemspec content provided in the analysis context. This prevents verification of known vulnerabilities in gem dependencies, which is critical for a code analysis tool that may be used in various Ruby environments. Fix: Maintain an up-to-date Gemfile.lock and regularly run 'bundle audit' to check for known vulnerabilities in dependencies. Pin specific versions of critical gems.
  • Low · Lack of Security Policy Documentation — Repository root. No SECURITY.md or security policy file is visible in the repository structure, which makes it difficult for security researchers to report vulnerabilities responsibly. Fix: Create a SECURITY.md file with clear guidelines for reporting security vulnerabilities, including a responsible disclosure process and contact information.
  • Low · Potential Path Traversal Risk in File Operations — lib/annotate/annotate_models.rb. The gem performs file read/write operations on user-specified Rails project paths. Without proper path validation, path traversal attacks could potentially access files outside the intended Rails application directory. Fix: Implement strict path validation using File.expand_path and verify that all file operations remain within the Rails application root. Use realpath to resolve symlinks and prevent escape attempts.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.