thoughtbot/factory_bot_rails
Factory Bot ♥ Rails
Healthy across the board
Permissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 4w ago
- ✓30+ active contributors
- ✓Distributed ownership (top contributor 26% of recent commits)
Show 3 more →Show less
- ✓MIT licensed
- ✓CI configured
- ✓Tests present
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 "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/thoughtbot/factory_bot_rails)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/thoughtbot/factory_bot_rails on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: thoughtbot/factory_bot_rails
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:
- 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. - 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.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/thoughtbot/factory_bot_rails 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
GO — Healthy across the board
- Last commit 4w ago
- 30+ active contributors
- Distributed ownership (top contributor 26% of recent commits)
- MIT licensed
- CI configured
- Tests present
<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 thoughtbot/factory_bot_rails
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/thoughtbot/factory_bot_rails.
What it runs against: a local clone of thoughtbot/factory_bot_rails — 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 thoughtbot/factory_bot_rails | Confirms the artifact applies here, not a fork |
| 2 | License is still MIT | Catches relicense before you depend on it |
| 3 | Default branch main exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 61 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of thoughtbot/factory_bot_rails. If you don't
# have one yet, run these first:
#
# git clone https://github.com/thoughtbot/factory_bot_rails.git
# cd factory_bot_rails
#
# 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 thoughtbot/factory_bot_rails and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "thoughtbot/factory_bot_rails(\\.git)?\\b" \\
&& ok "origin remote is thoughtbot/factory_bot_rails" \\
|| miss "origin remote is not thoughtbot/factory_bot_rails (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
&& ok "license is MIT" \\
|| miss "license drift — was MIT at generation time"
# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
&& ok "default branch main exists" \\
|| miss "default branch main no longer exists"
# 4. Critical files exist
test -f "lib/factory_bot_rails.rb" \\
&& ok "lib/factory_bot_rails.rb" \\
|| miss "missing critical file: lib/factory_bot_rails.rb"
test -f "lib/factory_bot_rails/railtie.rb" \\
&& ok "lib/factory_bot_rails/railtie.rb" \\
|| miss "missing critical file: lib/factory_bot_rails/railtie.rb"
test -f "lib/factory_bot_rails/definition_file_paths.rb" \\
&& ok "lib/factory_bot_rails/definition_file_paths.rb" \\
|| miss "missing critical file: lib/factory_bot_rails/definition_file_paths.rb"
test -f "lib/factory_bot_rails/reloader.rb" \\
&& ok "lib/factory_bot_rails/reloader.rb" \\
|| miss "missing critical file: lib/factory_bot_rails/reloader.rb"
test -f "lib/generators/factory_bot/model/model_generator.rb" \\
&& ok "lib/generators/factory_bot/model/model_generator.rb" \\
|| miss "missing critical file: lib/generators/factory_bot/model/model_generator.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 61 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~31d)"
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/thoughtbot/factory_bot_rails"
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).
⚡TL;DR
factory_bot_rails is a Rails plugin that integrates factory_bot (a fixtures replacement library) with Rails projects, enabling developers to define reusable test object factories with multiple build strategies instead of static fixtures. It automatically discovers and loads factory definitions from conventional directories like spec/factories and test/factories, and hooks into Rails generators to produce factories instead of fixtures when scaffolding models. Simple gem structure: entry point is lib/factory_bot_rails.rb, core logic splits into lib/factory_bot_rails/definition_file_paths.rb (path discovery), generator.rb (Rails integration), factory_validator.rb (validation), and file_fixture_support.rb (helpers). Features are tested via Cucumber acceptance tests in features/ (load_definitions.feature, generators.feature, initializers.feature, reloading.feature). Multiple Appraisal gemfiles (gemfiles/rails*.gemfile) test against 10+ Rails versions.
👥Who it's for
Rails developers writing tests (unit, integration, acceptance) who need to create complex, realistic model instances during test setup. Test engineers and TDD practitioners who want factory-based approaches instead of YAML fixtures, and contributors to the thoughtbot open-source ecosystem.
🌱Maturity & risk
Production-ready and actively maintained. The repo supports Rails 5.0–8.1 (10+ versions), has comprehensive test coverage via Cucumber features and RSpec, runs CI on GitHub Actions (build.yml), and maintains clear documentation in README and CONTRIBUTING.md. Regular updates to Appraisals show recent Rails version support (Rails 8.1 added), indicating active development.
Low risk for production use, but depends on factory_bot (separate gem—must track updates there) and tight coupling to Rails versions. Single-maintainer concerns are mitigated by thoughtbot's backing. Breaking changes are infrequent but possible when Rails major versions release; check NEWS.md and RELEASING.md before upgrading. No obvious technical debt visible in the file structure.
Active areas of work
Actively tracking Rails releases—recent gemfiles show Rails 8.0 and 8.1 support added. CI workflows (build.yml, dynamic-readme.yml, dynamic-security.yml) are up-to-date. GitHub Issues and PRs suggest incremental feature polishing and Rails compatibility maintenance rather than major rewrites.
🚀Get running
Clone: git clone https://github.com/thoughtbot/factory_bot_rails.git && cd factory_bot_rails. Install: bundle install. Run tests: bundle exec rake (runs RSpec and Cucumber features). Use bin/setup script for interactive setup if needed.
Daily commands:
Development flow: bin/setup for initial setup, then bundle exec rake to run full test suite (RSpec + Cucumber). Individual test runs: bundle exec rspec (unit tests) or bundle exec cucumber (acceptance tests, defined in cucumber.yml). Test against specific Rails version: bundle exec appraisal rails-7-0 rake (example for Rails 7.0).
🗺️Map of the codebase
lib/factory_bot_rails.rb— Primary entry point that initializes the gem and registers the Rails railtie.lib/factory_bot_rails/railtie.rb— Rails integration hook that configures factory_bot with Rails, loads factories, and sets up reloading.lib/factory_bot_rails/definition_file_paths.rb— Core logic for discovering and managing factory definition file paths in the Rails app.lib/factory_bot_rails/reloader.rb— Handles factory reloading during development to pick up changes without restart.lib/generators/factory_bot/model/model_generator.rb— Generator invoked duringrails generate factory_bot:modelto scaffold new factory files.lib/factory_bot_rails/factory_validator.rb— Validates factory definitions at load time to catch syntax and configuration errors early.factory_bot_rails.gemspec— Gem manifest defining dependencies, version, and metadata for the package.
🧩Components & responsibilities
- Railtie (lib/factory_bot_rails/railtie.rb) (Rails::Railtie, FactoryBot) — Hooks into Rails lifecycle; orchestrates initialization, validation, and reloading of factories.
- Failure mode: If railtie fails to register or configure, factories never load; tests fail with undefined factory errors.
- DefinitionFilePaths (lib/factory_bot_rails/definition_file_paths.rb) (File system I/O, Ruby Pathname) — Discovers all factory definition files in standard Rails paths.
- Failure mode: If paths are misconfigured or files don't exist, FactoryBot receives empty definition list; factories unavailable.
- FactoryValidator (lib/factory_bot_rails/factory_validator.rb) (FactoryBot introspection API) — Validates factory definitions after loading to catch errors early.
- Failure mode: If validation is skipped, invalid factories go undetected until test runs; harder to debug.
- Reloader (lib/factory_bot_rails/reloader.rb) (Rails::Autoloaders) — Integrates with Rails reloader to reload factories on file changes during development.
- Failure mode: If reloader fails, factory changes require manual server restart; slows development loop.
- Model Generator (lib/generators/factory_bot/model/model_generator.rb) (Rails::Generators, ERB templates) — Scaffolds new factory files via
rails generate factory_bot:model.
🛠️How to make changes
Add a new factory generator option
- Edit the model generator in lib/generators/factory_bot/model/model_generator.rb to add a new class method or option (e.g., --with-traits). (
lib/generators/factory_bot/model/model_generator.rb) - Update the factory template at lib/generators/factory_bot/model/templates/factories.erb to conditionally render the new feature. (
lib/generators/factory_bot/model/templates/factories.erb) - Add a feature scenario in features/generators.feature to document and test the new option. (
features/generators.feature)
Support a new Rails version
- Create a new gemfile in gemfiles/rails<version>.gemfile (e.g., gemfiles/rails9.0.gemfile) that pins the Rails version. (
gemfiles/rails9.0.gemfile) - Add the new version to the Appraisals file so it is tested in CI. (
Appraisals) - Update .github/workflows/build.yml to include the new Rails version in the test matrix. (
.github/workflows/build.yml)
Add custom factory discovery logic
- Extend or subclass DefinitionFilePaths in lib/factory_bot_rails/definition_file_paths.rb to customize where factories are discovered. (
lib/factory_bot_rails/definition_file_paths.rb) - Register the custom paths class in the railtie's config setup within lib/factory_bot_rails/railtie.rb. (
lib/factory_bot_rails/railtie.rb) - Write a test in spec/factory_bot_rails/definition_file_paths_spec.rb to verify path discovery behavior. (
spec/factory_bot_rails/definition_file_paths_spec.rb)
Add a new factory validation rule
- Add a new validation method to FactoryValidator in lib/factory_bot_rails/factory_validator.rb. (
lib/factory_bot_rails/factory_validator.rb) - Call the new validation method from the validate! or validate_factory! method. (
lib/factory_bot_rails/factory_validator.rb) - Add a test case in spec/factory_bot_rails/factory_spec.rb to verify the validation rule fires correctly. (
spec/factory_bot_rails/factory_spec.rb)
🔧Why these technologies
- Rails Railtie — Provides clean integration point into Rails initialization without monkeypatching; respects Rails conventions.
- FactoryBot gem (core dependency) — Provides factory definition DSL and build strategies; this gem just integrates it with Rails.
- Rails code generators — Allows
rails generate factory_bot:modelto scaffold factories consistent with Rails conventions. - Cucumber feature tests — High-level acceptance tests verify end-to-end Rails integration without unit test brittleness.
⚖️Trade-offs already made
-
Discover factories from fixed paths (spec/factories, test/factories) rather than scanning entire app.
- Why: Simplicity, predictability, and performance; follows Rails conventions.
- Consequence: Users must organize factories in the expected directory structure; custom paths require configuration override.
-
Validate factories synchronously at boot time rather than lazily.
- Why: Fail fast; catch factory definition errors before tests run.
- Consequence: Slower app boot in development; requires FactoryValidator to be efficient.
-
Reload factories via Rails reloader rather than manual restart.
- Why: Improves development experience; changes to factories picked up without server restart.
- Consequence: Adds complexity to track file changes; potential for stale cached factory references.
🚫Non-goals (don't propose these)
- Does not handle database persistence; relies on FactoryBot and Rails ORM.
- Does not provide UI or dashboard for managing factories.
- Does not add authentication or authorization; user responsible for securing test data.
- Does not extend FactoryBot DSL (that is FactoryBot's domain); only integrates it with Rails.
🪤Traps & gotchas
Rails version constraints are strict—Appraisals file defines minimum/maximum supported Rails versions; installing factory_bot_rails in an unsupported Rails version will silently fail to load generators. Automatic factory loading paths are relative to Rails.root; if Rails.root is misconfigured in test env, factories won't be found. File fixture support (file_fixture_support.rb) requires ActiveSupport::Testing::FileFixtures to be available—not guaranteed in all test frameworks (e.g., custom test frameworks). Reloading.feature tests indicate factory reloading can be tricky in development mode; watch out for stale factory definitions in console sessions.
🏗️Architecture
💡Concepts to learn
- Rails Railtie — Factory_bot_rails uses a Railtie to hook into Rails initialization; understanding how Railties register config blocks and initializers is essential to modifying how factory_bot loads in Rails apps
- Rails Generators — The gem patches Rails scaffolding generators to emit factories instead of fixtures; knowing how to write and hook custom generators is critical for modifying factory template generation
- Convention over Configuration — Factory_bot_rails discovers factories from conventional paths (spec/factories, test/factories) without explicit config; the entire design philosophy relies on this Rails principle
- Test Fixtures vs. Factory Pattern — Understanding why factories are superior to static YAML fixtures (reusability, associations, sequences, multiple variants) explains the entire motivation for this gem
- Appraisal Multi-Version Testing — The Appraisals file and Appraisal gem enable testing across 10+ Rails versions simultaneously; critical for maintaining compatibility without breaking old users
- Gherkin BDD (Behavior-Driven Development) — Features/ folder uses Cucumber/Gherkin to describe user-facing behavior in plain English; understanding the step definitions bridges test intent and Ruby implementation
- Rails Autoloader (Zeitwerk) — Factory definition file paths interact with Rails' eager loading and lazy loading; understanding Zeitwerk is important for debugging factory discovery issues in different Rails modes
🔗Related repos
thoughtbot/factory_bot— The core factory_bot library that factory_bot_rails wraps; all factory definition syntax and build strategies live herethoughtbot/shoulda-matchers— Companion testing gem from thoughtbot providing Rails model matchers; often used alongside factory_bot in test suitesseeding-labs/faker— Complements factory_bot by generating realistic fake data for factory attributes (names, emails, addresses)rails/rails— Rails framework itself; factory_bot_rails is a plugin that integrates with Rails generators and initializersrspec/rspec-rails— RSpec integration for Rails; the primary test framework used by factory_bot_rails tests and most Rails projects using this gem
🪄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 integration tests for Rails 8.1 Zeitwerk autoloader compatibility
The repo supports Rails 8.1 (seen in gemfiles/rails8.1.gemfile) but there are no specific tests validating that factory definitions are correctly loaded with Zeitwerk's strict autoloading mode. This is critical since factory_bot_rails relies on lib/factory_bot_rails/definition_file_paths.rb to discover factories, and Zeitwerk has different require semantics than previous autoloaders. New contributors could add feature tests ensuring factories are found and loaded correctly under Zeitwerk.
- [ ] Create a new feature file: features/zeitwerk_autoloading.feature
- [ ] Add step definitions in features/step_definitions/ to test factory discovery with Zeitwerk enabled
- [ ] Verify factories in spec/factories/ are loaded without explicit requires
- [ ] Test that factory_bot_rails/definition_file_paths.rb correctly handles Zeitwerk paths
Add unit tests for FactoryValidator edge cases
The file lib/factory_bot_rails/factory_validator.rb exists but appears to have minimal test coverage based on the spec/ directory structure not showing a corresponding spec file. This validator is critical for preventing silent failures when factories are misconfigured. Contributors should add comprehensive unit tests covering invalid factory definitions, circular dependencies, and missing associations.
- [ ] Create spec/factory_bot_rails/factory_validator_spec.rb
- [ ] Add tests for invalid factory syntax detection
- [ ] Add tests for circular trait/factory dependencies
- [ ] Add tests for missing association references
- [ ] Add tests for the validator integration with the Railtie
Refactor and add tests for the Reloader in development mode
The lib/factory_bot_rails/reloader.rb handles factory reloading during Rails development, but there's no dedicated test file for it. With Rails supporting multiple execution environments and the complexity of factory reloading (dealing with class redefinition, trait caching, etc.), this needs comprehensive coverage. Contributors should test reloader behavior across different Rails versions.
- [ ] Create spec/factory_bot_rails/reloader_spec.rb
- [ ] Add tests for factory reloading on file changes
- [ ] Add tests for trait and factory cache invalidation
- [ ] Test reloader behavior in test vs development environments
- [ ] Add integration tests with features/reloading.feature (currently exists but may lack coverage)
🌿Good first issues
- Add Ruby 3.3+ support tests to build.yml if not present, or update .tool-versions to use latest Ruby—check current Ruby version constraints in gemspec and update CI accordingly
- Write a new Cucumber feature (e.g., features/custom_factory_path_config.feature) to test edge case of user-configured definition_file_paths with absolute paths, then implement validation in lib/factory_bot_rails/definition_file_paths.rb
- Document the interaction between file_fixture_support and non-Rails test frameworks in CONTRIBUTING.md or add a configuration example to README showing how to disable file_fixture_support for custom test setups
⭐Top contributors
Click to expand
Top contributors
- @composerinteralia — 26 commits
- @neilvcarvalho — 12 commits
- @dependabot[bot] — 9 commits
- @mike-burns — 8 commits
- @smaboshe — 6 commits
📝Recent commits
Click to expand
Recent commits
ed9c9bc— Fix hash syntax error (#553) (neilvcarvalho)bd6834b— Require MFA for gem pushes (neilvcarvalho)2428e31— Update Gemfile.lock to upgrade dependencies and fix version inconsistencies (#545) (ydah)7b7b459— Support Rails 8.1 (#549) (toshimaru)5ef6971— removes @DoodlingDev (#546) (DoodlingDev)dfdef4c— Bump to 6.5.1 (#543) (neilvcarvalho)b6c4e8d— Add AuthenticationGenerator for users factory creation (#542) (neilvcarvalho)364bd89— add vburzynski as codeowner (#539) (DoodlingDev)8e45bc3— Updaterequired_ruby_versionto require >= Ruby 3.1 (#538) (y-yagi)6b757eb— Fix Cucumber tests (#536) (neilvcarvalho)
🔒Security observations
factory_bot_rails demonstrates generally solid security posture as a test utility library. No critical vulnerabilities were identified in the codebase structure or configuration. The main concerns are administrative: incomplete security documentation and best practices for managing test fixtures. As a gem providing Rails integration for factory management, the attack surface is limited. Recommendations focus on improving security transparency and documentation rather than remediating code-level vulnerabilities.
- Low · Empty SECURITY.md File —
SECURITY.md. The SECURITY.md file is present but contains only template placeholders with no actual security policy or vulnerability disclosure guidelines. This may confuse users about how to report security issues responsibly. Fix: Populate SECURITY.md with a proper security policy including vulnerability reporting procedures, supported versions, and security contact information. - Low · Multiple Gemfile Versions Without Pinning Strategy —
Gemfile, gemfiles/ directory. The repository maintains multiple Gemfiles for different Rails versions (5.0-8.1). While necessary for compatibility testing, there's no evidence of lock files being committed, which could lead to inconsistent dependency versions across environments. Fix: Ensure Gemfile.lock files are committed to version control for reproducible builds. Consider using dependency scanning tools in CI/CD pipelines. - Low · Test Fixtures Could Contain Sensitive Data —
spec/fixtures/. The repository contains fixture files (spec/fixtures/factories.rb, spec/fixtures/files/) that could potentially contain sensitive test data if developers are not careful about what they add. Fix: Add clear documentation in CONTRIBUTING.md about not including sensitive data in fixtures. Consider adding pre-commit hooks to scan for secrets in fixture files.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.