RepoPilotOpen in app →

thoughtbot/factory_bot

A library for setting up Ruby objects as test data.

Healthy

Healthy across the board

Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

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.

  • Last commit 5d ago
  • 35+ active contributors
  • Distributed ownership (top contributor 16% of recent commits)
Show 3 more →
  • 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.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/thoughtbot/factory_bot)](https://repopilot.app/r/thoughtbot/factory_bot)

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 on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: thoughtbot/factory_bot

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/thoughtbot/factory_bot 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 5d ago
  • 35+ active contributors
  • Distributed ownership (top contributor 16% 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 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.

What it runs against: a local clone of thoughtbot/factory_bot — 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 | 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 | Last commit ≤ 35 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>thoughtbot/factory_bot</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of thoughtbot/factory_bot. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/thoughtbot/factory_bot.git
#   cd factory_bot
#
# 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 and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "thoughtbot/factory_bot(\\.git)?\\b" \\
  && ok "origin remote is thoughtbot/factory_bot" \\
  || miss "origin remote is not thoughtbot/factory_bot (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"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 35 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~5d)"
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"
  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

factory_bot is a Ruby test data builder library that replaces fixtures with a declarative DSL for defining object factories. It supports multiple build strategies (persisted objects, unsaved instances, attribute hashes, stubbed objects) and enables factory inheritance, allowing developers to create consistent, reusable test data across RSpec, Cucumber, and other test frameworks without writing repetitive setup code. Monolithic gem structure: lib/factory_bot/ contains the core engine (likely DSL parser, build strategies, registry), features/ has Cucumber integration tests (Gherkin 2265 bytes), spec/ holds RSpec tests. Documentation lives in docs/src/ with separate sections for associations, callbacks, activesupport-instrumentation (see docs/src/aliases/, docs/src/building-or-creating-multiple-records/). Workflows automate testing, docs generation (workflows/docs.yml), and semantic versioning releases.

👥Who it's for

Ruby and Rails developers writing tests who need to quickly generate realistic test objects with minimal boilerplate. Specifically: RSpec users building model/integration tests, Rails developers using factory_bot_rails, and QA engineers writing Cucumber scenarios who want DRY, maintainable test fixtures.

🌱Maturity & risk

Highly mature production-ready library maintained by thoughtbot since ~2008 (original factory_girl era). Multiple CI workflows in .github/workflows/ (build.yml, release.yml, security scanning), extensive documentation in docs/src/, curated Appraisals file for multi-version testing, and active release pipeline indicate professional maintenance. Widely adopted in the Ruby ecosystem (145k+ GitHub stars in thoughtbot org).

Low risk: project has institutional backing (thoughtbot), established release process (workflows/release.yml, RELEASING.md), and validates changes against multiple Ruby versions (build.yml). Main risks are typical for single-organization-maintained gems: breaking API changes require major version bumps (see UPGRADE_FROM_FACTORY_GIRL.md pattern), and test suite must pass on 6+ Ruby versions per build.yml matrix.

Active areas of work

Active maintenance with automated CI/CD: workflows/build.yml runs on every push, workflows/validate-changelog.yml enforces changelog entries, workflows/dynamic-readme.yml auto-updates README, and workflows/prepare-release.yml / workflows/release.yml manage versioning. Dependabot enabled (.github/dependabot.yml) for dependency updates. Documentation is being actively maintained as a Markdown book (docs/book.toml) with mdBook toolchain.

🚀Get running

git clone https://github.com/thoughtbot/factory_bot.git
cd factory_bot
bundle install
bundle exec rspec

Then explore bin/console for interactive REPL testing and review GETTING_STARTED.md for core concepts.

Daily commands:

bundle exec rspec              # Run full RSpec suite
bundle exec cucumber          # Run BDD Cucumber features
bundle exec rake               # Default Rakefile tasks
bin/console                    # Interactive REPL with factory_bot loaded

CI runs via workflows/build.yml matrix across Ruby 3.1–3.3 (inferred from supported versions note).

🗺️Map of the codebase

  • lib/factory_bot/factory.rb: Core Factory class that manages trait application, attribute sequences, and delegation to build strategies—central orchestrator for all factory behavior
  • lib/factory_bot/dsl.rb: DSL parser and evaluation context enabling the FactoryBot.define { factory :user } syntax—implements the fluent builder interface
  • lib/factory_bot/registry.rb: Global factory registry storing all defined factories by name, enabling FactoryBot.create(:user) lookups and lazy registration
  • lib/factory_bot/strategies/: Build strategy implementations (create.rb, build.rb, attributes_for.rb, stub.rb) that control how objects are instantiated and persisted
  • .github/workflows/build.yml: CI matrix testing across Ruby versions, runs RSpec + Cucumber on every commit—validates compatibility and prevents regressions
  • docs/src/associations/: Comprehensive documentation of association handling (implicit, explicit, inline) which is a core distinguishing feature from raw fixtures
  • cucumber.yml: Cucumber test configuration defining feature profiles; test suite validates DSL behavior via BDD scenarios rather than unit tests alone

🛠️How to make changes

Core factory definitions: lib/factory_bot/factory.rb, lib/factory_bot/registry.rb (factory storage). Build strategies: lib/factory_bot/strategies/ (create, build, attributes_for, stub). Associations: lib/factory_bot/association.rb and docs/src/associations/ docs. Tests: spec/ mirrors lib/ structure; features/ has Cucumber scenarios. Docs: Add to docs/src/ using Markdown + mdBook (book.toml); update SUMMARY.md for navigation. Use .github/REPRODUCTION_SCRIPT.rb template for bug issues.

🪤Traps & gotchas

No significant hidden traps documented in file list. Notable non-obvious behaviors: (1) Factories use lazy evaluation—attributes are computed at call time, not definition time, so sequences increment per-call. (2) Association definitions may implicitly define child factories if not already registered (docs/src/associations/implicit-definition.md pattern). (3) Build strategy choice affects object persistence state and callbacks triggered (see docs/src/associations/build-strategies.md). (4) .irbrc exists—bin/console relies on specific setup; interactive testing may behave differently from test runs. Standard Ruby/Rails version constraints apply per build.yml matrix.

💡Concepts to learn

  • Build Strategies — factory_bot's core differentiator—understanding create, build, attributes_for, and stub strategies determines when objects persist, when callbacks fire, and which strategy suits each test scenario
  • Traits (Mixins for Factory Variants) — Traits enable factory composition without inheritance hell; allows FactoryBot.create(:user, :admin, :verified) to combine multiple behavioral sets—critical for reducing factory count
  • Lazy Attributes (Procs & Lambdas in DSL) — Sequences and block-based attributes ensure values are computed at instantiation time, not definition time; prevents stale data or shared mutable state across test runs
  • Factory Inheritance & Subclassing — Allows factory :user to inherit from :person and override specific attributes; reduces duplication when similar object hierarchies exist in domain model
  • Implicit vs. Explicit Association Definition — Factories can auto-create child factories from association declarations (implicit) or require manual factory definition (explicit); impacts test speed and data consistency
  • ActiveSupport Instrumentation Hooks — Callbacks (after_create, before_build, etc.) integrate with Rails lifecycle events; allows side effects (mailers, webhooks, analytics) to fire during factory object creation in tests
  • Test Fixture Registry Pattern — Global factory registry enables lazy lookup (FactoryBot.create(:user)) and dynamic factory definition; architectural pattern underlying the declarative DSL vs. imperative factories
  • thoughtbot/factory_bot_rails — Official Rails integration layer; handles Rails-specific setup (test helpers, fixtures loading, asset precompilation in test env) that factory_bot core doesn't cover
  • ruby/faker — Commonly paired with factory_bot; generates realistic fake data (names, emails, addresses) for attributes instead of static values or sequences
  • DatabaseCleaner/database_cleaner — Companion gem for test suites using factory_bot; handles transaction rollback or truncation between tests after factories create real DB records
  • djezzzl/factory_trace — Analysis tool that identifies unused factories defined in your test suite (mentioned in README); helps optimize factory sprawl over time
  • machinist/machinist — Alternative Sinatra-compatible object factory DSL predating factory_bot; simpler API but less feature-rich; useful for understanding design tradeoffs

🪄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 custom-strategies functionality

The docs/src/custom-strategies/summary.md exists but there's no visible corresponding spec file in the test suite for custom strategy implementations. This is a critical feature that allows users to extend factory_bot's behavior, and comprehensive tests would ensure edge cases are covered (e.g., strategy inheritance, method resolution order, error handling when strategies conflict).

  • [ ] Review existing strategy tests in spec/ directory to understand current coverage
  • [ ] Identify gaps in testing custom strategy definition and invocation
  • [ ] Create spec/factories/strategies/custom_strategies_spec.rb with tests for: defining custom strategies, strategy composition, error cases, and integration with callbacks
  • [ ] Ensure tests cover both simple and complex custom strategy scenarios mentioned in docs
  • [ ] Run full test suite to verify no regressions

Implement validation and examples for polymorphic-associations cookbook recipe

The cookbook includes docs/src/cookbook/polymorphic-associations.md but there's no corresponding integration test or example in the codebase validating the documented patterns work correctly. Polymorphic associations are complex and error-prone; adding tested examples ensures the documentation remains accurate as the library evolves.

  • [ ] Create a new file spec/integration/polymorphic_associations_spec.rb
  • [ ] Implement test cases for the polymorphic association patterns documented in docs/src/cookbook/polymorphic-associations.md
  • [ ] Add examples covering: has_many :through with polymorphic belongs_to, overriding polymorphic type/id fields, nested polymorphic associations
  • [ ] Verify all examples from the documentation pass as integration tests
  • [ ] Update the cookbook if any documented patterns have issues discovered during testing

Add instrumentation tests for activesupport-instrumentation feature

The docs/src/activesupport-instrumentation/summary.md documents this feature, but there's no visible spec file specifically testing the instrumentation hooks and events. This is important for users relying on instrumentation for performance monitoring or debugging, and ensures the feature works with different ActiveSupport versions tested in the CI matrix.

  • [ ] Create spec/factory_bot/instrumentation_spec.rb to test instrumentation event emission
  • [ ] Add tests for: factory.create.begin/end events, factory.build.begin/end events, event payload content, subscriber integration
  • [ ] Test edge cases: nested factory calls, failed builds, custom strategies with instrumentation
  • [ ] Ensure tests work across the Ruby/Rails versions specified in .tool-versions and Appraisals
  • [ ] Verify instrumentation doesn't negatively impact performance by adding optional benchmark tests

🌿Good first issues

  • Add missing Gherkin feature tests for the stub build strategy edge cases (create with stub + nested associations); only 2265 bytes of Gherkin suggests coverage gaps vs. 345k Ruby bytes—check features/ directory for stub-related scenarios.
  • Expand docs/src/aliases/summary.md documentation—file structure suggests aliases feature exists but docs are sparse; add examples and cross-references to main association docs.
  • Write integration tests for ActiveSupport instrumentation hooks (docs/src/activesupport-instrumentation/) to ensure callbacks fire correctly with after_commit, before_validation, etc.; likely under-tested given ActiveSupport's complexity.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 5d39953 — Commit Gemfile.lock as part of the release preparation (#1819) (neilvcarvalho)
  • 8b2d41a — Fix release workflow: add workflow_dispatch, environment, and .tool-versions (#1818) (neilvcarvalho)
  • aaa9275 — Release v6.6.0 (#1817) (github-actions[bot])
  • c47758a — Add gem release workflow with GitHub release notes from changelog (#1815) (neilvcarvalho)
  • 63bf988 — Add bundle install step before bundle exec rake in prepare-release workflow (Copilot)
  • 0337f8b — Extract changelog update logic into a Rake task (neilvcarvalho)
  • 46c5812 — Add workflow to prepare a release PR (neilvcarvalho)
  • ab74525 — Require MFA for gem pushes (MatheusRich)
  • 26f3680 — Add factory_bot.before_run_factory instrumentation event (#1795) (hammadxcm)
  • a4e5ab7 — DefinitionProxy#method_missing: Forward given block to #association (#1579) (grekko)

🔒Security observations

factory_bot demonstrates reasonable security awareness with documented security policies and automated workflows in place. However, the security policy has limited scope (latest version only) which may leave users on older versions vulnerable. No critical vulnerabilities are apparent in the visible file structure, but the codebase is Ruby-based and relies on dependencies that should be monitored via Dependabot. The project lacks visibility into specific vulnerability disclosure timelines and response procedures. As a testing library, the primary risk vectors are indirect—vulnerabilities here could affect test suites across many projects. Overall security posture is good but could be improved with more detailed security documentation.

  • Medium · Limited Security Policy Support Window — SECURITY.md. The SECURITY.md policy only supports the latest version of the project at any given time. This means users on older versions may not receive security patches, potentially leaving them vulnerable to known issues. The policy does not provide a grace period or patch release window for critical vulnerabilities. Fix: Consider adopting a semantic versioning security policy that provides at least patch-level support for 2-3 previous minor versions, especially for a widely-used testing library. Define clear timelines for security patch releases.
  • Low · No Vulnerability Disclosure Timeline Specified — SECURITY.md. The SECURITY.md file directs users to an external URL (thoughtbot.com/security) for vulnerability reporting but does not specify expected response times, disclosure timelines, or acknowledgment procedures. This reduces transparency around the security incident response process. Fix: Add specific SLAs for vulnerability response, such as 'We aim to acknowledge reports within 48 hours and provide fixes within 30 days for critical issues.' Include a responsible disclosure timeline.
  • Low · Dependabot Configuration Present — .github/dependabot.yml. While the presence of .github/dependabot.yml indicates dependency management is enabled, the actual configuration content is not visible. If not properly configured, it may miss security updates or create excessive noise. Fix: Verify that Dependabot is configured to detect security vulnerabilities automatically and create pull requests promptly. Ensure commit signing is enabled and security alerts are monitored.
  • Low · Dynamic Security Workflow May Require Review — .github/workflows/dynamic-security.yml. The presence of .github/workflows/dynamic-security.yml suggests automated security checks are in place, but the actual workflow configuration is not visible for inspection. Fix: Review this workflow to ensure it includes: SAST scanning (code analysis), dependency scanning, and container scanning if applicable. Consider using GitHub's native security features or third-party tools like Snyk or Checkmarx.

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.

Healthy signals · thoughtbot/factory_bot — RepoPilot