Showing preview only (579K chars total). Download the full file or copy to clipboard to get everything.
Repository: thoughtbot/factory_bot
Branch: main
Commit: d3d6b85319e0
Files: 274
Total size: 517.8 KB
Directory structure:
gitextract_cvhgehfx/
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.md
│ │ └── feature_request.md
│ ├── REPRODUCTION_SCRIPT.rb
│ ├── dependabot.yml
│ └── workflows/
│ ├── build.yml
│ ├── docs.yml
│ ├── dynamic-readme.yml
│ └── dynamic-security.yml
├── .gitignore
├── .irbrc
├── .rspec
├── .simplecov
├── .standard.yml
├── .standard_todo.yml
├── .yardopts
├── Appraisals
├── CODEOWNERS
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── GETTING_STARTED.md
├── Gemfile
├── LICENSE
├── NAME.md
├── NEWS.md
├── README.md
├── RELEASING.md
├── Rakefile
├── SECURITY.md
├── cucumber.yml
├── docs/
│ ├── book.toml
│ └── src/
│ ├── SUMMARY.md
│ ├── activesupport-instrumentation/
│ │ └── summary.md
│ ├── aliases/
│ │ └── summary.md
│ ├── associations/
│ │ ├── association-overrides.md
│ │ ├── build-strategies.md
│ │ ├── explicit-definition.md
│ │ ├── implicit-definition.md
│ │ ├── inline-definition.md
│ │ ├── overriding-attributes.md
│ │ ├── specifying-the-factory.md
│ │ └── summary.md
│ ├── building-or-creating-multiple-records/
│ │ └── summary.md
│ ├── callbacks/
│ │ ├── callback_order.md
│ │ ├── default-callbacks.md
│ │ ├── global-callbacks.md
│ │ ├── multiple-callbacks.md
│ │ ├── summary.md
│ │ └── symbol-to_proc.md
│ ├── cookbook/
│ │ ├── has_and_belongs_to_many-associations.md
│ │ ├── has_many-associations.md
│ │ ├── interconnected-associations.md
│ │ └── polymorphic-associations.md
│ ├── custom-callbacks/
│ │ └── summary.md
│ ├── custom-construction/
│ │ └── summary.md
│ ├── custom-methods-to-persist-objects/
│ │ └── summary.md
│ ├── custom-strategies/
│ │ └── summary.md
│ ├── defining/
│ │ ├── best-practices.md
│ │ ├── explicit-class.md
│ │ ├── file-paths.md
│ │ ├── hash-attributes.md
│ │ ├── name-attributes.md
│ │ ├── static-attributes.md
│ │ └── summary.md
│ ├── dependent-attributes/
│ │ └── summary.md
│ ├── inheritance/
│ │ ├── assigning-parent-explicitly.md
│ │ ├── best-practices.md
│ │ ├── nested-factories.md
│ │ └── summary.md
│ ├── intro.md
│ ├── linting-factories/
│ │ └── summary.md
│ ├── method-name-reserved-word-attributes/
│ │ └── summary.md
│ ├── modifying-factories/
│ │ └── summary.md
│ ├── rails-preloaders-and-rspec/
│ │ └── summary.md
│ ├── ref/
│ │ ├── add_attribute.md
│ │ ├── association.md
│ │ ├── build-and-create.md
│ │ ├── build-strategies.md
│ │ ├── define.md
│ │ ├── factory.md
│ │ ├── find_definitions.md
│ │ ├── hooks.md
│ │ ├── lint.md
│ │ ├── method_missing.md
│ │ ├── modify.md
│ │ ├── register_strategy.md
│ │ ├── sequence.md
│ │ ├── trait.md
│ │ ├── traits_for_enum.md
│ │ └── transient.md
│ ├── sequences/
│ │ ├── aliases.md
│ │ ├── as-implicit-attributes.md
│ │ ├── factory-sequences.md
│ │ ├── generating.md
│ │ ├── global-sequences.md
│ │ ├── initial-value.md
│ │ ├── rewinding.md
│ │ ├── sequence-uris.md
│ │ ├── setting-the-value.md
│ │ ├── summary.md
│ │ ├── uniqueness.md
│ │ ├── with-dynamic-attributes.md
│ │ └── without-a-block.md
│ ├── setup/
│ │ └── summary.md
│ ├── traits/
│ │ ├── as-implicit-attributes.md
│ │ ├── attribute-precedence.md
│ │ ├── defining-traits.md
│ │ ├── enum.md
│ │ ├── in-child-factories.md
│ │ ├── mixins.md
│ │ ├── summary.md
│ │ ├── traits-within-traits.md
│ │ ├── using.md
│ │ ├── with-associations.md
│ │ └── with-transient-attributes.md
│ ├── transient-attributes/
│ │ ├── summary.md
│ │ ├── with-associations.md
│ │ ├── with-attributes_for.md
│ │ ├── with-callbacks.md
│ │ └── with-other-attributes.md
│ ├── using-factories/
│ │ ├── attribute-overrides.md
│ │ ├── build-strategies.md
│ │ ├── build_stubbed-and-marshaldump.md
│ │ └── summary.md
│ └── using-without-bundler/
│ └── summary.md
├── factory_bot.gemspec
├── features/
│ ├── find_definitions.feature
│ ├── step_definitions/
│ │ ├── database_steps.rb
│ │ └── factory_bot_steps.rb
│ └── support/
│ ├── env.rb
│ └── factories.rb
├── gemfiles/
│ ├── 7.0.gemfile
│ ├── 7.1.gemfile
│ ├── 7.2.gemfile
│ ├── 8.0.gemfile
│ └── main.gemfile
├── lib/
│ ├── factory_bot/
│ │ ├── aliases.rb
│ │ ├── attribute/
│ │ │ ├── association.rb
│ │ │ ├── dynamic.rb
│ │ │ └── sequence.rb
│ │ ├── attribute.rb
│ │ ├── attribute_assigner.rb
│ │ ├── attribute_list.rb
│ │ ├── callback.rb
│ │ ├── callbacks_observer.rb
│ │ ├── configuration.rb
│ │ ├── declaration/
│ │ │ ├── association.rb
│ │ │ ├── dynamic.rb
│ │ │ └── implicit.rb
│ │ ├── declaration.rb
│ │ ├── declaration_list.rb
│ │ ├── decorator/
│ │ │ ├── attribute_hash.rb
│ │ │ ├── disallows_duplicates_registry.rb
│ │ │ ├── invocation_tracker.rb
│ │ │ └── new_constructor.rb
│ │ ├── decorator.rb
│ │ ├── definition.rb
│ │ ├── definition_hierarchy.rb
│ │ ├── definition_proxy.rb
│ │ ├── enum.rb
│ │ ├── errors.rb
│ │ ├── evaluation.rb
│ │ ├── evaluator.rb
│ │ ├── evaluator_class_definer.rb
│ │ ├── factory.rb
│ │ ├── factory_runner.rb
│ │ ├── find_definitions.rb
│ │ ├── internal.rb
│ │ ├── linter.rb
│ │ ├── null_factory.rb
│ │ ├── null_object.rb
│ │ ├── registry.rb
│ │ ├── reload.rb
│ │ ├── sequence.rb
│ │ ├── strategy/
│ │ │ ├── attributes_for.rb
│ │ │ ├── build.rb
│ │ │ ├── create.rb
│ │ │ ├── null.rb
│ │ │ └── stub.rb
│ │ ├── strategy.rb
│ │ ├── strategy_syntax_method_registrar.rb
│ │ ├── syntax/
│ │ │ ├── default.rb
│ │ │ └── methods.rb
│ │ ├── syntax.rb
│ │ ├── syntax_runner.rb
│ │ ├── trait.rb
│ │ ├── uri_manager.rb
│ │ └── version.rb
│ └── factory_bot.rb
└── spec/
├── acceptance/
│ ├── activesupport_instrumentation_spec.rb
│ ├── add_attribute_spec.rb
│ ├── associations_spec.rb
│ ├── attribute_aliases_spec.rb
│ ├── attribute_existing_on_object_spec.rb
│ ├── attributes_for_destructuring.rb
│ ├── attributes_for_spec.rb
│ ├── attributes_from_instance_spec.rb
│ ├── attributes_ordered_spec.rb
│ ├── build_list_spec.rb
│ ├── build_spec.rb
│ ├── build_stubbed_spec.rb
│ ├── callbacks_spec.rb
│ ├── create_list_spec.rb
│ ├── create_pair_spec.rb
│ ├── create_spec.rb
│ ├── define_child_before_parent_spec.rb
│ ├── defining_methods_inside_a_factory_spec.rb
│ ├── definition_camel_string_spec.rb
│ ├── definition_spec.rb
│ ├── definition_without_block_spec.rb
│ ├── enum_traits_spec.rb
│ ├── global_initialize_with_spec.rb
│ ├── global_to_create_spec.rb
│ ├── initialize_with_spec.rb
│ ├── keyed_by_class_spec.rb
│ ├── lint_spec.rb
│ ├── modify_factories_spec.rb
│ ├── modify_inherited_spec.rb
│ ├── nested_attributes_spec.rb
│ ├── overrides_spec.rb
│ ├── parent_spec.rb
│ ├── private_attributes_spec.rb
│ ├── register_strategies_spec.rb
│ ├── reload_spec.rb
│ ├── sequence_context_spec.rb
│ ├── sequence_setting_spec.rb
│ ├── sequence_spec.rb
│ ├── skip_create_spec.rb
│ ├── stub_spec.rb
│ ├── syntax_methods_within_dynamic_attributes_spec.rb
│ ├── traits_spec.rb
│ └── transient_attributes_spec.rb
├── factory_bot/
│ ├── aliases_spec.rb
│ ├── attribute/
│ │ ├── association_spec.rb
│ │ ├── dynamic_spec.rb
│ │ └── sequence_spec.rb
│ ├── attribute_assignment_spec.rb
│ ├── attribute_list_spec.rb
│ ├── attribute_spec.rb
│ ├── callback_spec.rb
│ ├── declaration/
│ │ ├── association_spec.rb
│ │ ├── dynamic_spec.rb
│ │ └── implicit_spec.rb
│ ├── declaration_list_spec.rb
│ ├── decorator/
│ │ └── attribute_hash_spec.rb
│ ├── definition_proxy_spec.rb
│ ├── definition_spec.rb
│ ├── disallows_duplicates_registry_spec.rb
│ ├── evaluator_class_definer_spec.rb
│ ├── factory_spec.rb
│ ├── find_definitions_spec.rb
│ ├── internal_spec.rb
│ ├── null_factory_spec.rb
│ ├── null_object_spec.rb
│ ├── registry_spec.rb
│ ├── sequence_spec.rb
│ ├── strategy/
│ │ ├── attributes_for_spec.rb
│ │ ├── build_spec.rb
│ │ ├── create_spec.rb
│ │ └── stub_spec.rb
│ ├── strategy_spec.rb
│ └── uri_manager_spec.rb
├── factory_bot_spec.rb
├── spec_helper.rb
└── support/
├── containers/
│ └── test_log.rb
├── macros/
│ ├── define_constant.rb
│ ├── deprecation.rb
│ └── temporary_assignment.rb
├── matchers/
│ ├── be_about_now.rb
│ ├── callback.rb
│ ├── declaration.rb
│ ├── delegate.rb
│ ├── raise_did_you_mean_error.rb
│ └── trait.rb
└── shared_examples/
└── strategy.rb
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: 'bug'
assignees: ''
---
<!-- By contributing to this project, you agree to abide by the thoughtbot Code
of Conduct: https://thoughtbot.com/open-source-code-of-conduct -->
### Description
<!-- A clear and concise description of what the bug is. -->
### Reproduction Steps
<!-- Steps for others to reproduce the bug. Be as specific as possible. A
reproduction script or link to a sample application that demonstrates the
problem are especially helpful. -->
<!-- You can create a reproduction script by copying this sample reproduction
script and adding whatever code is necessary to get a failing test case:
https://github.com/thoughtbot/factory_bot/blob/main/.github/REPRODUCTION_SCRIPT.rb -->
### Expected behavior
<!-- What you expected to happen. -->
### Actual behavior
<!-- What happened instead. -->
### System configuration
**factory_bot version**:
**rails version**:
**ruby version**:
================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: 'feature'
assignees: ''
---
<!-- By contributing to this project, you agree to abide by the thoughtbot Code
of Conduct: https://thoughtbot.com/open-source-code-of-conduct -->
### Problem this feature will solve
<!-- A clear and concise description of what the problem is. Ex. When doing
[...] I find it difficult to [...] -->
### Desired solution
<!-- The feature or change that would solve the problem -->
## Alternatives considered
<!-- Any alternative solutions or features you've considered. -->
## Additional context
<!-- Add any other context about this feature request. -->
================================================
FILE: .github/REPRODUCTION_SCRIPT.rb
================================================
require "bundler/inline"
gemfile(true) do
source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
gem "factory_bot", "~> 6.0"
gem "activerecord"
gem "sqlite3"
end
require "active_record"
require "factory_bot"
require "minitest/autorun"
require "logger"
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
ActiveRecord::Base.logger = Logger.new(STDOUT)
ActiveRecord::Schema.define do
# TODO: Update the schema to include the specific tables or columns necessary
# to reproduct the bug
create_table :posts, force: true do |t|
t.string :body
end
end
# TODO: Add any application specific code necessary to reproduce the bug
class Post < ActiveRecord::Base
end
FactoryBot.define do
# TODO: Write the factory definitions necessary to reproduce the bug
factory :post do
body { "Post body" }
end
end
class FactoryBotTest < Minitest::Test
def test_factory_bot_stuff
# TODO: Write a failing test case to demonstrate what isn't working as
# expected
body_override = "Body override"
post = FactoryBot.build(:post, body: body_override)
assert_equal post.body, body_override
end
end
# Run the tests with `ruby <filename>`
================================================
FILE: .github/dependabot.yml
================================================
---
version: 2
updates:
- package-ecosystem: "bundler"
directory: "/"
schedule:
interval: weekly
time: "02:00"
timezone: "Etc/UTC"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: weekly
time: "02:00"
timezone: "Etc/UTC"
================================================
FILE: .github/workflows/build.yml
================================================
name: Build
on:
pull_request:
push:
branches: [ main ]
jobs:
build:
name: Ruby ${{ matrix.ruby }} / Rails ${{ matrix.rails }}
strategy:
fail-fast: false
matrix:
ruby:
- jruby-9.4
- truffleruby
- "4.0"
- "3.4"
- "3.3"
- "3.2"
- "3.1"
rails:
- "7.0"
- "7.1"
- "7.2"
- "8.0"
- main
exclude:
- { ruby: jruby-9.4, rails: "7.1" }
- { ruby: jruby-9.4, rails: "7.2" }
- { ruby: jruby-9.4, rails: "8.0" }
- { ruby: jruby-9.4, rails: main }
# Rails >= 8.0 requires Ruby 3.2
- { ruby: "3.1", rails: "8.0" }
- { ruby: "3.1", rails: "main" }
# Rails >= 8.1 requires Ruby 3.3
- { ruby: "3.2", rails: "main" }
# 2025-10-23 There's an incompatibility between truffleruby and rails edge Git ref
# results in a "NoMethodError: undefined method `[]' for class Fiber" error whilst running specs
- { ruby: truffleruby, rails: "main" }
runs-on: 'ubuntu-latest'
env:
BUNDLE_GEMFILE: gemfiles/${{ matrix.rails }}.gemfile
steps:
- uses: actions/checkout@v6
- uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
- name: Setup project
run: bundle install
- name: Run test
run: bundle exec rake all_specs
standard:
name: Run standard
runs-on: 'ubuntu-latest'
steps:
- uses: actions/checkout@v6
- uses: ruby/setup-ruby@v1
with:
ruby-version: "3.3"
- name: Setup project
run: bundle install
- name: Run test
run: bundle exec rake standard
================================================
FILE: .github/workflows/docs.yml
================================================
name: Docs
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
contents: write # To push a branch
pull-requests: write # To create a PR from that branch
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Install mdbook
run: |
mkdir mdbook
curl -sSL https://github.com/rust-lang/mdBook/releases/download/v0.4.27/mdbook-v0.4.27-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=./mdbook
echo `pwd`/mdbook >> $GITHUB_PATH
- name: Deploy GitHub Pages
run: |
cd docs
mdbook build
git worktree add gh-pages
git config user.name "Deploy from CI"
git config user.email ""
cd gh-pages
# Delete the ref to avoid keeping history.
git update-ref -d refs/heads/gh-pages
rm -rf *
mv ../book/* .
git add .
git commit -m "Deploy $GITHUB_SHA to gh-pages"
git push --force --set-upstream origin gh-pages
================================================
FILE: .github/workflows/dynamic-readme.yml
================================================
name: update-templates
on:
push:
branches:
- main
paths:
- README.md
workflow_dispatch:
jobs:
update-templates:
permissions:
contents: write
pull-requests: write
pages: write
uses: thoughtbot/templates/.github/workflows/dynamic-readme.yaml@main
secrets:
token: ${{ secrets.GITHUB_TOKEN }}
================================================
FILE: .github/workflows/dynamic-security.yml
================================================
name: update-security
on:
push:
paths:
- SECURITY.md
branches:
- main
workflow_dispatch:
jobs:
update-security:
permissions:
contents: write
pull-requests: write
pages: write
uses: thoughtbot/templates/.github/workflows/dynamic-security.yaml@main
secrets:
token: ${{ secrets.GITHUB_TOKEN }}
================================================
FILE: .gitignore
================================================
.bundle
.rubocop-https*
.yardoc
.zed
*.swp
bin
coverage
test.db
tmp
# yard
doc
# gem builds
factory_bot-*.gem
factory_girl-*.gem
# mdBook generated output
docs/book
# lock files generated by appraisal
gemfiles/*.lock
================================================
FILE: .irbrc
================================================
def reload!
# Undefine FactoryBot so we can reload constants and fresh code
Object.send(:remove_const, :FactoryBot) if Object.const_defined?(:FactoryBot)
# Remove all files from the 'loaded' register
$LOADED_FEATURES.delete_if { |path| path.match?(/factory_bot/) }
# re-load it again
require "factory_bot"
puts "\nfactory_bot reloaded!\n\n"
true
end
================================================
FILE: .rspec
================================================
--format progress
--color
--require spec_helper
================================================
FILE: .simplecov
================================================
SimpleCov.start do
add_filter "/spec/"
add_filter "/tmp/"
end
================================================
FILE: .standard.yml
================================================
ruby_version: "3.0"
parallel: true
format: progress
================================================
FILE: .standard_todo.yml
================================================
# Auto generated files with errors to ignore.
# Remove from this list as you refactor files.
---
ignore:
- lib/factory_bot/linter.rb:
- Lint/SharedMutableDefault
================================================
FILE: .yardopts
================================================
lib/**/*.rb
-
GETTING_STARTED.md
CONTRIBUTING.md
NAME.md
LICENSE
================================================
FILE: Appraisals
================================================
appraise "6.1" do
gem "activerecord", "~> 6.1.0"
gem "activerecord-jdbcsqlite3-adapter", "~> 61.0", platforms: [:jruby]
gem "sqlite3", "~> 1.4", platforms: [:ruby]
gem "concurrent-ruby", "< 1.3.5"
end
appraise "7.0" do
gem "activerecord", "~> 7.0.0"
gem "activerecord-jdbcsqlite3-adapter", "~> 70.0", platforms: [:jruby]
gem "sqlite3", "~> 1.4", platforms: [:ruby]
gem "concurrent-ruby", "< 1.3.5"
end
appraise "7.1" do
gem "activerecord", "~> 7.1.0"
# When version 71 is released, uncomment this and also allow it in the GitHub
# Action build workflow.
# gem "activerecord-jdbcsqlite3-adapter", "~> 71.0", platforms: [:jruby]
gem "sqlite3", "~> 1.4", platforms: [:ruby]
end
appraise "7.2" do
gem "activerecord", "~> 7.2.0"
# When version 71 is released, uncomment this and also allow it in the GitHub
# Action build workflow.
# gem "activerecord-jdbcsqlite3-adapter", "~> 71.0", platforms: [:jruby]
gem "sqlite3", platforms: [:ruby]
end
appraise "main" do
gem "activerecord", git: "https://github.com/rails/rails.git", branch: "main"
gem "activerecord-jdbcsqlite3-adapter", "~> 70.0", platforms: [:jruby]
gem "sqlite3", platforms: [:ruby]
end
================================================
FILE: CODEOWNERS
================================================
# Lines starting with '#' are comments.
# Each line is a file pattern followed by one or more owners.
# More details are here: https://help.github.com/articles/about-codeowners/
# The '*' pattern is global owners.
# Order is important. The last matching pattern has the most precedence.
# The folders are ordered as follows:
# In each subsection folders are ordered first by depth, then alphabetically.
# This should make it easy to add new rules without breaking existing ones.
# Global rule:
* @neilvcarvalho @vburzynski
================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Code of conduct
By participating in this project, you agree to abide by the
[thoughtbot code of conduct][1].
[1]: https://thoughtbot.com/open-source-code-of-conduct
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to Factory Bot
We love pull requests from everyone. By participating in this project, you
agree to abide by the thoughtbot [code of conduct].
[code of conduct]: https://thoughtbot.com/open-source-code-of-conduct
Here are some ways *you* can contribute:
* by using alpha, beta, and prerelease versions
* by reporting bugs
* by suggesting new features
* by writing or editing documentation
* by writing specifications
* by writing code ( **no patch is too small** : fix typos, add comments, etc. )
* by refactoring code
* by closing [issues][]
* by reviewing patches
[issues]: https://github.com/thoughtbot/factory_bot/issues
## Submitting an Issue
* We use the [GitHub issue tracker][issues] to track bugs and features.
* Before submitting a bug report or feature request, check to make sure it hasn't
already been submitted.
* When submitting a bug report, please include a [reproduction script] and any
other details that may be necessary to reproduce the bug, including your gem
version, Ruby version, and operating system.
## Cleaning up issues
* Issues that have no response from the submitter will be closed after 30 days.
* Issues will be closed once they're assumed to be fixed or answered. If the
maintainer is wrong, it can be opened again.
* If your issue is closed by mistake, please understand and explain the issue.
We will happily reopen the issue.
## Submitting a Pull Request
1. [Fork][fork] the [official repository][repo].
1. [Create a topic branch.][branch]
1. Implement your feature or bug fix.
1. Add, commit, and push your changes.
1. [Submit a pull request.][pr]
### Notes
* Please add tests if you changed code. Contributions without tests won't be accepted.
* If you don't know how to add tests, please put in a PR and leave a comment
asking for help. We love helping!
* Please don't update the Gem version.
## Setting up
```sh
bundle install
```
## Running the test suite
The default rake task will run the full test suite and [standard]:
```sh
bundle exec rake
```
You can also run a single group of tests (unit, spec, or feature)
```sh
bundle exec rake spec:unit
bundle exec rake spec:acceptance
bundle exec rake features
```
To run an individual rspec test, you can provide a path and line number:
```sh
bundle exec rspec spec/path/to/spec.rb:123
```
You can run tests with a specific version of rails via [appraisal]. To run
the default rake task against Rails 6, for example:
```sh
bundle exec appraisal 6.0 rake
```
## Formatting
Use [standard] to automatically format your code:
```sh
bundle exec rake standard:fix
```
[repo]: https://github.com/thoughtbot/factory_bot/tree/main
[fork]: https://help.github.com/articles/fork-a-repo/
[branch]: https://help.github.com/articles/creating-and-deleting-branches-within-your-repository/
[pr]: https://help.github.com/articles/using-pull-requests/
[standard]: https://github.com/testdouble/standard
[appraisal]: https://github.com/thoughtbot/appraisal
[reproduction script]: https://github.com/thoughtbot/factory_bot/blob/main/.github/REPRODUCTION_SCRIPT.rb
Inspired by https://github.com/middleman/middleman-heroku/blob/master/CONTRIBUTING.md
================================================
FILE: GETTING_STARTED.md
================================================
**Deprecated**
See our extensive reference, guides, and cookbook in [the factory_bot book][].
For information on integrations with third party libraries, such as RSpec or
Rails, see [the factory_bot wiki][].
We also have [a detailed introductory video][], available for free on Upcase.
[a detailed introductory video]: https://upcase.com/videos/factory-bot?utm_source=github&utm_medium=open-source&utm_campaign=factory-girl
[the factory_bot book]: https://thoughtbot.github.io/factory_bot
[the factory_bot wiki]: https://github.com/thoughtbot/factory_bot/wiki
This document is deprecated and preserved for historical use. It may disappear
at any time.
Getting Started
===============
- [Setup](#setup)
- [Update Your Gemfile](#update-your-gemfile)
- [Configure your test suite](#configure-your-test-suite)
- [RSpec](#rspec)
- [Test::Unit](#testunit)
- [Cucumber](#cucumber)
- [Spinach](#spinach)
- [Minitest](#minitest)
- [Minitest::Spec](#minitestspec)
- [minitest-rails](#minitest-rails)
- [Defining factories](#defining-factories)
- [Factory name and attributes](#factory-name-and-attributes)
- [Specifying the class explicitly](#specifying-the-class-explicitly)
- [Hash attributes](#hash-attributes)
- [Best practices](#best-practices)
- [Definition file paths](#definition-file-paths)
- [Static Attributes](#static-attributes)
- [Using factories](#using-factories)
- [Build strategies](#build-strategies)
- [Attribute overrides](#attribute-overrides)
- [build\_stubbed and Marshal.dump](#build_stubbed-and-marshaldump)
- [Aliases](#aliases)
- [Dependent Attributes](#dependent-attributes)
- [Transient Attributes](#transient-attributes)
- [With other attributes](#with-other-attributes)
- [With attributes\_for](#with-attributes_for)
- [With callbacks](#with-callbacks)
- [With associations](#with-associations)
- [Method Name / Reserved Word Attributes](#method-name--reserved-word-attributes)
- [Inheritance](#inheritance)
- [Nested factories](#nested-factories)
- [Assigning parent explicitly](#assigning-parent-explicitly)
- [Best practices](#best-practices-1)
- [Associations](#associations)
- [Implicit definition](#implicit-definition)
- [Explicit definition](#explicit-definition)
- [Inline definition](#inline-definition)
- [Specifying the factory](#specifying-the-factory)
- [Overriding attributes](#overriding-attributes)
- [Association overrides](#association-overrides)
- [Build strategies](#build-strategies-1)
- [has\_many associations](#has_many-associations)
- [has\_and\_belongs\_to\_many associations](#has_and_belongs_to_many-associations)
- [Polymorphic associations](#polymorphic-associations)
- [Interconnected associations](#interconnected-associations)
- [Sequences](#sequences)
- [Global sequences](#global-sequences)
- [With dynamic attributes](#with-dynamic-attributes)
- [As implicit attributes](#as-implicit-attributes)
- [Inline sequences](#inline-sequences)
- [Initial value](#initial-value)
- [Without a block](#without-a-block)
- [Aliases](#aliases-1)
- [Rewinding](#rewinding)
- [Uniqueness](#uniqueness)
- [Traits](#traits)
- [Defining traits](#defining-traits)
- [As implicit attributes](#as-implicit-attributes-1)
- [Attribute precedence](#attribute-precedence)
- [In child factories](#in-child-factories)
- [As mixins](#as-mixins)
- [Using traits](#using-traits)
- [With associations](#with-associations-1)
- [Traits within traits](#traits-within-traits)
- [With transient attributes](#with-transient-attributes)
- [Enum traits](#enum-traits)
- [Callbacks](#callbacks)
- [Default callbacks](#default-callbacks)
- [Multiple callbacks](#multiple-callbacks)
- [Global callbacks](#global-callbacks)
- [Symbol#to\_proc](#symbolto_proc)
- [Modifying factories](#modifying-factories)
- [Building or Creating Multiple Records](#building-or-creating-multiple-records)
- [Linting Factories](#linting-factories)
- [Custom Construction](#custom-construction)
- [Custom Strategies](#custom-strategies)
- [Custom Callbacks](#custom-callbacks)
- [Custom Methods to Persist Objects](#custom-methods-to-persist-objects)
- [ActiveSupport Instrumentation](#activesupport-instrumentation)
- [Rails Preloaders and RSpec](#rails-preloaders-and-rspec)
- [Using Without Bundler](#using-without-bundler)
Setup
-----
### Update Your Gemfile
If you're using Rails:
```ruby
gem "factory_bot_rails"
```
If you're *not* using Rails:
```ruby
gem "factory_bot"
```
### Configure your test suite
#### RSpec
If you're using Rails, add the following configuration to
`spec/support/factory_bot.rb` and be sure to require that file in
`rails_helper.rb`:
```ruby
RSpec.configure do |config|
config.include FactoryBot::Syntax::Methods
end
```
If you're *not* using Rails:
```ruby
RSpec.configure do |config|
config.include FactoryBot::Syntax::Methods
config.before(:suite) do
FactoryBot.find_definitions
end
end
```
#### Test::Unit
```ruby
class Test::Unit::TestCase
include FactoryBot::Syntax::Methods
end
```
#### Cucumber
```ruby
# env.rb (Rails example location - RAILS_ROOT/features/support/env.rb)
World(FactoryBot::Syntax::Methods)
```
#### Spinach
```ruby
class Spinach::FeatureSteps
include FactoryBot::Syntax::Methods
end
```
#### Minitest
```ruby
class Minitest::Unit::TestCase
include FactoryBot::Syntax::Methods
end
```
#### Minitest::Spec
```ruby
class Minitest::Spec
include FactoryBot::Syntax::Methods
end
```
#### minitest-rails
```ruby
class ActiveSupport::TestCase
include FactoryBot::Syntax::Methods
end
```
If you do not include `FactoryBot::Syntax::Methods` in your test suite, then all
factory\_bot methods will need to be prefaced with `FactoryBot`.
Defining factories
------------------
### Factory name and attributes
Each factory has a name and a set of attributes. The name is used to guess the
class of the object by default:
```ruby
# This will guess the User class
FactoryBot.define do
factory :user do
first_name { "John" }
last_name { "Doe" }
admin { false }
end
end
```
### Specifying the class explicitly
It is also possible to explicitly specify the class:
```ruby
# This will use the User class (otherwise Admin would have been guessed)
factory :admin, class: "User"
```
Explicit specification of the class, _with the full namespace_, is necessary when defining factories for classes nested within other modules or classes:
```ruby
# foo/bar.rb
module Foo
class Bar
...
end
end
# factories.rb
FactoryBot.define do
factory :bar, class: 'Foo::Bar' do
...
end
end
```
If the full namespace is not provided in the `factory` statement, you will receive a `NameError: uninitialized constant Bar` error.
You can pass a constant as well, if the constant is available (note that this
can cause test performance problems in large Rails applications, since
referring to the constant will cause it to be eagerly loaded).
```ruby
factory :access_token, class: User
```
### Hash attributes
Because of the block syntax in Ruby, defining attributes as `Hash`es (for
serialized/JSON columns, for example) requires two sets of curly brackets:
```ruby
factory :program do
configuration { { auto_resolve: false, auto_define: true } }
end
```
### Best practices
It is recommended that you have one factory for each class that provides
the simplest set of attributes necessary to create an instance of that class. If
you're creating ActiveRecord objects, that means that you should only provide
attributes that are required through validations and that do not have defaults.
Other factories can be created through inheritance to cover common scenarios for
each class.
Attempting to define multiple factories with the same name will raise an error.
### Definition file paths
Factories can be defined anywhere, but will be automatically loaded after
calling `FactoryBot.find_definitions` if factories are defined in files at the
following locations:
factories.rb
factories/**/*.rb
test/factories.rb
test/factories/**/*.rb
spec/factories.rb
spec/factories/**/*.rb
### Static Attributes
Static attributes (without a block) are no longer available in factory\_bot 5.
You can read more about the decision to remove them in
[this blog post](https://robots.thoughtbot.com/deprecating-static-attributes-in-factory_bot-4-11).
Using factories
---------------
### Build strategies
factory\_bot supports several different build strategies: build, create,
attributes\_for and build\_stubbed:
```ruby
# Returns a User instance that's not saved
user = build(:user)
# Returns a saved User instance
user = create(:user)
# Returns a hash of attributes that can be used to build a User instance
attrs = attributes_for(:user)
# Integrates with Ruby 3.0's support for pattern matching assignment
attributes_for(:user) => {email:, name:, **attrs}
# Returns an object with all defined attributes stubbed out
stub = build_stubbed(:user)
# Passing a block to any of the methods above will yield the return object
create(:user) do |user|
user.posts.create(attributes_for(:post))
end
```
### Attribute overrides
No matter which strategy is used, it's possible to override the defined
attributes by passing a Hash:
```ruby
# Build a User instance and override the first_name property
user = build(:user, first_name: "Joe")
user.first_name
# => "Joe"
```
Overriding associations is also supported:
```ruby
account = build(:account, :deluxe)
friends = build_list(:user, 2)
user = build(:user, account: account, friends: friends)
```
Ruby 3.1's support for [omitting values][] from `Hash` literals dovetails with
attribute overrides and provides an opportunity to limit the repetition of
variable names:
```ruby
account = build(:account, :deluxe)
friends = build_list(:user, 2)
# The keyword arguments correspond to local variable names, so omit their values
user = build(:user, account:, friends:)
```
[omitting values]: https://docs.ruby-lang.org/en/3.1/syntax/literals_rdoc.html#label-Hash+Literals
### build_stubbed and Marshal.dump
Note that objects created with `build_stubbed` cannot be serialized with
`Marshal.dump`, since factory\_bot defines singleton methods on these objects.
Aliases
-------
factory\_bot allows you to define aliases to existing factories to make them
easier to re-use. This could come in handy when, for example, your Post object
has an author attribute that actually refers to an instance of a User class.
While normally factory\_bot can infer the factory name from the association name,
in this case it will look for an author factory in vain. So, alias your user
factory so it can be used under alias names.
```ruby
factory :user, aliases: [:author, :commenter] do
first_name { "John" }
last_name { "Doe" }
date_of_birth { 18.years.ago }
end
factory :post do
# The alias allows us to write author instead of
# association :author, factory: :user
author
title { "How to read a book effectively" }
body { "There are five steps involved." }
end
factory :comment do
# The alias allows us to write commenter instead of
# association :commenter, factory: :user
commenter
body { "Great article!" }
end
```
Dependent Attributes
--------------------
Attributes can be based on the values of other attributes using the evaluator
that is yielded to dynamic attribute blocks:
```ruby
factory :user do
first_name { "Joe" }
last_name { "Blow" }
email { "#{first_name}.#{last_name}@example.com".downcase }
end
create(:user, last_name: "Doe").email
# => "joe.doe@example.com"
```
Transient Attributes
--------------------
Transient attributes are attributes only available within the factory definition, and not set on the object being built. This allows for more complex logic inside factories.
### With other attributes
There may be times where your code can be DRYed up by passing in transient
attributes to factories. You can access transient attributes within other
attributes (see [Dependent Attributes](#dependent-attributes)):
```ruby
factory :user do
transient do
rockstar { true }
end
name { "John Doe#{" - Rockstar" if rockstar}" }
end
create(:user).name
#=> "John Doe - ROCKSTAR"
create(:user, rockstar: false).name
#=> "John Doe"
```
### With attributes_for
Transient attributes will be ignored within attributes\_for and won't be set on
the model, even if the attribute exists or you attempt to override it.
### With callbacks
If you need to access the evaluator in a factory\_bot callback,
you'll need to declare a second block argument (for the evaluator) and access
transient attributes from there.
```ruby
factory :user do
transient do
upcased { false }
end
name { "John Doe" }
after(:create) do |user, evaluator|
user.name.upcase! if evaluator.upcased
end
end
create(:user).name
#=> "John Doe"
create(:user, upcased: true).name
#=> "JOHN DOE"
```
### With associations
Transient [associations](#associations) are not supported in factory\_bot.
Associations within the transient block will be treated as regular,
non-transient associations.
If needed, you can generally work around this by building a factory within a
transient attribute:
```ruby
factory :post
factory :user do
transient do
post { build(:post) }
end
end
```
Method Name / Reserved Word Attributes
-------------------------------
If your attributes conflict with existing methods or reserved words (all methods in the [DefinitionProxy](https://github.com/thoughtbot/factory_bot/blob/main/lib/factory_bot/definition_proxy.rb) class) you can define them with `add_attribute`.
```ruby
factory :dna do
add_attribute(:sequence) { 'GATTACA' }
end
factory :payment do
add_attribute(:method) { 'paypal' }
end
```
Inheritance
-----------
### Nested factories
You can easily create multiple factories for the same class without repeating
common attributes by nesting factories:
```ruby
factory :post do
title { "A title" }
factory :approved_post do
approved { true }
end
end
approved_post = create(:approved_post)
approved_post.title # => "A title"
approved_post.approved # => true
```
### Assigning parent explicitly
You can also assign the parent explicitly:
```ruby
factory :post do
title { "A title" }
end
factory :approved_post, parent: :post do
approved { true }
end
```
### Best practices
As mentioned above, it's good practice to define a basic factory for each class
with only the attributes required to create it. Then, create more specific
factories that inherit from this basic parent. Factory definitions are still
code, so keep them DRY.
Associations
------------
### Implicit definition
It's possible to set up associations within factories. If the factory name is
the same as the association name, the factory name can be left out.
```ruby
factory :post do
# ...
author
end
```
### Explicit definition
You can define associations explicitly. This can be handy especially when
[Overriding attributes](#overriding-attributes)
```ruby
factory :post do
# ...
association :author
end
```
### Inline definition
You can also define associations inline within regular attributes,
but note that the value will be `nil`
when using the `attributes_for` strategy.
```ruby
factory :post do
# ...
author { association :author }
end
```
### Specifying the factory
You can specify a different factory (although [Aliases](#aliases) might also
help you out here).
Implicitly:
```ruby
factory :post do
# ...
author factory: :user
end
```
Explicitly:
```ruby
factory :post do
# ...
association :author, factory: :user
end
```
Inline:
```ruby
factory :post do
# ...
author { association :user }
end
```
### Overriding attributes
You can also override attributes.
Implicitly:
```ruby
factory :post do
# ...
author factory: :author, last_name: "Writely"
end
```
Explicitly:
```ruby
factory :post do
# ...
association :author, last_name: "Writely"
end
```
Or inline using attributes from the factory:
```ruby
factory :post do
# ...
author_last_name { "Writely" }
author { association :author, last_name: author_last_name }
end
```
### Association overrides
Attribute overrides can be used to link associated objects:
```ruby
FactoryBot.define do
factory :author do
name { 'Taylor' }
end
factory :post do
author
end
end
eunji = build(:author, name: 'Eunji')
post = build(:post, author: eunji)
```
### Build strategies
In factory\_bot 5, associations default to using the same build strategy as
their parent object:
```ruby
FactoryBot.define do
factory :author
factory :post do
author
end
end
post = build(:post)
post.new_record? # => true
post.author.new_record? # => true
post = create(:post)
post.new_record? # => false
post.author.new_record? # => false
```
This is different than the default behavior for previous versions of
factory\_bot, where the association strategy would not always match the strategy
of the parent object. If you want to continue using the old behavior, you can
set the `use_parent_strategy` configuration option to `false`.
```ruby
FactoryBot.use_parent_strategy = false
# Builds and saves a User and a Post
post = create(:post)
post.new_record? # => false
post.author.new_record? # => false
# Builds and saves a User, and then builds but does not save a Post
post = build(:post)
post.new_record? # => true
post.author.new_record? # => false
```
To not save the associated object, specify `strategy: :build` in the factory:
```ruby
FactoryBot.use_parent_strategy = false
factory :post do
# ...
association :author, factory: :user, strategy: :build
end
# Builds a User, and then builds a Post, but does not save either
post = build(:post)
post.new_record? # => true
post.author.new_record? # => true
```
Please note that the `strategy: :build` option must be passed to an explicit call to `association`,
and cannot be used with implicit associations:
```ruby
factory :post do
# ...
author strategy: :build # <<< this does *not* work; causes author_id to be nil
```
### has_many associations
There are a few ways to generate data for a `has_many` relationship. The
simplest approach is to write a helper method in plain Ruby to tie together the
different records:
```ruby
FactoryBot.define do
factory :post do
title { "Through the Looking Glass" }
user
end
factory :user do
name { "Rachel Sanchez" }
end
end
def user_with_posts(posts_count: 5)
FactoryBot.create(:user) do |user|
FactoryBot.create_list(:post, posts_count, user: user)
end
end
create(:user).posts.length # 0
user_with_posts.posts.length # 5
user_with_posts(posts_count: 15).posts.length # 15
```
If you prefer to keep the object creation fully within factory\_bot, you can
build the posts in an `after(:create)` callback.
```ruby
FactoryBot.define do
factory :post do
title { "Through the Looking Glass" }
user
end
factory :user do
name { "John Doe" }
# user_with_posts will create post data after the user has been created
factory :user_with_posts do
# posts_count is declared as a transient attribute available in the
# callback via the evaluator
transient do
posts_count { 5 }
end
# the after(:create) yields two values; the user instance itself and the
# evaluator, which stores all values from the factory, including transient
# attributes; `create_list`'s second argument is the number of records
# to create and we make sure the user is associated properly to the post
after(:create) do |user, evaluator|
create_list(:post, evaluator.posts_count, user: user)
# You may need to reload the record here, depending on your application
user.reload
end
end
end
end
create(:user).posts.length # 0
create(:user_with_posts).posts.length # 5
create(:user_with_posts, posts_count: 15).posts.length # 15
```
Or, for a solution that works with `build`, `build_stubbed`, and `create`
(although it doesn't work well with `attributes_for`), you can use inline
associations:
```ruby
FactoryBot.define do
factory :post do
title { "Through the Looking Glass" }
user
end
factory :user do
name { "Taylor Kim" }
factory :user_with_posts do
posts { [association(:post)] }
end
end
end
create(:user).posts.length # 0
create(:user_with_posts).posts.length # 1
build(:user_with_posts).posts.length # 1
build_stubbed(:user_with_posts).posts.length # 1
```
For more flexibility you can combine this with the `posts_count` transient
attribute from the callback example:
```ruby
FactoryBot.define do
factory :post do
title { "Through the Looking Glass" }
user
end
factory :user do
name { "Adiza Kumato" }
factory :user_with_posts do
transient do
posts_count { 5 }
end
posts do
Array.new(posts_count) { association(:post) }
end
end
end
end
create(:user_with_posts).posts.length # 5
create(:user_with_posts, posts_count: 15).posts.length # 15
build(:user_with_posts, posts_count: 15).posts.length # 15
build_stubbed(:user_with_posts, posts_count: 15).posts.length # 15
```
### has_and_belongs_to_many associations
Generating data for a `has_and_belongs_to_many` relationship is very similar
to the above `has_many` relationship, with a small change: you need to pass an
array of objects to the model's pluralized attribute name rather than a single
object to the singular version of the attribute name.
```ruby
def profile_with_languages(languages_count: 2)
FactoryBot.create(:profile) do |profile|
FactoryBot.create_list(:language, languages_count, profiles: [profile])
end
end
```
Or with the callback approach:
```ruby
factory :profile_with_languages do
transient do
languages_count { 2 }
end
after(:create) do |profile, evaluator|
create_list(:language, evaluator.languages_count, profiles: [profile])
profile.reload
end
end
```
Or the inline association approach (note the use of the `instance` method here
to refer to the profile being built):
```ruby
factory :profile_with_languages do
transient do
languages_count { 2 }
end
languages do
Array.new(languages_count) do
association(:language, profiles: [instance])
end
end
end
```
### Polymorphic associations
Polymorphic associations can be handled with traits:
```ruby
FactoryBot.define do
factory :video
factory :photo
factory :comment do
for_photo # default to the :for_photo trait if none is specified
trait :for_video do
association :commentable, factory: :video
end
trait :for_photo do
association :commentable, factory: :photo
end
end
end
```
This allows us to do:
```ruby
create(:comment)
create(:comment, :for_video)
create(:comment, :for_photo)
```
### Interconnected associations
There are limitless ways objects might be interconnected, and
factory\_bot may not always be suited to handle those relationships. In some
cases it makes sense to use factory\_bot to build each individual object, and
then to write helper methods in plain Ruby to tie those objects together.
That said, some more complex, interconnected relationships can be built in factory\_bot
using inline associations with reference to the `instance` being built.
Let's say your models look like this, where an associated `Student` and
`Profile` should both belong to the same `School`:
```ruby
class Student < ApplicationRecord
belongs_to :school
has_one :profile
end
class Profile < ApplicationRecord
belongs_to :school
belongs_to :student
end
class School < ApplicationRecord
has_many :students
has_many :profiles
end
```
We can ensure the student and profile are connected to each other and to the
same school with a factory like this:
```ruby
FactoryBot.define do
factory :student do
school
profile { association :profile, student: instance, school: school }
end
factory :profile do
school
student { association :student, profile: instance, school: school }
end
factory :school
end
```
Note that this approach works with `build`, `build_stubbed`, and `create`, but
the associations will return `nil` when using `attributes_for`.
Also, note that if you assign any attributes inside a custom `initialize_with`
(e.g. `initialize_with { new(**attributes) }`), those attributes should not refer to `instance`,
since it will be `nil`.
Sequences
---------
### Global sequences
Unique values in a specific format (for example, e-mail addresses) can be
generated using sequences. Sequences are defined by calling `sequence` in a
definition block, and values in a sequence are generated by calling
`generate`:
```ruby
# Defines a new sequence
FactoryBot.define do
sequence :email do |n|
"person#{n}@example.com"
end
end
generate :email
# => "person1@example.com"
generate :email
# => "person2@example.com"
```
### With dynamic attributes
Sequences can be used in dynamic attributes:
```ruby
factory :invite do
invitee { generate(:email) }
end
```
### As implicit attributes
Or as implicit attributes:
```ruby
factory :user do
email # Same as `email { generate(:email) }`
end
```
Note that defining sequences as implicit attributes will not work if you have a
factory with the same name as the sequence.
### Inline sequences
And it's also possible to define an in-line sequence that is only used in
a particular factory:
```ruby
factory :user do
sequence(:email) { |n| "person#{n}@example.com" }
end
```
With Ruby 2.7's support for [numbered parameters][], inline definitions can be
even more abbreviated:
```ruby
factory :user do
sequence(:email) { "person#{_1}@example.com" }
end
```
[numbered parameters]: https://ruby-doc.org/core-2.7.1/Proc.html#class-Proc-label-Numbered+parameters
### Initial value
You can override the initial value. Any value that responds to the `#next`
method will work (e.g. 1, 2, 3, 'a', 'b', 'c')
```ruby
factory :user do
sequence(:email, 1000) { |n| "person#{n}@example.com" }
end
```
### Without a block
Without a block, the value will increment itself, starting at its initial value:
```ruby
factory :post do
sequence(:position)
end
```
Please note, that the value for the sequence could be any Enumerable instance,
as long as it responds to `#next`:
```ruby
factory :task do
sequence :priority, %i[low medium high urgent].cycle
end
```
### Aliases
Sequences can also have aliases. The sequence aliases share the same counter:
```ruby
factory :user do
sequence(:email, 1000, aliases: [:sender, :receiver]) { |n| "person#{n}@example.com" }
end
# will increase value counter for :email which is shared by :sender and :receiver
generate(:sender)
```
Define aliases and use default value (1) for the counter
```ruby
factory :user do
sequence(:email, aliases: [:sender, :receiver]) { |n| "person#{n}@example.com" }
end
```
Setting the value:
```ruby
factory :user do
sequence(:email, 'a', aliases: [:sender, :receiver]) { |n| "person#{n}@example.com" }
end
```
The value just needs to support the `#next` method. Here the next value will be 'a', then 'b', etc.
### Rewinding
Sequences can also be rewound with `FactoryBot.rewind_sequences`:
```ruby
sequence(:email) {|n| "person#{n}@example.com" }
generate(:email) # "person1@example.com"
generate(:email) # "person2@example.com"
generate(:email) # "person3@example.com"
FactoryBot.rewind_sequences
generate(:email) # "person1@example.com"
```
This rewinds all registered sequences.
### Uniqueness
When working with uniqueness constraints, be careful not to pass in override values that will conflict with the generated sequence values.
In this example the email will be the same for both users. If email must be unique, this code will error:
```ruby
factory :user do
sequence(:email) { |n| "person#{n}@example.com" }
end
FactoryBot.create(:user, email: "person1@example.com")
FactoryBot.create(:user)
```
Traits
------
### Defining traits
Traits allow you to group attributes together and then apply them
to any factory.
```ruby
factory :user, aliases: [:author]
factory :story do
title { "My awesome story" }
author
trait :published do
published { true }
end
trait :unpublished do
published { false }
end
trait :week_long_publishing do
start_at { 1.week.ago }
end_at { Time.now }
end
trait :month_long_publishing do
start_at { 1.month.ago }
end_at { Time.now }
end
factory :week_long_published_story, traits: [:published, :week_long_publishing]
factory :month_long_published_story, traits: [:published, :month_long_publishing]
factory :week_long_unpublished_story, traits: [:unpublished, :week_long_publishing]
factory :month_long_unpublished_story, traits: [:unpublished, :month_long_publishing]
end
```
### As implicit attributes
Traits can be used as implicit attributes:
```ruby
factory :week_long_published_story_with_title, parent: :story do
published
week_long_publishing
title { "Publishing that was started at #{start_at}" }
end
```
Note that defining traits as implicit attributes will not work if you have a
factory or sequence with the same name as the trait.
### Attribute precedence
Traits that define the same attributes won't raise AttributeDefinitionErrors;
the trait that defines the attribute latest gets precedence.
```ruby
factory :user do
name { "Friendly User" }
login { name }
trait :active do
name { "John Doe" }
status { :active }
login { "#{name} (active)" }
end
trait :inactive do
name { "Jane Doe" }
status { :inactive }
login { "#{name} (inactive)" }
end
trait :admin do
admin { true }
login { "admin-#{name}" }
end
factory :active_admin, traits: [:active, :admin] # login will be "admin-John Doe"
factory :inactive_admin, traits: [:admin, :inactive] # login will be "Jane Doe (inactive)"
end
```
### In child factories
You can override individual attributes granted by a trait in a child factory:
```ruby
factory :user do
name { "Friendly User" }
login { name }
trait :active do
name { "John Doe" }
status { :active }
login { "#{name} (M)" }
end
factory :brandon do
active
name { "Brandon" }
end
end
```
### As mixins
Traits can be defined outside of factories and used as mixins to compose shared attributes
```ruby
FactoryBot.define do
trait :timestamps do
created_at { 8.days.ago }
updated_at { 4.days.ago }
end
factory :user, traits: [:timestamps] do
username { "john_doe" }
end
factory :post do
timestamps
title { "Traits rock" }
end
end
```
### Using traits
Traits can also be passed in as a list of symbols when you construct an instance
from factory\_bot.
```ruby
factory :user do
name { "Friendly User" }
trait :active do
name { "John Doe" }
status { :active }
end
trait :admin do
admin { true }
end
end
# creates an admin user with :active status and name "Jon Snow"
create(:user, :admin, :active, name: "Jon Snow")
```
This ability works with `build`, `build_stubbed`, `attributes_for`, and `create`.
`create_list` and `build_list` methods are supported as well. Just remember to pass
the number of instances to create/build as second parameter, as documented in the
"Building or Creating Multiple Records" section of this file.
```ruby
factory :user do
name { "Friendly User" }
trait :admin do
admin { true }
end
end
# creates 3 admin users with :active status and name "Jon Snow"
create_list(:user, 3, :admin, :active, name: "Jon Snow")
```
### With associations
Traits can be used with associations easily too:
```ruby
factory :user do
name { "Friendly User" }
trait :admin do
admin { true }
end
end
factory :post do
association :user, :admin, name: 'John Doe'
end
# creates an admin user with name "John Doe"
create(:post).user
```
When you're using association names that're different than the factory:
```ruby
factory :user do
name { "Friendly User" }
trait :admin do
admin { true }
end
end
factory :post do
association :author, :admin, factory: :user, name: 'John Doe'
# or
association :author, factory: [:user, :admin], name: 'John Doe'
end
# creates an admin user with name "John Doe"
create(:post).author
```
### Traits within traits
Traits can be used within other traits to mix in their attributes.
```ruby
factory :order do
trait :completed do
completed_at { 3.days.ago }
end
trait :refunded do
completed
refunded_at { 1.day.ago }
end
end
```
### With transient attributes
Finally, traits can accept transient attributes.
```ruby
factory :invoice do
trait :with_amount do
transient do
amount { 1 }
end
after(:create) do |invoice, evaluator|
create :line_item, invoice: invoice, amount: evaluator.amount
end
end
end
create :invoice, :with_amount, amount: 2
```
### Enum traits
Given an Active Record model with an enum attribute:
```ruby
class Task < ActiveRecord::Base
enum status: {queued: 0, started: 1, finished: 2}
end
```
factory\_bot will automatically define traits for each possible value of the
enum:
```ruby
FactoryBot.define do
factory :task
end
FactoryBot.build(:task, :queued)
FactoryBot.build(:task, :started)
FactoryBot.build(:task, :finished)
```
Writing the traits out manually would be cumbersome, and is not necessary:
```ruby
FactoryBot.define do
factory :task do
trait :queued do
status { :queued }
end
trait :started do
status { :started }
end
trait :finished do
status { :finished }
end
end
end
```
If automatically defining traits for enum attributes on every factory is not
desired, it is possible to disable the feature by setting
`FactoryBot.automatically_define_enum_traits = false`
In that case, it is still possible to explicitly define traits for an enum
attribute in a particular factory:
```ruby
FactoryBot.automatically_define_enum_traits = false
FactoryBot.define do
factory :task do
traits_for_enum(:status)
end
end
```
It is also possible to use this feature for other enumerable values, not
specifically tied to Active Record enum attributes.
With an array:
```ruby
class Task
attr_accessor :status
end
FactoryBot.define do
factory :task do
traits_for_enum(:status, ["queued", "started", "finished"])
end
end
```
Or with a hash:
```ruby
class Task
attr_accessor :status
end
FactoryBot.define do
factory :task do
traits_for_enum(:status, { queued: 0, started: 1, finished: 2 })
end
end
```
Callbacks
---------
### Default callbacks
factory\_bot makes available four callbacks for injecting some code:
* after(:build) - called after a factory is built (via `FactoryBot.build`, `FactoryBot.create`)
* before(:create) - called before a factory is saved (via `FactoryBot.create`)
* after(:create) - called after a factory is saved (via `FactoryBot.create`)
* after(:stub) - called after a factory is stubbed (via `FactoryBot.build_stubbed`)
Examples:
```ruby
# Define a factory that calls the generate_hashed_password method after it is built
factory :user do
after(:build) { |user| generate_hashed_password(user) }
end
```
Note that you'll have an instance of the user in the block. This can be useful.
### Multiple callbacks
You can also define multiple types of callbacks on the same factory:
```ruby
factory :user do
after(:build) { |user| do_something_to(user) }
after(:create) { |user| do_something_else_to(user) }
end
```
Factories can also define any number of the same kind of callback. These
callbacks will be executed in the order they are specified:
```ruby
factory :user do
after(:create) { this_runs_first }
after(:create) { then_this }
end
```
Calling `create` will invoke both `after_build` and `after_create` callbacks.
Also, like standard attributes, child factories will inherit (and can also
define) callbacks from their parent factory.
Multiple callbacks can be assigned to run a block; this is useful when building
various strategies that run the same code (since there are no callbacks that are
shared across all strategies).
```ruby
factory :user do
callback(:after_stub, :before_create) { do_something }
after(:stub, :create) { do_something_else }
before(:create, :custom) { do_a_third_thing }
end
```
### Global callbacks
To override callbacks for all factories, define them within the
`FactoryBot.define` block:
```ruby
FactoryBot.define do
after(:build) { |object| puts "Built #{object}" }
after(:create) { |object| AuditLog.create(attrs: object.attributes) }
factory :user do
name { "John Doe" }
end
end
```
### Symbol#to_proc
You can call callbacks that rely on `Symbol#to_proc`:
```ruby
# app/models/user.rb
class User < ActiveRecord::Base
def confirm!
# confirm the user account
end
end
# spec/factories.rb
FactoryBot.define do
factory :user do
after :create, &:confirm!
end
end
create(:user) # creates the user and confirms it
```
Modifying factories
-------------------
If you're given a set of factories (say, from a gem developer) but want to
change them to fit into your application better, you can modify that factory
instead of creating a child factory and adding attributes there.
If a gem were to give you a User factory:
```ruby
FactoryBot.define do
factory :user do
full_name { "John Doe" }
sequence(:username) { |n| "user#{n}" }
password { "password" }
end
end
```
Instead of creating a child factory that added additional attributes:
```ruby
FactoryBot.define do
factory :application_user, parent: :user do
full_name { "Jane Doe" }
date_of_birth { 21.years.ago }
health { 90 }
end
end
```
You could modify that factory instead.
```ruby
FactoryBot.modify do
factory :user do
full_name { "Jane Doe" }
date_of_birth { 21.years.ago }
health { 90 }
end
end
```
When modifying a factory, you can change any of the attributes you want (aside from callbacks).
`FactoryBot.modify` must be called outside of a `FactoryBot.define` block as it operates on factories differently.
A caveat: you can only modify factories (not sequences or traits) and callbacks *still compound as they normally would*. So, if
the factory you're modifying defines an `after(:create)` callback, you defining an `after(:create)` won't override it, it'll just get run after the first callback.
Building or Creating Multiple Records
-------------------------------------
Sometimes, you'll want to create or build multiple instances of a factory at once.
```ruby
built_users = build_list(:user, 25)
created_users = create_list(:user, 25)
```
These methods will build or create a specific amount of factories and return them as an array.
To set the attributes for each of the factories, you can pass in a hash as you normally would.
```ruby
twenty_year_olds = build_list(:user, 25, date_of_birth: 20.years.ago)
```
In order to set different attributes for each factory, these methods may be passed a block, with the factory and the index as parameters:
```ruby
twenty_somethings = build_list(:user, 10) do |user, i|
user.date_of_birth = (20 + i).years.ago
end
```
`create_list` passes saved instances into the block. If you modify the instance, you must save it again:
```ruby
twenty_somethings = create_list(:user, 10) do |user, i|
user.date_of_birth = (20 + i).years.ago
user.save!
end
```
`build_stubbed_list` will give you fully stubbed out instances:
```ruby
stubbed_users = build_stubbed_list(:user, 25) # array of stubbed users
```
There's also a set of `*_pair` methods for creating two records at a time:
```ruby
built_users = build_pair(:user) # array of two built users
created_users = create_pair(:user) # array of two created users
```
If you need multiple attribute hashes, `attributes_for_list` will generate them:
```ruby
users_attrs = attributes_for_list(:user, 25) # array of attribute hashes
```
Linting Factories
-----------------
factory\_bot allows for linting known factories:
```ruby
FactoryBot.lint
```
`FactoryBot.lint` creates each factory and catches any exceptions raised
during the creation process. `FactoryBot::InvalidFactoryError` is raised with
a list of factories (and corresponding exceptions) for factories which could
not be created.
Recommended usage of `FactoryBot.lint`
is to run this in a task
before your test suite is executed.
Running it in a `before(:suite)`,
will negatively impact the performance
of your tests
when running single tests.
Example Rake task:
```ruby
# lib/tasks/factory_bot.rake
namespace :factory_bot do
desc "Verify that all FactoryBot factories are valid"
task lint: :environment do
if Rails.env.test?
conn = ActiveRecord::Base.connection
conn.transaction do
FactoryBot.lint
raise ActiveRecord::Rollback
end
else
system("bundle exec rake factory_bot:lint RAILS_ENV='test'")
fail if $?.exitstatus.nonzero?
end
end
end
```
After calling `FactoryBot.lint`, you'll likely want to clear out the
database, as records will most likely be created. The provided example above
uses an sql transaction and rollback to leave the database clean.
You can lint factories selectively by passing only factories you want linted:
```ruby
factories_to_lint = FactoryBot.factories.reject do |factory|
factory.name =~ /^old_/
end
FactoryBot.lint factories_to_lint
```
This would lint all factories that aren't prefixed with `old_`.
Traits can also be linted. This option verifies that each
and every trait of a factory generates a valid object on its own.
This is turned on by passing `traits: true` to the `lint` method:
```ruby
FactoryBot.lint traits: true
```
This can also be combined with other arguments:
```ruby
FactoryBot.lint factories_to_lint, traits: true
```
You can also specify the strategy used for linting:
```ruby
FactoryBot.lint strategy: :build
```
Verbose linting will include full backtraces for each error, which can be
helpful for debugging:
```ruby
FactoryBot.lint verbose: true
```
Custom Construction
-------------------
If you want to use factory\_bot to construct an object where some attributes
are passed to `initialize` or if you want to do something other than simply
calling `new` on your build class, you can override the default behavior by
defining `initialize_with` on your factory. Example:
```ruby
# user.rb
class User
attr_accessor :name, :email
def initialize(name)
@name = name
end
end
# factories.rb
sequence(:email) { |n| "person#{n}@example.com" }
factory :user do
name { "Jane Doe" }
email
initialize_with { new(name) }
end
build(:user).name # Jane Doe
```
Although factory\_bot is written to work with ActiveRecord out of the box, it
can also work with any Ruby class. For maximum compatibility with ActiveRecord,
the default initializer builds all instances by calling `new` on your build class
without any arguments. It then calls attribute writer methods to assign all the
attribute values. While that works fine for ActiveRecord, it actually doesn't
work for almost any other Ruby class.
You can override the initializer in order to:
* Build non-ActiveRecord objects that require arguments to `initialize`
* Use a method other than `new` to instantiate the instance
* Do wild things like decorate the instance after it's built
When using `initialize_with`, you don't have to declare the class itself when
calling `new`; however, any other class methods you want to call will have to
be called on the class explicitly.
For example:
```ruby
factory :user do
name { "John Doe" }
initialize_with { User.build_with_name(name) }
end
```
You can also access all public attributes within the `initialize_with` block
by calling `attributes`:
```ruby
factory :user do
transient do
comments_count { 5 }
end
name "John Doe"
initialize_with { new(**attributes) }
end
```
This will build a hash of all attributes to be passed to `new`. It won't
include transient attributes, but everything else defined in the factory will be
passed (associations, evaluated sequences, etc.)
You can define `initialize_with` for all factories by including it in the
`FactoryBot.define` block:
```ruby
FactoryBot.define do
initialize_with { new("Awesome first argument") }
end
```
When using `initialize_with`, attributes accessed from within the `initialize_with`
block are assigned *only* in the constructor; this equates to roughly the
following code:
```ruby
FactoryBot.define do
factory :user do
initialize_with { new(name) }
name { 'value' }
end
end
build(:user)
# runs
User.new('value')
```
This prevents duplicate assignment; in versions of factory\_bot before 4.0, it
would run this:
```ruby
FactoryBot.define do
factory :user do
initialize_with { new(name) }
name { 'value' }
end
end
build(:user)
# runs
user = User.new('value')
user.name = 'value'
```
Custom Strategies
-----------------
There are times where you may want to extend behavior of factory\_bot by
adding a custom build strategy.
Strategies define two methods: `association` and `result`. `association`
receives a `FactoryBot::FactoryRunner` instance, upon which you can call
`run`, overriding the strategy if you want. The second method, `result`,
receives a `FactoryBot::Evaluation` instance. It provides a way to trigger
callbacks (with `notify`), `object` or `hash` (to get the result instance or a
hash based on the attributes defined in the factory), and `create`, which
executes the `to_create` callback defined on the factory.
To understand how factory\_bot uses strategies internally, it's probably
easiest to just view the source for each of the four default strategies.
Here's an example of composing a strategy using
`FactoryBot::Strategy::Create` to build a JSON representation of your model.
```ruby
class JsonStrategy
def initialize
@strategy = FactoryBot.strategy_by_name(:create).new
end
delegate :association, to: :@strategy
def result(evaluation)
@strategy.result(evaluation).to_json
end
def to_sym
:json
end
end
```
For factory\_bot to recognize the new strategy, you can register it:
```ruby
FactoryBot.register_strategy(:json, JsonStrategy)
```
This allows you to call
```ruby
FactoryBot.json(:user)
```
Finally, you can override factory\_bot's own strategies if you'd like by
registering a new object in place of the strategies.
Custom Callbacks
----------------
Custom callbacks can be defined if you're using custom strategies:
```ruby
class JsonStrategy
def initialize
@strategy = FactoryBot.strategy_by_name(:create).new
end
delegate :association, to: :@strategy
def result(evaluation)
result = @strategy.result(evaluation)
evaluation.notify(:before_json, result)
result.to_json.tap do |json|
evaluation.notify(:after_json, json)
evaluation.notify(:make_json_awesome, json)
end
end
def to_sym
:json
end
end
FactoryBot.register_strategy(:json, JsonStrategy)
FactoryBot.define do
factory :user do
before(:json) { |user| do_something_to(user) }
after(:json) { |user_json| do_something_to(user_json) }
callback(:make_json_awesome) { |user_json| do_something_to(user_json) }
end
end
```
Custom Methods to Persist Objects
---------------------------------
By default, creating a record will call `save!` on the instance; since this
may not always be ideal, you can override that behavior by defining
`to_create` on the factory:
```ruby
factory :different_orm_model do
to_create { |instance| instance.persist! }
end
```
To disable the persistence method altogether on create, you can `skip_create`
for that factory:
```ruby
factory :user_without_database do
skip_create
end
```
To override `to_create` for all factories, define it within the
`FactoryBot.define` block:
```ruby
FactoryBot.define do
to_create { |instance| instance.persist! }
factory :user do
name { "John Doe" }
end
end
```
ActiveSupport Instrumentation
-----------------------------
In order to track what factories are created (and with what build strategy),
`ActiveSupport::Notifications` are included to provide a way to subscribe to
factories being compiled and run. One example would be to track factories based on a
threshold of execution time.
```ruby
ActiveSupport::Notifications.subscribe("factory_bot.run_factory") do |name, start, finish, id, payload|
execution_time_in_seconds = finish - start
if execution_time_in_seconds >= 0.5
$stderr.puts "Slow factory: #{payload[:name]} using strategy #{payload[:strategy]}"
end
end
```
Another example would be tracking all factories and how they're used
throughout your test suite. If you're using RSpec, it's as simple as adding a
`before(:suite)` and `after(:suite)`:
```ruby
factory_bot_results = {}
config.before(:suite) do
ActiveSupport::Notifications.subscribe("factory_bot.run_factory") do |name, start, finish, id, payload|
factory_name = payload[:name]
strategy_name = payload[:strategy]
factory_bot_results[factory_name] ||= {}
factory_bot_results[factory_name][strategy_name] ||= 0
factory_bot_results[factory_name][strategy_name] += 1
end
end
config.after(:suite) do
puts factory_bot_results
end
```
Another example could involve tracking the attributes and traits that factories are compiled with. If you're using RSpec, you could add `before(:suite)` and `after(:suite)` blocks that subscribe to `factory_bot.compile_factory` notifications:
```ruby
factory_bot_results = {}
config.before(:suite) do
ActiveSupport::Notifications.subscribe("factory_bot.compile_factory") do |name, start, finish, id, payload|
factory_name = payload[:name]
factory_class = payload[:class]
attributes = payload[:attributes]
traits = payload[:traits]
factory_bot_results[factory_class] ||= {}
factory_bot_results[factory_class][factory_name] = {
attributes: attributes.map(&:name)
traits: traits.map(&:name)
}
end
end
config.after(:suite) do
puts factory_bot_results
end
```
Rails Preloaders and RSpec
--------------------------
When running RSpec with a Rails preloader such as `spring` or `zeus`, it's possible
to encounter an `ActiveRecord::AssociationTypeMismatch` error when creating a factory
with associations, as below:
```ruby
FactoryBot.define do
factory :united_states, class: "Location" do
name { 'United States' }
association :location_group, factory: :north_america
end
factory :north_america, class: "LocationGroup" do
name { 'North America' }
end
end
```
The error occurs during the run of the test suite:
```
Failure/Error: united_states = create(:united_states)
ActiveRecord::AssociationTypeMismatch:
LocationGroup(#70251250797320) expected, got LocationGroup(#70251200725840)
```
The two possible solutions are to either run the suite without the preloader, or
to add `FactoryBot.reload` to the RSpec configuration, like so:
```ruby
RSpec.configure do |config|
config.before(:suite) { FactoryBot.reload }
end
```
Using Without Bundler
---------------------
If you're not using Bundler, be sure to have the gem installed and call:
```ruby
require 'factory_bot'
```
Once required, assuming you have a directory structure of `spec/factories` or
`test/factories`, all you'll need to do is run:
```ruby
FactoryBot.find_definitions
```
If you're using a separate directory structure for your factories, you can
change the definition file paths before trying to find definitions:
```ruby
FactoryBot.definition_file_paths = %w(custom_factories_directory)
FactoryBot.find_definitions
```
If you don't have a separate directory of factories and would like to define
them inline, that's possible as well:
```ruby
require 'factory_bot'
FactoryBot.define do
factory :user do
name { 'John Doe' }
date_of_birth { 21.years.ago }
end
end
```
================================================
FILE: Gemfile
================================================
source "https://rubygems.org"
gem "activerecord-jdbcsqlite3-adapter", platforms: [:jruby]
gem "sqlite3", platforms: [:ruby]
gemspec name: "factory_bot"
================================================
FILE: LICENSE
================================================
Copyright (c) 2008-2019 Joe Ferris and thoughtbot, inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
================================================
FILE: NAME.md
================================================
# Project Naming History
## Factory Girl
This library was [initially released](https://robots.thoughtbot.com/waiting-for-a-factory-girl)
in 2008 with the name "Factory Girl".
We chose the name as a nod in the direction of the [Factory method](https://en.wikipedia.org/wiki/Factory_method_pattern)
and [Object Mother](http://martinfowler.com/bliki/ObjectMother.html) software
patterns from the _Design Patterns_ book, and as a reference to the
[Rolling Stones song](https://www.youtube.com/watch?v=4jKix2DFlnA) of the same
name.
## Factory Bot
The name "Factory Girl" was confusing to some developers who encountered this
library, and offensive or problematic to others. In October 2017 we [renamed the library](https://robots.thoughtbot.com/factory_bot)
to "Factory Bot".
================================================
FILE: NEWS.md
================================================
# News
## 6.5.6 (October 22, 2025)
* Fix: Enforce association override precedence over trait foreign keys by @JinOketani in [#1768](https://github.com/thoughtbot/factory_bot/pull/1768)
* Build: Add ostruct as a development dependency by @ydah in [#1778](https://github.com/thoughtbot/factory_bot/pull/1778)
* Build: Bump standard from v1.44.0 to v1.51.1 by @ydah in [#1779](https://github.com/thoughtbot/factory_bot/pull/1779)
* Build: Add Ruby 3.4 to CI matrix by @ydah in [#1780](https://github.com/thoughtbot/factory_bot/pull/1780)
* Build: Remove unnecessary development dependencies by @ydah in [#1781](https://github.com/thoughtbot/factory_bot/pull/1781)
* Build: update gem versions and dependencies by @ydah in [#1782](https://github.com/thoughtbot/factory_bot/pull/1782)
* Build: revert removal of mutex_m by @vburzynski in [#1784](https://github.com/thoughtbot/factory_bot/pull/1784)
* Refactor: factory calculator cleanup by @vburzynski in [#1770](https://github.com/thoughtbot/factory_bot/pull/1770)
* Chore(ci): Bump actions/checkout from 4 to 5 by @dependabot[bot] in [#1765](https://github.com/thoughtbot/factory_bot/pull/1765)
* Chore(specs): tag slow specs by @vburzynski in [#1776](https://github.com/thoughtbot/factory_bot/pull/1776)
* Docs: Update RELEASING.md by @vburzynski in [#1763](https://github.com/thoughtbot/factory_bot/pull/1763)
* Docs: Update link to FactoryGirl upgrade guide by @imRohan in [#1769](https://github.com/thoughtbot/factory_bot/pull/1769)
* Docs: Fix some typos by @ydah in [#1783](https://github.com/thoughtbot/factory_bot/pull/1783)
* Docs(yard): resolve yard doc warnings by @vburzynski in [#1764](https://github.com/thoughtbot/factory_bot/pull/1764)
* Docs(yard): ruby syntax highlighting in yard docs by @djbender in [#1777](https://github.com/thoughtbot/factory_bot/pull/1777)
## 6.5.5 (August 15, 2025)
* Feat: Adds developer console features (CodeMeister)
* adds `bin/setup` to run bundle install
* adds `bin/console` to open an IRB console with factory_bot loaded
* adds a session method `reload!` will reload all gem files.
* Feat: Before(:all) and after(:all) callbacks added (CodeMeister)
* Feat: Adds support for before build callback (Mohammed Nasser and Neil Carvalho)
* Feat: Adds support for lazy loaded initial value sequences (AJ Esler)
* Fix: Refactors the removal of files from the loaded register in `.irbrc` (CodeMeister)
* Fix: Improves the sequence handling with better context support (CodeMeister)
* Fixes issue #1754 where `#generate` was throwing an error
* Refactors the `#increment_sequence` method to remove the URI requirement
* Fix: Cleans up ActiveSupport core extensions (Neil Carvalho)
* Fix: Addresses issue #1709 with resolution of conflict between '<attribute>' and '<attribute_id>` (CodeMeister)
* Fix: Addresses issue #1712 by ensuring callbacks only run once per instance (CodeMeister)
* Docs: Downcase of the word "constants" in `.irbrc` file (CodeMeister)
* Docs: Update docs with note clarifying when the full namespace is required in a factory (John Pitchko)
* Chore: Add new maintainers to CODEOWNERS (Ajina Slater)
## 6.5.4 (June 13, 2025)
* Fix bug where user-defined method named `definition` could not be set through `method_missing` in factories. (CodeMeister)
## 6.5.3 (June 2, 2025)
* Fix: Factory sequences without blocks (CodeMeister)
* Added: New methods for setting, generating and rewinding sequences (CodeMeister)
## 6.5.2 (May 30, 2025)
* Changed: Updated "verbose linting" test to allow for backtrace changes in Ruby 3.4 (CodeMeister)
* Fix: Set the same timestamps for `created_at` and `updated_at` on `build_stubbed` (Kim Emmanuel)
* Fix: Refactored sequences to ensure cloned traits use parent sequences. (CodeMeister)
* Docs: Fix definition_file_paths comment (Milo Winningham)
* Docs: Add ruby-lsp extensions to Useful Tools in README.md (johansenja)
* Docs: Fix docs about definition file paths (Ryo Nakamura)
* Docs: Update has_many-associations.md to mention that traits can use inline associations (Matthew Zagaja)
* Docs: Fix "Transitioning from Factory Girl" guide link (Neil Carvalho)
## 6.5.1 (January 31, 2025)
* Changed: execute linting tests within ActiveRecord transactions when available (Sean Doyle)
* Fix: Random test failure when tracking compilation time (CodeMeister)
* Fix: Bump the minimum required activesupport version to 6.1 (Earlopain)
* Internal: Update development dependencies (Neil Carvalho)
## 6.5.0 (September 6, 2024)
* fix: issue 1621 broken links in ref/factory.md by @elasticspoon in https://github.com/thoughtbot/factory_bot/pull/1623
* Add standard settings by @ydah in https://github.com/thoughtbot/factory_bot/pull/1625
* Call dynamic-readme reusable workflow by @stefannibrasil in https://github.com/thoughtbot/factory_bot/pull/1628
* Update README again by @stefannibrasil in https://github.com/thoughtbot/factory_bot/pull/1630
* Only run this workflow if the README has been updated by @stefannibrasil in https://github.com/thoughtbot/factory_bot/pull/1635
* Automatically Generated: Update Dynamic Section in README by @github-actions in https://github.com/thoughtbot/factory_bot/pull/1637
* Added a case for build_class to handle class names with underscores passed as a string by @m-gizzi in https://github.com/thoughtbot/factory_bot/pull/1642
* Add Ruby 3.3 to CI by @berkos in https://github.com/thoughtbot/factory_bot/pull/1615
* Update Dependabot configuration by @smaboshe in https://github.com/thoughtbot/factory_bot/pull/1655
* Add new maintainers to CODEOWNERS by @sarahraqueld in https://github.com/thoughtbot/factory_bot/pull/1651
* Improve docs formatting and fix filename conflicts by @sarahraqueld in https://github.com/thoughtbot/factory_bot/pull/1666
* Add a dynamic security workflow and a SECURITY.md file by @sarahraqueld in https://github.com/thoughtbot/factory_bot/pull/1677
* Automatically Generated: Update Dynamic Section in SECURITY by @github-actions in https://github.com/thoughtbot/factory_bot/pull/1678
* Ensure rails 7.2 compatibility by @Earlopain in https://github.com/thoughtbot/factory_bot/pull/1686
* Fix the factory definition in traits documentation by @ddieulivol in https://github.com/thoughtbot/factory_bot/pull/1688
## 6.4.6 (January 30, 2023)
* Fix: Bump minimum required Ruby in gemspec (Earlopain).
* Fix: Broken link in `FactoryBot.modify` docs (Matt Brictson).
* Fix: Broken link in `FactoryBot.lint` docs (Anton Dieterle).
## 6.4.5 (December 29, 2023)
* Changed: Support Ruby 3.0+, Rails 6.1+ (Mike Burns).
## 6.4.4 (December 27, 2023)
* Internal: Remove observer dependency (Earlopain).
## 6.4.3 (December 26, 2023)
* Fix: Support models without ID setters in build_stubbed (Olivier Bellone).
* Fix: Explicit observer dependency (Oleg Antonyan).
* Internal: Add Rails 7.1 to CI (Olivier Bellone).
* Internal: Bump github actions/checkout to v4 (Lorenzo Zabot)
* Internal: Stop passing disable-error_highlight in CI (Mike Burns).
* Internal: Relax the exception message check (Mike Burns).
## 6.4.2 (November 22, 2023)
* Fix: top-level traits pass their class to ActiveSupport::Notifications (makicamel).
## 6.4.1 (November 20, 2023)
* Fix: factories with traits pass their class to ActiveSupport::Notifications
(makicamel).
## 6.4.0 (November 17, 2023)
* Added: if `build_stubbed` detects a UUID primary key, generate the correct
type (Peter Boling, Alexandre Ruban).
* Docs: show examples of Ruby 3 syntactic sugars (Sean Doyle).
* Internal: resolve test warning messages (Mike Burns).
## 6.3.0 (September 1, 2023)
* Fix: link to changelog for RubyGems (Berkan Ünal).
* Fix: integrate with Ruby 3.2's `did_you_mean` library (Daniel Colson).
* Changed: explicitly define `#destroyed?` within the `Stub` strategy to return `false` to be consistent
with ActiveRecord (Benjamin Fleischer).
* Added: announce `factory_bot.compile_factory` notification (Sean Doyle).
* Docs: clarify that custom strategies need to define `#to_sym` (Edmund Korley, Jonas S).
* Docs: fix CI link in README (Mark Huk).
* Docs: fix GitHub links (Robert Fletcher).
* Docs: install this library with `bundle add` (Glauco Custódio).
* Docs: re-write into mdBook (Mike Burns, Sara Jackson, Stefanni Brasil)
* Docs: clarify that automatic trait definitions could introduce new linting errors (Lawrence Chou).
* Internal: skip TruffleRuby on Rails 5.0, 5.1, 5.2 (Andrii Konchyn).
* Internal: fix typos throughout codebase (Yudai Takada).
* Internal: run CI on `actions/checkout` v3 (Yudai Takada).
* Internal: follow standardrb code style (Yudai Takada).
* Internal: stop using Hound (Daniel Nolan).
* Internal: only run simplecov on C Ruby (Daniel Colson).
* Internal: quieter Cucumber (Daniel Colson).
* Internal: Ruby 3.2 support (Daniel Colson).
* Internal: Mike Burns is the CODEOWNER (Stefanni Brasil).
## 6.2.1 (March 8, 2022)
* Added: CI testing against truffleruby
* Changed: Documentation improvements for sequences and traits
* Fixed: ActiveSupport::Notifications reporting strategy through associations now report as symbols
* BREAKING CHANGE: Custom strategies now need to define a `to_sym` method to specify the strategy identifier
* Fixed: `add_attribute` with reserved keywords assigns values correctly
## 6.2.0 (May 7, 2021)
* Added: support for Ruby 3.0
* Changed: Include factory or trait name in error messages for missing traits. d05a9a3c
* Changed: Switched from Travis CI to GitHub Actions
* Fixed: More Ruby 2.7 kwarg deprecation warnings
## 6.1.0 (July 8, 2020)
* Added: public reader for the evaluation instance, helpful for building interrelated associations
* Changed: raise a more helpful error when passing an invalid argument to an association
* Fixed: Ruby 2.7 kwarg deprecation warnings
## 6.0.2 (June 19, 2020)
* Fixed: bug causing traits to consume more memory each time they were used
## 6.0.1 (June 19, 2020)
* Fixed: bug with constant resolution causing unexpected uninitialized constant errors
## 6.0.0 (June 18, 2020)
* Added: automatic definition of traits for Active Record enum attributes, enabled by default
(Note that this required changing where factory_bot constantizes the build
class, which may affect applications that were using abstract factories for
inheritance. See issue #1409.) (This may break `FactoryBot.lint` because
there may be previously non-existing factory+trait combinations being
defined and checked)
* Added: `traits_for_enum` method to define traits for non-Active Record enums
* Added: `build_stubbed_starting_id=` option to define the starting id for `build_stubbed`
* Removed: deprecated methods on the top-level `FactoryBot` module meant only for internal use
* Removed: support for EOL versions of Ruby (2.3, 2.4) and Rails (4.2)
* Removed: support for "abstract" factories with no associated class; use traits instead.
## 5.2.0 (April 24, 2020)
* Added: Pass index to block for `*_list` methods
* Deprecated: methods on the top-level `FactoryBot` module meant only for internal use: `callbacks`, `configuration`, `constructor`, `initialize_with`, `register_sequence`, `resent_configuration`, `skip_create`, `to_create`
## 5.1.2 (March 25, 2020)
* Fixed: Ruby 2.7 keyword deprecation warning in FactoryBot.lint
## 5.1.1 (October 2, 2019)
* Improved: performance of traits
* Fixed: registering strategies on JRuby
## 5.1.0 (September 21, 2019)
* Added: "Did you mean?" style error message to help with typos in association declarations
* Changed: `NoMethodError` for static attributes now offers a "Did you mean?" style message
* Fixed: avoid undefining inherited evaluator methods
* Fixed: avoid stubbing id for records without a primary key
* Fixed: raise a helpful error for self-referencing traits to avoid a `SystemStackError`
* Deprecated: methods on the top-level `FactoryBot` module meant only for internal use: `allow_class_lookup`, `allow_class_lookup`=, `register_trait`, `trait_by_name`, `traits`, `sequence_by_name`, `sequences`, `factory_by_name`, `register_factory`, `callback_names`, `register_callback`, `register_default_callbacks`, `register_default_strategies`, `strategies`
## 5.0.2 (February 22, 2019)
* Bugfix: raise "Trait not registered" error when passing invalid trait arguments
## 5.0.1 (February 15, 2019)
* Bugfix: Do not raise error when two sequences have the same name
in two traits that have the same name
## 5.0.0 (February 1, 2019)
* Added: Verbose option to include full backtraces in the linting output
* Changed: use_parent_strategy now defaults to true, so by default the
build strategy will build, rather than create associations
* Changed: Passing a block when defining associations now raises an error
* Bugfix: use_parent_strategy is no longer reset by FactoryBot.reload
* Bugfix: rewind_sequences will now rewind local sequences along with the global ones
* Bugfix: the build_stubbed strategy now sets timestamps without changing the
the original behavior of the timestamp methods
* Bugfix: avoid a stack error when referring to an "attributes" attribute in initialize_with
* Removed: support for EOL versions of Ruby and Rails
* Removed: static attributes (use dynamic attributes with a block instead)
* Removed: looking up factories by class
* Removed: ignore method (use transient instead)
* Removed: duplicate_attribute_assignment_from_initialize_with configuration option
* Deprecated: allow_class_lookup configuration option
## 4.11.1 (September 7, 2018)
* Documentation: Include .yardopts in the gem to fix broken RubyDoc links
## 4.11.0 (August, 15, 2018)
* Bugfix: Do not raise error for valid build_stubbed methods: decrement, increment, and toggle
* Bugfix: Do not add timestamps with build_stubbed for objects that shouldn't have timestamps
* Deprecate static attributes
## 4.10.0 (May 25, 2018)
* Allow sequences to be rewound
## 4.9.0 (skipped - FactoryGirl only release)
## 4.8.2 (October 20, 2017)
* Rename factory_girl to factory_bot
## 4.8.1 (September 28, 2017)
* Explicitly define `#destroyed?` within the `Stub` strategy to return `nil` instead of raising
* Update various dependencies
* Update internal test suite to use RSpec's mocking/stubbing instead of mocha
## 4.8.0 (December 16, 2016)
* Improve documentation
* Add `FactoryGirl.generate_list` to be consistent with `build_list`/`create_list` and friends
* Add `FactoryGirl.use_parent_strategy` configuration to allow associations to leverage parent build strategy
## 4.7.0 (April 1, 2016)
* Improve documentation
* Improve instrumentation payload to include traits, overrides, and the factory itself
* Allow linting of traits
* Deprecate factory lookup by class name in preparation for 5.0
* Improve internal performance by using flat_map instead of map and compact
* Improve handling of dirty attributes after building a stubbed object
* Reduce warnings from redefining methods
## 4.6.0 (skipped)
## 4.5.0 (October 17, 2014)
* Improve FactoryGirl.lint by including exception and message in output
* Allow selective linting
* Use more explicit #public_send when doing attribute assignment
* Improve documentation around FactoryGirl.lint and initialize_with
* Deprecate #ignore in favor of #transient
## 4.4.0 (February 10, 2014)
* Add FactoryGirl.lint
* Fix memory leak in duplicate traits
* Update documentation
## 4.3.0 (November 3, 2013)
* Start testing against Rails 4.0 and Ruby 2.0.0
* Stop testing against Rails 3.0 and Ruby 1.9.2
* Add `*_pair` methods to only build two objects
* Raise if a method is defined with a FactoryGirl block (factory or trait)
* Allow use of Symbol#to_proc in callbacks
* Add global callbacks
* Improve GETTING_STARTED and README
## 4.2.0 (January 18, 2013)
* Improve documentation
* Allow `*_list` syntax methods to accept a block
* Update gem dependencies
* Allow setting id for objects created with `build_stubbed`
* Fix Stub strategy to mimic ActiveRecord regarding `created_at`
* Evaluate sequences within the context of an Evaluator
* Fix Mocha deprecation warning
* Fix some warnings when running RUBYOPT=-w rake
* Convert test suite to RSpec's "expect" syntax
## 4.1.0 (September 11, 2012)
* Allow multiple callbacks to bind to the same block
* Fix documentation surrounding the stub strategy
## 4.0.0 (August 3, 2012)
* Remove deprecated cucumber_steps
* Remove deprecated alternate syntaxes
* Deprecate duplicate_attribute_assignment_from_initialize_with, which is now unused
as attributes assigned within initialize_with are not subsequently assigned
## 3.6.1 (August 2, 2012)
Update README to include info about running with JRuby
* Update dependencies on RSpec and tiny versions of Rails in Appraisal
* Improve flexibility of using traits with associations and add documentation
* Stub update_column to raise to mirror ActiveRecord's change from update_attribute
## 3.6.0 (July 27, 2012)
* Code/spec cleanup
* Allow factories with traits to be used in associations
* Refactor Factory to use DefinitionHierarchy to handle managing callbacks,
custom constructor, and custom to_create
* Add memoization to speed up factories providing attribute overrides
* Add initial support of JRuby when running in 1.9 mode
* Improve docs on what happens when including FactoryGirl::Syntax::Methods
## 3.5.0 (June 22, 2012)
* Allow created_at to be set when using build_stubbed
* Deprecate FactoryGirl step definitions
## 3.4.2 (June 19, 2012)
* Fix bug in traits with callbacks called implicitly in factories whose
callbacks trigger multiple times
## 3.4.1 (June 18, 2012)
* Fix traits so they can be nested and referred to from other traits
## 3.4.0 (June 11, 2012)
* Sequences support Enumerators
* Optionally disable duplicate assignment of attributes in initialize_with
* Make hash of public attributes available in initialize_with
* Support referring to a factory based on class name
## 3.3.0 (May 13, 2012)
* Allow to_create, skip_create, and initialize_with to be defined globally
* Allow to_create, skip_create, and initialize_with to be defined within traits
* Fix deprecation messages for alternate syntaxes (make, generate, etc.)
* Improve library documentation
* Deprecate after_build, after_create, before_create, after_stub in favor of new callbacks
* Introduce new callback syntax: after(:build) {}, after(:custom) {}, or callback(:different) {}
This allows for declaring any callback, usable with custom strategies
* Add attributes_for_list and build_stubbed_list with the StrategySyntaxMethodRegistrar
* Allow use of syntax methods (build, create, generate, etc) implicitly in callbacks
* Internal refactoring of a handful of components
## 3.2.0 (April 24, 2012)
* Use AS::Notifications for pub/sub to track running factories
* Call new within initialize_with implicitly on the build class
* Skip to_create with skip_create
* Allow registration of custom strategies
* Deprecate alternate syntaxes
* Implicitly call factory_bot's syntax methods from dynamic attributes
## 3.1.0 (April 6, 2012)
* Sequences support aliases, which reference the same block
* Update documentation
* Add before_create callback
* Support use of #attribute_names method to determine available attributes for steps
* Use ActiveSupport::Deprecation for all deprecations
## 3.0.0 (March 23, 2012)
* Deprecate the vintage syntax
* Remove Rails 2.x support
* Remove Ruby 1.8 support
* Remove deprecated features, including default_strategy, factory_name,
:method for defining default strategy, ignore on individual attributes, and
interacting with Factory the way you would FactoryGirl
## 2.6.4 (March 16, 2012)
* Do not ignore names of transient attributes
* Ensure attributes set on instance are calculated uniquely
## 2.6.3 (March 9, 2012)
* Fix issue with traits not being present the first time a factory is accessed
* Update available Cucumber step definitions to not require a trailing colon
when building a table of attributes to instantiate records with
## 2.6.2 (March 9, 2012)
* Allow factories to use all their ancestors' traits
* Ignore bin dir generated by bundler
* Namespace ::Factory as top-level to fix vintage syntax issue with
Ruby 1.9.2-p3p18
## 2.6.1 (March 2, 2012)
* Use FactoryGirl.reload in specs
* Clean up running named factories with a particular strategy with
FactoryGirl::FactoryRunner
## 2.6.0 (February 17, 2012)
* Improve documentation of has_many associations in the GETTING_STARTED
document
* Deprecate :method in favor of :strategy when overriding an association's
build strategy
## 2.5.2 (February 10, 2012)
* Fix step definitions to use associations defined in parent factories
* Add inline trait support to (build|create)_list
* Update ActiveSupport dependency to >= 2.3.9, which introduced
class_attribute
## 2.5.1 (February 3, 2012)
* Fix attribute evaluation when the attribute isn't defined in the factory but
is a private method on Object
* Update rubygems on Travis before running tests
* Fix spec name
* Update GETTING_STARTED with correct usage of build_stubbed
* Update README with more info on initialize_with
* Honor :parent on factory over block nesting
## 2.5.0 (January 20, 2012)
* Revert 'Deprecate build_stubbed and attributes_for'
* Implement initialize_with to allow overriding object instantiation
* Ensure FG runs against Rails 3.2.0
## 2.4.2 (January 18, 2012)
* Fix inline traits' interaction with defaults on the factory
## 2.4.1 (January 17, 2012)
* Deprecate build_stubbed and attributes_for
* Fix inline traits
## 2.4.0 (January 13, 2012)
* Refactor internals of FactoryGirl to use anonymous class on which attributes
get defined
* Explicitly require Ruby 1.8.7 or higher in gemspec
* Fix documentation
* Add Gemnasium status to documentation
* Supplying a Class to a factory that overrides to_s no longer results in
getting the wrong Class constructed
* Be more agnostic about ORMs when using columns in FactoryGirl step
definitions
* Test against Active Record 3.2.0.rc2
* Update GETTING_STARTED to use Ruby syntax highlighting
## 2.3.2 (November 26, 2011)
* Move logic of where instance.save! is set to Definition
* Fix method name from aliases_for? to alias_for?
* Refactor internal attribute handling to use an anonymous class instead of
faking Ruby's variable resolution. This allows for more sane usage of
attributes without having to manage sorting priority because attributes
can turn themselves into procs, which are used with define_method on a
class so attributes work correctly all the time.
## 2.3.1 (November 23, 2011)
* Remove internally-used associate method from all the FactoryGirl::Proxy subclasses
* Move around requiring of files
* Consolidate errors into factory_bot.rb
* Refactor AttributeList to deal with priority only when iterating over
attributes
* Refactor internals of some of the Proxy subclasses
* Ensure callbacks on traits are executed in the correct order
## 2.3.0 (November 18, 2011)
* Registries are named, resulting in better messages when factories, traits,
or sequences cannot be found
* Fix incorrect tests
* Internals refactoring introducing FactoryGirl::NullFactory,
FactoryGirl::Definition, and FactoryGirl::DeclarationList
* Use ActiveSupport for Hash#except and its delegation capabilities
* Fix usage of callbacks when added via implicit traits
* Use Bundler tasks and clean up dependencies
* Fix failing spec for big letters in factory name passed as symbol
* Add ability for traits to be added dynamically when creating an instance via
build, create, build_stubbed, or attributes_for
## 2.2.0 (October 14, 2011)
* Clean up RSpec suite to not use 'should'
* Use create_list in step definitions
* Syntax methods that deal with ORM interaction (attributes_for, build, build_stubbed,
and create) now accept a block that yields the result. This results in a
more convenient way to interact with the result than using Object.tap.
* Standardize deprecation warnings
* Update transient attribute syntax to use blocks instead of calling ignore on
each attribute declaration
* Parents can be defined after children because factories are evaluated when
they're used; this means breaking up factories across multiple files will
behave as expected
* Large internal refactoring, including changing access modifiers for a
handful of methods for a more clearly defined API
## 2.1.2 (September 23, 2011)
* Bugfix: Vintage syntax fixed after bug introduced in 2.1.1
* Introduce dependency on activesupport to remove code from Factory class
## 2.1.1 (September 23, 2011) (yanked)
* Bugfix: Parent object callbacks are run before child object callbacks
* Declarations: allow overriding/modification of individual traits in child factories
* Callbacks refactored to not be attributes
* Updating documentation for formatting and clarity (incl. new specificity for cucumber)
## 2.1.0 (September 02, 2011)
* Bugfix: created_at now defined for stubbed models
* Gemspec updated for use with Rails 3.1
* Factories can now be modified post-definition (useful for overriding defaults from gems/plugins)
* All factories can now be reloaded with Factory.reload
* Add :method => build to factory associations to prevent saving of associated objects
* Factories defined in {Rails.root}/factories are now loaded by default
* Various documentation updates
## 1.1.4 (November 28, 2008)
* Factory.build now uses Factory.create for associations of the built object
* Factory definitions are now detected in subdirectories, such as
factories/person_factory.rb (thanks to Josh Nichols)
* Factory definitions are now loaded after the environment in a Rails project
(fixes some issues with dependencies being loaded too early) (thanks to
Josh Nichols)
* Factory names ending in 's' no longer cause problems (thanks to Alex Sharp
and Josh Owens)
## 1.1.3 (September 12, 2008)
* Automatically pull in definitions from factories.rb, test/factories.rb, or
spec/factories.rb
## 1.1.2 (July 30, 2008)
* Improved error handling for invalid and undefined factories/attributes
* Improved handling of strings vs symbols vs classes
* Added a prettier syntax for handling associations
* Updated documentation and fixed compatibility with Rails 2.1
## 1.1.1 (June 23, 2008)
* The attribute "name" no longer requires using #add_attribute
## 1.1.0 (June 03, 2008)
* Added support for dependent attributes
* Fixed the attributes_for build strategy to not build associations
* Added support for sequences
## 1.0.0 (May 31, 2008)
* First version
================================================
FILE: README.md
================================================
# factory_bot
[![Build Status][ci-image]][ci] [![Gem Version][version-image]][version]
factory_bot is a fixtures replacement with a straightforward definition syntax, support for multiple build strategies (saved instances, unsaved instances, attribute hashes, and stubbed objects), and support for multiple factories for the same class (user, admin_user, and so on), including factory inheritance.
If you want to use factory_bot with Rails, see
[factory_bot_rails](https://github.com/thoughtbot/factory_bot_rails).
Interested in the history of the project name? You can find the history [here](https://github.com/thoughtbot/factory_bot/blob/main/NAME.md)
Transitioning from factory\_girl? Check out the [upgrade guide](https://github.com/thoughtbot/factory_bot/blob/v4.9.0/UPGRADE_FROM_FACTORY_GIRL.md).
## Documentation
See our extensive reference, guides, and cookbook in [the factory_bot book][].
For information on integrations with third party libraries, such as RSpec or
Rails, see [the factory_bot wiki][].
We also have [a detailed introductory video][], available for free on Upcase.
[a detailed introductory video]: https://upcase.com/videos/factory-bot?utm_source=github&utm_medium=open-source&utm_campaign=factory-girl
[the factory_bot book]: https://thoughtbot.github.io/factory_bot
[the factory_bot wiki]: https://github.com/thoughtbot/factory_bot/wiki
## Install
Run:
```ruby
bundle add factory_bot
```
To install the gem manually from your shell, run:
```shell
gem install factory_bot
```
## Supported Ruby versions
Supported Ruby versions are listed in `.github/workflows/build.yml` ([source](https://github.com/thoughtbot/factory_bot/blob/main/.github/workflows/build.yml))
## More Information
* [Rubygems](https://rubygems.org/gems/factory_bot)
* [Stack Overflow](https://stackoverflow.com/questions/tagged/factory-bot)
* [Issues](https://github.com/thoughtbot/factory_bot/issues)
* [GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS](https://robots.thoughtbot.com/)
[GETTING_STARTED]: https://github.com/thoughtbot/factory_bot/blob/main/GETTING_STARTED.md
## Useful Tools
* [FactoryTrace](https://github.com/djezzzl/factory_trace) - helps to find unused factories and traits.
* [ruby-lsp-factory_bot](https://github.com/donny741/ruby-lsp-factory_bot) / [ruby-lsp-rails-factory-bot](https://github.com/johansenja/ruby-lsp-rails-factory-bot) - integration with [ruby-lsp](https://github.com/Shopify/ruby-lsp) to provide intellisense
Contributing
------------
Please see [CONTRIBUTING.md](https://github.com/thoughtbot/factory_bot/blob/main/CONTRIBUTING.md).
factory_bot was originally written by Joe Ferris and is maintained by thoughtbot.
Many improvements and bugfixes were contributed by the [open source
community](https://github.com/thoughtbot/factory_bot/graphs/contributors).
License
-------
factory_bot is Copyright © 2008 Joe Ferris and thoughtbot. It is free
software, and may be redistributed under the terms specified in the
[LICENSE] file.
[LICENSE]: https://github.com/thoughtbot/factory_bot/blob/main/LICENSE
<!-- START /templates/footer.md -->
## About thoughtbot

This repo is maintained and funded by thoughtbot, inc.
The names and logos for thoughtbot are trademarks of thoughtbot, inc.
We love open source software!
See [our other projects][community].
We are [available for hire][hire].
[community]: https://thoughtbot.com/community?utm_source=github
[hire]: https://thoughtbot.com/hire-us?utm_source=github
<!-- END /templates/footer.md -->
[ci-image]: https://github.com/thoughtbot/factory_bot/actions/workflows/build.yml/badge.svg?branch=main
[ci]: https://github.com/thoughtbot/factory_bot/actions?query=workflow%3ABuild+branch%3Amain
[version-image]: https://badge.fury.io/rb/factory_bot.svg
[version]: https://badge.fury.io/rb/factory_bot
[hound-badge-image]: https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg
[hound]: https://houndci.com
================================================
FILE: RELEASING.md
================================================
# Releasing
1. Create a release branch using the naming scheme `release-x.x.x`
```shell
git checkout main
git pull
git checkout -b release-x.x.x
```
2. Bump the `VERSION` inside `lib/factory_bot/version.rb`
3. Run `bundle install` to ensure the `Gemfile.lock` file is up to date.
4. Generate release notes using [GitHub's New Release](https://github.com/thoughtbot/factory_bot/releases/new) feature.
1. Click the tags drop down and select "Create new tag"
2. Fill in the create new tag modal and select "Create"
Note: This is a safe step as the tag will not be created unless the release is published
3. Click the "Generate release notes" button
4. Copy the generated text from the "What's Changed" section, for use when updating `NEWS.md` in the next step.
5. Update `NEWS.md` to reflect the changes since last release.
1. Add a heading with the version number and date
2. Paste the release notes you copied from the previous step
Note: A useful GitHub URL to compare the changes is:
`https://github.com/thoughtbot/factory_bot/compare/vLAST_VERSION...main`
6. Commit the changes.
Note: As there shouldn't be code changes, CI doesn't need to run.
You can add `[ci skip]` to the commit message to skip it.
7. Create a Pull Request, get it reviewed, and merge it to the `main` branch once approved.
8. Back on your machine, switch to the `main` branch and tag the latest commit with the release version: `git tag -s vVERSION`
- We recommend the [_quick guide on how to sign a release_] from git ready.
9. Push your changes: `git push && git push --tags`
10. If you haven't already, add yourself as an owner of the `factory_bot` gem on [rubygems.org](https://rubygems.org/) using [the guide in the thoughtbot handbook](https://github.com/thoughtbot/handbook/blob/main/operations/services/rubygems.md#managing-rubygems)
11. Build and publish the gem:
```bash
gem build factory_bot.gemspec
gem push factory_bot-VERSION.gem
```
12. On GitHub, add a new release using the recent `NEWS.md` as the content. Sample
URL: `https://github.com/thoughtbot/factory_bot/releases/new?tag=vVERSION`
13. Announce the new release, making sure to say "thank you" to the contributors who helped shape this version!
thoughtbotters can refer to the handbook for announcements guidelines.
[_quick guide on how to sign a release_]: http://gitready.com/advanced/2014/11/02/gpg-sign-releases.html
================================================
FILE: Rakefile
================================================
require "rubygems"
require "bundler"
require "rake"
require "yard"
require "rspec/core/rake_task"
require "cucumber/rake/task"
require "standard/rake"
Bundler::GemHelper.install_tasks(name: "factory_bot")
desc "Default: run all specs and standard"
task default: %w[all_specs standard]
desc "Run all specs and features"
task all_specs: %w[spec:unit spec:acceptance features]
namespace :spec do
desc "Run unit specs"
RSpec::Core::RakeTask.new("unit") do |t|
t.pattern = "spec/{*_spec.rb,factory_bot/**/*_spec.rb}"
end
desc "Run acceptance specs"
RSpec::Core::RakeTask.new("acceptance") do |t|
t.pattern = "spec/acceptance/**/*_spec.rb"
end
end
desc "Run the unit and acceptance specs"
task spec: ["spec:unit", "spec:acceptance"]
Cucumber::Rake::Task.new(:features) do |t|
t.fork = true
t.cucumber_opts = ["--format", ENV["CUCUMBER_FORMAT"] || "progress"]
end
YARD::Rake::YardocTask.new do |t|
end
================================================
FILE: SECURITY.md
================================================
<!-- START /templates/security.md -->
# Security Policy
## Supported Versions
Only the the latest version of this project is supported at a given time. If
you find a security issue with an older version, please try updating to the
latest version first.
If for some reason you can't update to the latest version, please let us know
your reasons so that we can have a better understanding of your situation.
## Reporting a Vulnerability
For security inquiries or vulnerability reports, visit
<https://thoughtbot.com/security>.
If you have any suggestions to improve this policy, visit <https://thoughtbot.com/security>.
<!-- END /templates/security.md -->
================================================
FILE: cucumber.yml
================================================
default: --publish-quiet -r features features
================================================
FILE: docs/book.toml
================================================
[book]
authors = ["Mike Burns"]
language = "en"
multilingual = false
src = "src"
title = "factory_bot"
[output.html.redirect]
"/setup/rspec.html" = "https://github.com/thoughtbot/factory_bot/wiki/Integration:-RSpec"
"/setup/cucumber.html" = "https://github.com/thoughtbot/factory_bot/wiki/Integration:-Cucumber"
"/setup/minitest-rails.html" = "https://github.com/thoughtbot/factory_bot/wiki/Integration:-minitest-rails"
"/setup/minitest-spec.html" = "https://github.com/thoughtbot/factory_bot/wiki/Integration:-Minitest::Spec"
"/setup/minitest.html" = "https://github.com/thoughtbot/factory_bot/wiki/Integration:-Minitest"
"/setup/spinach.html" = "https://github.com/thoughtbot/factory_bot/wiki/Integration:-Spinach"
"/setup/test-unit.html" = "https://github.com/thoughtbot/factory_bot/wiki/Integration:-Test::Unit"
"/setup/update-gemfile.html" = "summary.html"
"/setup/configure-test-suite.html" = "summary.html"
"/using-factories/build_stubbed-and-marshaldump.html" = "build-strategies.html"
"/associations/has_many-associations.html" = "../cookbook/has_many-associations.html"
"/associations/has_and_belongs_to_many-associations.html" = "../cookbook/has_and_belongs_to_many-associations.html"
"/associations/polymorphic-associations.html" = "../cookbook/polymorphic-associations.html"
"/associations/interconnected-associations.html" = "../cookbook/interconnected-associations.html"
"/traits/defining-traits.html" = "summary.html"
"/callbacks/default-callbacks.html" = "summary.html"
================================================
FILE: docs/src/SUMMARY.md
================================================
# Summary
[Intro](intro.md)
## Reference
- [Build strategies](ref/build-strategies.md)
- [FactoryBot.find_definitions](ref/find_definitions.md)
- [FactoryBot.define](ref/define.md)
- [factory](ref/factory.md)
- [add_attribute](ref/add_attribute.md)
- [association](ref/association.md)
- [sequence](ref/sequence.md)
- [trait](ref/trait.md)
- [method_missing](ref/method_missing.md)
- [traits_for_enum](ref/traits_for_enum.md)
- [skip_create, to_create, and initialize_with](ref/build-and-create.md)
- [transient](ref/transient.md)
- [Hooks](ref/hooks.md)
- [FactoryBot.modify](ref/modify.md)
- [FactoryBot.lint](ref/lint.md)
- [FactoryBot.register_strategy](ref/register_strategy.md)
## Guide
- [Setup](setup/summary.md)
- [Using Without Bundler](using-without-bundler/summary.md)
- [Rails Preloaders and RSpec](rails-preloaders-and-rspec/summary.md)
- [Defining factories](defining/summary.md)
- [Factory name and attributes](defining/name-attributes.md)
- [Specifying the class explicitly](defining/explicit-class.md)
- [Definition file paths](defining/file-paths.md)
- [Hash attributes](defining/hash-attributes.md)
- [Best practices](defining/best-practices.md)
- [Static Attributes (deprecated)](defining/static-attributes.md)
- [Using factories](using-factories/summary.md)
- [Build strategies](using-factories/build-strategies.md)
- [Building or Creating Multiple Records](building-or-creating-multiple-records/summary.md)
- [Attribute overrides](using-factories/attribute-overrides.md)
- [Aliases](aliases/summary.md)
- [Dependent Attributes](dependent-attributes/summary.md)
- [Transient Attributes](transient-attributes/summary.md)
- [With other attributes](transient-attributes/with-other-attributes.md)
- [With `attributes_for`](transient-attributes/with-attributes_for.md)
- [With callbacks](transient-attributes/with-callbacks.md)
- [With associations](transient-attributes/with-associations.md)
- [Method Name / Reserved Word Attributes](method-name-reserved-word-attributes/summary.md)
- [Inheritance](inheritance/summary.md)
- [Nested factories](inheritance/nested-factories.md)
- [Assigning parent explicitly](inheritance/assigning-parent-explicitly.md)
- [Best practices](inheritance/best-practices.md)
- [Associations](associations/summary.md)
- [Implicit definition](associations/implicit-definition.md)
- [Explicit definition](associations/explicit-definition.md)
- [Inline definition](associations/inline-definition.md)
- [Specifying the factory](associations/specifying-the-factory.md)
- [Overriding attributes](associations/overriding-attributes.md)
- [Association overrides](associations/association-overrides.md)
- [Build strategies](associations/build-strategies.md)
- [Sequences](sequences/summary.md)
- [Global sequences](sequences/global-sequences.md)
- [With dynamic attributes](sequences/with-dynamic-attributes.md)
- [As implicit attributes](sequences/as-implicit-attributes.md)
- [Factory sequences](sequences/factory-sequences.md)
- [Initial value](sequences/initial-value.md)
- [Without a block](sequences/without-a-block.md)
- [Aliases](sequences/aliases.md)
- [Sequence URIs](sequences/sequence-uris.md)
- [Rewinding](sequences/rewinding.md)
- [Setting the value](sequences/setting-the-value.md)
- [Generating a sequence](sequences/generating.md)
- [Uniqueness](sequences/uniqueness.md)
- [Traits](traits/summary.md)
- [As implicit attributes](traits/as-implicit-attributes.md)
- [Using traits](traits/using.md)
- [Enum traits](traits/enum.md)
- [Attribute precedence](traits/attribute-precedence.md)
- [In child factories](traits/in-child-factories.md)
- [As mixins](traits/mixins.md)
- [With associations](traits/with-associations.md)
- [Traits within traits](traits/traits-within-traits.md)
- [With transient attributes](traits/with-transient-attributes.md)
- [Callbacks](callbacks/summary.md)
- [Multiple callbacks](callbacks/multiple-callbacks.md)
- [Global callbacks](callbacks/global-callbacks.md)
- [Symbol#to_proc](callbacks/symbol-to_proc.md)
- [Callback order](callbacks/callback_order.md)
- [Modifying factories](modifying-factories/summary.md)
- [Linting Factories](linting-factories/summary.md)
- [Custom Construction](custom-construction/summary.md)
- [Custom Strategies](custom-strategies/summary.md)
- [Custom Callbacks](custom-callbacks/summary.md)
- [Custom Methods to Persist Objects](custom-methods-to-persist-objects/summary.md)
- [ActiveSupport Instrumentation](activesupport-instrumentation/summary.md)
## Cookbook
- [`has_many` associations](cookbook/has_many-associations.md)
- [`has_and_belongs_to_many` associations](cookbook/has_and_belongs_to_many-associations.md)
- [Polymorphic associations](cookbook/polymorphic-associations.md)
- [Interconnected associations](cookbook/interconnected-associations.md)
================================================
FILE: docs/src/activesupport-instrumentation/summary.md
================================================
# ActiveSupport Instrumentation
In order to track what factories are created (and with what build strategy),
`ActiveSupport::Notifications` are included to provide a way to subscribe to
factories being compiled and run. One example would be to track factories based on a
threshold of execution time.
```ruby
ActiveSupport::Notifications.subscribe("factory_bot.run_factory") do |name, start, finish, id, payload|
execution_time_in_seconds = finish - start
if execution_time_in_seconds >= 0.5
$stderr.puts "Slow factory: #{payload[:name]} using strategy #{payload[:strategy]}"
end
end
```
Another example would be tracking all factories and how they're used throughout
your test suite. If you're using RSpec, it's as simple as adding a
`before(:suite)` and `after(:suite)`:
```ruby
factory_bot_results = {}
config.before(:suite) do
ActiveSupport::Notifications.subscribe("factory_bot.run_factory") do |name, start, finish, id, payload|
factory_name = payload[:name]
strategy_name = payload[:strategy]
factory_bot_results[factory_name] ||= {}
factory_bot_results[factory_name][strategy_name] ||= 0
factory_bot_results[factory_name][strategy_name] += 1
end
end
config.after(:suite) do
puts factory_bot_results
end
```
Another example could involve tracking the attributes and traits that factories are compiled with. If you're using RSpec, you could add `before(:suite)` and `after(:suite)` blocks that subscribe to `factory_bot.compile_factory` notifications:
```ruby
factory_bot_results = {}
config.before(:suite) do
ActiveSupport::Notifications.subscribe("factory_bot.compile_factory") do |name, start, finish, id, payload|
factory_name = payload[:name]
factory_class = payload[:class]
attributes = payload[:attributes]
traits = payload[:traits]
factory_bot_results[factory_class] ||= {}
factory_bot_results[factory_class][factory_name] = {
attributes: attributes.map(&:name)
traits: traits.map(&:name)
}
end
end
config.after(:suite) do
puts factory_bot_results
end
```
================================================
FILE: docs/src/aliases/summary.md
================================================
# Aliases
factory\_bot allows you to define aliases to existing factories to make them
easier to re-use. This could come in handy when, for example, your Post object
has an author attribute that actually refers to an instance of a User class.
While normally factory\_bot can infer the factory name from the association name,
in this case it will look for an author factory in vain. So, alias your user
factory so it can be used under alias names.
```ruby
factory :user, aliases: [:author, :commenter] do
first_name { "John" }
last_name { "Doe" }
date_of_birth { 18.years.ago }
end
factory :post do
# The alias allows us to write author instead of
# association :author, factory: :user
author
title { "How to read a book effectively" }
body { "There are five steps involved." }
end
factory :comment do
# The alias allows us to write commenter instead of
# association :commenter, factory: :user
commenter
body { "Great article!" }
end
```
================================================
FILE: docs/src/associations/association-overrides.md
================================================
# Association overrides
Attribute overrides can be used to link associated objects:
```ruby
FactoryBot.define do
factory :author do
name { 'Taylor' }
end
factory :post do
author
end
end
eunji = build(:author, name: 'Eunji')
post = build(:post, author: eunji)
```
Ruby 3.1's support for [omitting values][] from `Hash` literals dovetails with
attribute overrides, and provides an opportunity to limit the repetition of
variable names:
```ruby
author = build(:author, name: 'Eunji')
post = build(:post, author:)
```
[omitting values]: https://docs.ruby-lang.org/en/3.1/syntax/literals_rdoc.html#label-Hash+Literals
================================================
FILE: docs/src/associations/build-strategies.md
================================================
# Build strategies
Associations default to using the same build strategy as their parent object:
```ruby
FactoryBot.define do
factory :author
factory :post do
author
end
end
post = build(:post)
post.new_record? # => true
post.author.new_record? # => true
post = create(:post)
post.new_record? # => false
post.author.new_record? # => false
```
This is different than the default behavior for previous versions of
factory\_bot, where the association strategy would not always match the strategy
of the parent object. If you want to continue using the old behavior, you can
set the `use_parent_strategy` configuration option to `false`.
```ruby
FactoryBot.use_parent_strategy = false
# Builds and saves a User and a Post
post = create(:post)
post.new_record? # => false
post.author.new_record? # => false
# Builds and saves a User, and then builds but does not save a Post
post = build(:post)
post.new_record? # => true
post.author.new_record? # => false
```
To not save the associated object, specify `strategy: :build` in the factory:
```ruby
FactoryBot.use_parent_strategy = false
factory :post do
# ...
association :author, factory: :user, strategy: :build
end
# Builds a User, and then builds a Post, but does not save either
post = build(:post)
post.new_record? # => true
post.author.new_record? # => true
```
Note that the `strategy: :build` option must be passed to an explicit call to
`association`, and cannot be used with implicit associations:
```ruby
factory :post do
# ...
author strategy: :build # <<< this does *not* work; causes author_id to be nil
```
================================================
FILE: docs/src/associations/explicit-definition.md
================================================
# Explicit definition
You can define associations explicitly. This can be handy especially when
[Overriding attributes](overriding-attributes.md)
```ruby
factory :post do
# ...
association :author
end
```
================================================
FILE: docs/src/associations/implicit-definition.md
================================================
# Implicit definition
It's possible to set up associations within factories. If the factory name is
the same as the association name, the factory name can be left out.
```ruby
factory :post do
# ...
author
end
```
================================================
FILE: docs/src/associations/inline-definition.md
================================================
# Inline definition
You can also define associations inline within regular attributes, but note
that the value will be `nil` when using the `attributes_for` strategy.
```ruby
factory :post do
# ...
author { association :author }
end
```
================================================
FILE: docs/src/associations/overriding-attributes.md
================================================
# Overriding attributes
You can also override attributes on associations.
Implicitly:
```ruby
factory :post do
# ...
author factory: :author, last_name: "Writely"
end
```
Explicitly:
```ruby
factory :post do
# ...
association :author, last_name: "Writely"
end
```
Or inline using attributes from the factory:
```rb
factory :post do
# ...
author_last_name { "Writely" }
author { association :author, last_name: author_last_name }
end
```
================================================
FILE: docs/src/associations/specifying-the-factory.md
================================================
# Specifying the factory
You can specify a different factory (although [Aliases](../aliases/summary.md)
might also help you out here).
Implicitly:
```ruby
factory :post do
# ...
author factory: :user
end
```
Explicitly:
```ruby
factory :post do
# ...
association :author, factory: :user
end
```
Inline:
```ruby
factory :post do
# ...
author { association :user }
end
```
================================================
FILE: docs/src/associations/summary.md
================================================
# Associations
================================================
FILE: docs/src/building-or-creating-multiple-records/summary.md
================================================
# Building or Creating Multiple Records
Sometimes, you'll want to create or build multiple instances of a factory at
once.
```ruby
built_users = build_list(:user, 25)
created_users = create_list(:user, 25)
```
These methods will build or create a specific amount of factories and return
them as an array. To set the attributes for each of the factories, you can pass
in a hash as you normally would.
```ruby
twenty_year_olds = build_list(:user, 25, date_of_birth: 20.years.ago)
```
In order to set different attributes for each factory, these methods may be
passed a block, with the factory and the index as parameters:
```ruby
twenty_somethings = build_list(:user, 10) do |user, i|
user.date_of_birth = (20 + i).years.ago
end
```
`create_list` passes saved instances into the block. If you modify the
instance, you must save it again:
```ruby
twenty_somethings = create_list(:user, 10) do |user, i|
user.date_of_birth = (20 + i).years.ago
user.save!
end
```
`build_stubbed_list` will give you fully stubbed out instances:
```ruby
stubbed_users = build_stubbed_list(:user, 25) # array of stubbed users
```
There's also a set of `*_pair` methods for creating two records at a time:
```ruby
built_users = build_pair(:user) # array of two built users
created_users = create_pair(:user) # array of two created users
```
If you need multiple attribute hashes, `attributes_for_list` will generate
them:
```ruby
users_attrs = attributes_for_list(:user, 25) # array of attribute hashes
```
================================================
FILE: docs/src/callbacks/callback_order.md
================================================
# Callback Order
When a callback event like `after_build` or `before_all` is triggered, all callbacks for that event are executed in the following order:
1. Global callbacks.
2. Inherited callbacks.
3. Factory callbacks.
4. Trait callbacks (in the order requested).
## A simple factory example:
```ruby
FactoryBot.define do
before(:all) { puts "Global before(:all)" }
after(:all) { puts "Global after(:all)" }
factory :user do
before(:all) { puts "User before(:all)" }
after(:all) { puts "User after(:all)" }
before(:build) { puts "User before(:build)" }
after(:build) { puts "User after(:build)" }
trait :trait_a do
before(:build) { puts "Trait-A before(:build)" }
after(:build) { puts "Trait-A after(:build)" }
end
trait :trait_b do
before(:build) { puts "Trait-B before(:build)" }
after(:build) { puts "Trait-B after(:build)" }
end
end
end
build(:user, :trait_b, :trait_a)
# Result:
#
# 1. "Global before(:all)"
# 2. "User before(:all)"
# 3. "User before(:build)
# 4. "Trait-B before(:build)"
# 5. "Trait-A before(:build)"
# 6. "User after(:build)"
# 7. "Trait-B after(:build)"
# 8. "Trait-A after(:build)"
# 9. "Global after(:all)"
# 10. "User after(:all)"
```
## An inherited factory example:
```ruby
FactoryBot.define do
before(:all) { puts "Global before(:all)" }
before(:build) { puts "Global before(:build)" }
after(:build) { puts "Global after(:build)" }
after(:all) { puts "Global after(:all)" }
factory :parent do
before(:all) { puts "Parent before(:all)" }
before(:build) { puts "Parent before(:build)" }
after(:all) { puts "Parent after(:all)" }
after(:build) { puts "Parent after(:build)" }
trait :trait_a do
before(:build) { puts "Trait-A before(:build)" }
after(:build) { puts "Trait-A after(:build)" }
end
factory :child do
before(:all) { puts "Child before(:all)" }
before(:build) { puts "Child before(:build)" }
after(:build) { puts "Child after(:build)" }
after(:all) { puts "Child after(:all)" }
trait :trait_b do
before(:build) { puts "Trait-B before(:build)" }
after(:build) { puts "Trait-B after(:build)" }
after(:all) { puts "Trait-B after(:all)" }
end
trait :trait_c do
before(:build) { puts "Trait-C before(:build)" }
after(:build) { puts "Trait-C after(:build)" }
before(:all) { puts "Trait-C before(:all)" }
end
end
end
end
build(:child, :trait_c, :trait_a, :trait_b)
# Result:
#
# 1. "Global before(:all)"
# 2. "Parent before(:all)"
# 3. "Child before(:all)"
# 4. "Trait-C before(:all)"
# 5. "Global before(:build)"
# 6. "Parent before(:build)"
# 7. "Child before(:build)"
# 8. "Trait-C before(:build)"
# 9. "Trait-A before(:build)"
# 10. "Trait-B before(:build)"
# 11. "Global after(:build)"
# 12. "Parent after(:build)"
# 13. "Child after(:build)"
# 14. "Trait-C after(:build)"
# 15. "Trait-A after(:build)"
# 16. "Trait-B after(:build)"
# 17. "Global after(:all)"
# 18. "Parent after(:all)"
# 19. "Child after(:all)"
# 20. "Trait-B after(:all)"
```
================================================
FILE: docs/src/callbacks/default-callbacks.md
================================================
# Default callbacks
factory\_bot makes available four callbacks for injecting some code:
* before(:all) - called before any strategy is used (e.g., `FactoryBot.build`, `FactoryBot.create`, `FactoryBot.build_stubbed`)
* before(:build) - called before a factory is built (via `FactoryBot.build`, `FactoryBot.create`)
* after(:build) - called after a factory is built (via `FactoryBot.build`, `FactoryBot.create`)
* before(:create) - called before a factory is saved (via `FactoryBot.create`)
* after(:create) - called after a factory is saved (via `FactoryBot.create`)
* after(:stub) - called after a factory is stubbed (via `FactoryBot.build_stubbed`)
* after(:all) - called after any strategy is used (e.g., `FactoryBot.build`, `FactoryBot.create`, `FactoryBot.build_stubbed`)
Examples:
```ruby
# Define a factory that calls the generate_hashed_password method after it is built
factory :user do
after(:build) { |user| generate_hashed_password(user) }
end
```
Note that you'll have an instance of the object in the block. This can be useful.
================================================
FILE: docs/src/callbacks/global-callbacks.md
================================================
# Global callbacks
To override callbacks for all factories, define them within the
`FactoryBot.define` block:
```ruby
FactoryBot.define do
after(:build) { |object| puts "Built #{object}" }
after(:create) { |object| AuditLog.create(attrs: object.attributes) }
factory :user do
name { "John Doe" }
end
end
```
================================================
FILE: docs/src/callbacks/multiple-callbacks.md
================================================
# Multiple callbacks
You can also define multiple types of callbacks on the same factory:
```ruby
factory :user do
after(:build) { |user| do_something_to(user) }
after(:create) { |user| do_something_else_to(user) }
end
```
Factories can also define any number of the same kind of callback. These
callbacks will be executed in the order they are specified:
```ruby
factory :user do
after(:create) { this_runs_first }
after(:create) { then_this }
end
```
Calling `create` will invoke both `after_build` and `after_create` callbacks.
Also, like standard attributes, child factories will inherit (and can also
define) callbacks from their parent factory.
Multiple callbacks can be assigned to run a block; this is useful when building
various strategies that run the same code (since there are no callbacks that are
shared across all strategies).
```ruby
factory :user do
callback(:after_stub, :before_create) { do_something }
after(:stub, :create) { do_something_else }
before(:create, :custom) { do_a_third_thing }
end
```
================================================
FILE: docs/src/callbacks/summary.md
================================================
# Callbacks
factory\_bot makes six callbacks available:
| Callback | Timing |
| --------------- | ------------------------------------------------------------------------------------------------------------------------- |
| before(:all) | called before any strategy is used to construct an object, including custom strategies |
| before(:build) | called before a factory builds an object (via `FactoryBot.build` or `FactoryBot.create`) |
| after(:build) | called after a factory builds an object (via `FactoryBot.build` or `FactoryBot.create`) |
| before(:create) | called before a factory saves an object (via `FactoryBot.create`) |
| after(:create) | called after a factory saves an object (via `FactoryBot.create`) |
| after(:stub) | called after a factory stubs an object (via `FactoryBot.build_stubbed`) |
| after(:all) | called after any strategy has completed, including custom strategies |
## Examples
### Calling an object's own method after building
```ruby
##
# Define a factory that calls the generate_hashed_password method
# after the user factory is built.
#
# Note that you'll have an instance of the object in the block
#
factory :user do
after(:build) { |user, context| generate_hashed_password(user) }
end
```
### Skipping an object's own :after_create callback
```ruby
##
# Disable a model's own :after_create callback that sends an email
# on creation, then re-enable it afterwards
#
factory :user do
before(:all){ User.skip_callback(:create, :after, :send_welcome_email) }
after(:all){ User.set_callback(:create, :after, :send_welcome_email) }
end
```
================================================
FILE: docs/src/callbacks/symbol-to_proc.md
================================================
# Symbol#to_proc
You can call callbacks that rely on `Symbol#to_proc`:
```ruby
# app/models/user.rb
class User < ActiveRecord::Base
def confirm!
# confirm the user account
end
end
# spec/factories.rb
FactoryBot.define do
factory :user do
after :create, &:confirm!
end
end
create(:user) # creates the user and confirms it
```
================================================
FILE: docs/src/cookbook/has_and_belongs_to_many-associations.md
================================================
# has_and_belongs_to_many associations
Generating data for a `has_and_belongs_to_many` relationship is very similar
to the above `has_many` relationship, with a small change: you need to pass an
array of objects to the model's pluralized attribute name rather than a single
object to the singular version of the attribute name.
```ruby
def profile_with_languages(languages_count: 2)
FactoryBot.create(:profile) do |profile|
FactoryBot.create_list(:language, languages_count, profiles: [profile])
end
end
```
Or with the callback approach:
```ruby
factory :profile_with_languages do
transient do
languages_count { 2 }
end
after(:create) do |profile, context|
create_list(:language, context.languages_count, profiles: [profile])
profile.reload
end
end
```
Or the inline association approach (note the use of the `instance` method here
to refer to the profile being built):
```ruby
factory :profile_with_languages do
transient do
languages_count { 2 }
end
languages do
Array.new(languages_count) do
association(:language, profiles: [instance])
end
end
end
```
================================================
FILE: docs/src/cookbook/has_many-associations.md
================================================
# has_many associations
There are a few ways to generate data for a `has_many` relationship. The
simplest approach is to write a helper method in plain Ruby to tie together the
different records:
```ruby
FactoryBot.define do
factory :post do
title { "Through the Looking Glass" }
user
end
factory :user do
name { "Rachel Sanchez" }
end
end
def user_with_posts(posts_count: 5)
FactoryBot.create(:user) do |user|
FactoryBot.create_list(:post, posts_count, user: user)
end
end
create(:user).posts.length # 0
user_with_posts.posts.length # 5
user_with_posts(posts_count: 15).posts.length # 15
```
If you prefer to keep the object creation fully within factory\_bot, you can
build the posts in an `after(:create)` callback.
```ruby
FactoryBot.define do
factory :post do
title { "Through the Looking Glass" }
user
end
factory :user do
name { "John Doe" }
# user_with_posts will create post data after the user has been created
factory :user_with_posts do
# posts_count is declared as a transient attribute available in the
# callback via the context
transient do
posts_count { 5 }
end
# the after(:create) yields two values; the user instance itself and the
# context, which stores all values from the factory, including transient
# attributes; `create_list`'s second argument is the number of records
# to create and we make sure the user is associated properly to the post
after(:create) do |user, context|
create_list(:post, context.posts_count, user: user)
# You may need to reload the record here, depending on your application
user.reload
end
end
end
end
create(:user).posts.length # 0
create(:user_with_posts).posts.length # 5
create(:user_with_posts, posts_count: 15).posts.length # 15
```
The following is a simple example that works without having to save to the
database. It works with `build`, `build_stubbed`, and `create` (although it
doesn't work well with `attributes_for`), you can use inline associations:
```ruby
FactoryBot.define do
factory :post do
title { "Through the Looking Glass" }
user
end
factory :user do
name { "Taylor Kim" }
factory :user_with_posts do
posts { [association(:post)] }
end
# or
trait :with_posts do
posts { [association(:post)] }
end
end
end
create(:user).posts.length # 0
create(:user_with_posts).posts.length # 1
build(:user_with_posts).posts.length # 1
build_stubbed(:user_with_posts).posts.length # 1
```
For more flexibility you can combine this with the `posts_count` transient
attribute from the callback example:
```ruby
FactoryBot.define do
factory :post do
title { "Through the Looking Glass" }
user
end
factory :user do
name { "Adiza Kumato" }
factory :user_with_posts do
transient do
posts_count { 5 }
end
posts do
Array.new(posts_count) { association(:post) }
end
end
end
end
create(:user_with_posts).posts.length # 5
create(:user_with_posts, posts_count: 15).posts.length # 15
build(:user_with_posts, posts_count: 15).posts.length # 15
build_stubbed(:user_with_posts, posts_count: 15).posts.length # 15
```
================================================
FILE: docs/src/cookbook/interconnected-associations.md
================================================
# Interconnected associations
There are limitless ways objects might be interconnected, and
factory\_bot may not always be suited to handle those relationships. In some
cases it makes sense to use factory\_bot to build each individual object, and
then to write helper methods in plain Ruby to tie those objects together.
That said, some more complex, interconnected relationships can be built in factory\_bot
using inline associations with reference to the `instance` being built.
Let's say your models look like this, where an associated `Student` and
`Profile` should both belong to the same `School`:
```ruby
class Student < ApplicationRecord
belongs_to :school
has_one :profile
end
class Profile < ApplicationRecord
belongs_to :school
belongs_to :student
end
class School < ApplicationRecord
has_many :students
has_many :profiles
end
```
We can ensure the student and profile are connected to each other and to the
same school with a factory like this:
```ruby
FactoryBot.define do
factory :student do
school
profile { association :profile, student: instance, school: school }
end
factory :profile do
school
student { association :student, profile: instance, school: school }
end
factory :school
end
```
Note that this approach works with `build`, `build_stubbed`, and `create`, but
the associations will return `nil` when using `attributes_for`.
Also, note that if you assign any attributes inside a custom `initialize_with`
(e.g. `initialize_with { new(**attributes) }`), those attributes should not refer to `instance`,
since it will be `nil`.
================================================
FILE: docs/src/cookbook/polymorphic-associations.md
================================================
# Polymorphic associations
Polymorphic associations can be handled with traits:
```ruby
FactoryBot.define do
factory :video
factory :photo
factory :comment do
for_photo # default to the :for_photo trait if none is specified
trait :for_video do
association :commentable, factory: :video
end
trait :for_photo do
association :commentable, factory: :photo
end
end
end
```
This allows us to do:
```ruby
create(:comment)
create(:comment, :for_video)
create(:comment, :for_photo)
```
================================================
FILE: docs/src/custom-callbacks/summary.md
================================================
# Custom Callbacks
Custom callbacks can be defined if you're using custom strategies:
```ruby
class JsonStrategy
def initialize
@strategy = FactoryBot.strategy_by_name(:create).new
end
delegate :association, to: :@strategy
def result(evaluation)
result = @strategy.result(evaluation)
evaluation.notify(:before_json, result)
result.to_json.tap do |json|
evaluation.notify(:after_json, json)
evaluation.notify(:make_json_awesome, json)
end
end
def to_sym
:json
end
end
FactoryBot.register_strategy(:json, JsonStrategy)
FactoryBot.define do
factory :user do
before(:json) { |user| do_something_to(user) }
after(:json) { |user_json| do_something_to(user_json) }
callback(:make_json_awesome) { |user_json| do_something_to(user_json) }
end
end
```
================================================
FILE: docs/src/custom-construction/summary.md
================================================
# Custom Construction
If you want to use factory\_bot to construct an object where some attributes
are passed to `initialize` or if you want to do something other than simply
calling `new` on your build class, you can override the default behavior by
defining `initialize_with` on your factory. Example:
```ruby
# user.rb
class User
attr_accessor :name, :email
def initialize(name)
@name = name
end
end
# factories.rb
sequence(:email) { |n| "person#{n}@example.com" }
factory :user do
name { "Jane Doe" }
email
initialize_with { new(name) }
end
build(:user).name # Jane Doe
```
Although factory\_bot is written to work with ActiveRecord out of the box, it
can also work with any Ruby class. For maximum compatibility with ActiveRecord,
the default initializer builds all instances by calling `new` on your build
class without any arguments. It then calls attribute writer methods to assign
all the attribute values. While that works fine for ActiveRecord, it actually
doesn't work for almost any other Ruby class.
You can override the initializer in order to:
* Build non-ActiveRecord objects that require arguments to `initialize`
* Use a method other than `new` to instantiate the instance
* Do wild things like decorate the instance after it's built
When using `initialize_with`, you don't have to declare the class itself when
calling `new`; however, any other class methods you want to call will have to
be called on the class explicitly.
For example:
```ruby
factory :user do
name { "John Doe" }
initialize_with { User.build_with_name(name) }
end
```
You can also access all public attributes within the `initialize_with` block
by calling `attributes`:
```ruby
factory :user do
transient do
comments_count { 5 }
end
name "John Doe"
initialize_with { new(**attributes) }
end
```
This will build a hash of all attributes to be passed to `new`. It won't
include transient attributes, but everything else defined in the factory will
be passed (associations, evaluated sequences, etc.)
You can define `initialize_with` for all factories by including it in the
`FactoryBot.define` block:
```ruby
FactoryBot.define do
initialize_with { new("Awesome first argument") }
end
```
When using `initialize_with`, attributes accessed from within the
`initialize_with` block are assigned *only* in the constructor; this equates to
roughly the following code:
```ruby
FactoryBot.define do
factory :user do
initialize_with { new(name) }
name { 'value' }
end
end
build(:user)
# runs
User.new('value')
```
This prevents duplicate assignment; in versions of factory\_bot before 4.0, it
would run this:
```ruby
FactoryBot.define do
factory :user do
initialize_with { new(name) }
name { 'value' }
end
end
build(:user)
# runs
user = User.new('value')
user.name = 'value'
```
================================================
FILE: docs/src/custom-methods-to-persist-objects/summary.md
================================================
# Custom Methods to Persist Objects
By default, creating a record will call `save!` on the instance; since this may
not always be ideal, you can override that behavior by defining `to_create` on
the factory:
```ruby
factory :different_orm_model do
to_create { |instance| instance.persist! }
end
```
To disable the persistence method altogether on create, you can `skip_create`
for that factory:
```ruby
factory :user_without_database do
skip_create
end
```
To override `to_create` for all factories, define it within the
`FactoryBot.define` block:
```ruby
FactoryBot.define do
to_create { |instance| instance.persist! }
factory :user do
name { "John Doe" }
end
end
```
================================================
FILE: docs/src/custom-strategies/summary.md
================================================
# Custom Strategies
There are times where you may want to extend behavior of factory\_bot by adding
a custom build strategy.
Strategies define two methods: `association` and `result`. `association`
receives a `FactoryBot::FactoryRunner` instance, upon which you can call `run`,
overriding the strategy if you want. The second method, `result`, receives a
`FactoryBot::Evaluation` instance. It provides a way to trigger callbacks (with
`notify`), `object` or `hash` (to get the result instance or a hash based on
the attributes defined in the factory), and `create`, which executes the
`to_create` callback defined on the factory.
To understand how factory\_bot uses strategies internally, it's probably
easiest to view the source for each of the four default strategies.
Here's an example of composing a strategy using `FactoryBot::Strategy::Create`
to build a JSON representation of your model.
```ruby
class JsonStrategy
def initialize
@strategy = FactoryBot.strategy_by_name(:create).new
end
delegate :association, to: :@strategy
def result(evaluation)
@strategy.result(evaluation).to_json
end
def to_sym
:json
end
end
```
For factory\_bot to recognize the new strategy, you can register it:
```ruby
FactoryBot.register_strategy(:json, JsonStrategy)
```
This allows you to call
```ruby
FactoryBot.json(:user)
```
Finally, you can override factory\_bot's own strategies if you'd like by
registering a new object in place of the strategies.
================================================
FILE: docs/src/defining/best-practices.md
================================================
# Best practices
It is recommended that you have one factory for each class that provides
the simplest set of attributes necessary to create an instance of that class. If
you're creating ActiveRecord objects, that means that you should only provide
attributes that are required through validations and that do not have defaults.
Other factories can be created through inheritance to cover common scenarios for
each class.
Attempting to define multiple factories with the same name will raise an error.
================================================
FILE: docs/src/defining/explicit-class.md
================================================
# Specifying the class explicitly
It is also possible to explicitly specify the class:
```ruby
# This will use the User class (otherwise Admin would have been guessed)
factory :admin, class: "User"
```
You can pass a constant as well, if the constant is available (note that this
can cause test performance problems in large Rails applications, since
referring to the constant will cause it to be eagerly loaded).
```ruby
factory :access_token, class: User
```
================================================
FILE: docs/src/defining/file-paths.md
================================================
# Definition file paths
Factories can be defined anywhere, but will be automatically loaded after
calling `FactoryBot.find_definitions` if factories are defined in files at the
following locations:
factories.rb
factories/**/*.rb
test/factories.rb
test/factories/**/*.rb
spec/factories.rb
spec/factories/**/*.rb
================================================
FILE: docs/src/defining/hash-attributes.md
================================================
# Hash attributes
Because of the block syntax in Ruby, defining attributes as `Hash`es (for
serialized/JSON columns, for example) requires two sets of curly brackets:
```ruby
factory :program do
configuration { { auto_resolve: false, auto_define: true } }
end
```
Alternatively you may prefer `do`/`end` syntax:
```ruby
factory :program do
configuration do
{ auto_resolve: false, auto_define: true }
end
end
```
---
However, defining a value as a hash makes it complicated to set values within
the hash when constructing an object. Instead, prefer to use factory\_bot
itself:
```ruby
factory :program do
configuration { attributes_for(:configuration) }
end
factory :configuration do
auto_resolve { false }
auto_define { true }
end
```
This way you can more easily set value when building:
```ruby
create(
:program,
configuration: attributes_for(
:configuration,
auto_resolve: true,
)
)
```
================================================
FILE: docs/src/defining/name-attributes.md
================================================
# Factory name and attributes
Each factory has a name and a set of attributes. The name is used to guess the
class of the object by default:
```ruby
# This will guess the User class
FactoryBot.define do
factory :user do
first_name { "John" }
last_name { "Doe" }
admin { false }
end
end
```
================================================
FILE: docs/src/defining/static-attributes.md
================================================
# Static Attributes
Static attributes (without a block) are no longer available in factory\_bot 5.
You can read more about the decision to remove them in
[this blog post](https://robots.thoughtbot.com/deprecating-static-attributes-in-factory_bot-4-11).
================================================
FILE: docs/src/defining/summary.md
================================================
# Defining factories
================================================
FILE: docs/src/dependent-attributes/summary.md
================================================
# Dependent Attributes
Attributes can be based on the values of other attributes using the context
that is yielded to dynamic attribute blocks:
```ruby
factory :user do
first_name { "Joe" }
last_name { "Blow" }
email { "#{first_name}.#{last_name}@example.com".downcase }
end
create(:user, last_name: "Doe").email
# => "joe.doe@example.com"
```
================================================
FILE: docs/src/inheritance/assigning-parent-explicitly.md
================================================
# Assigning parent explicitly
You can also assign the parent explicitly:
```ruby
factory :post do
title { "A title" }
end
factory :approved_post, parent: :post do
approved { true }
end
```
================================================
FILE: docs/src/inheritance/best-practices.md
================================================
# Best practices
As mentioned above, it's good practice to define a basic factory for each class
with only the attributes required to create it. Then, create more specific
factories that inherit from this basic parent.
================================================
FILE: docs/src/inheritance/nested-factories.md
================================================
# Nested factories
You can create multiple factories for the same class without repeating common
attributes by nesting factories:
```ruby
factory :post do
title { "A title" }
factory :approved_post do
approved { true }
end
end
approved_post = create(:approved_post)
approved_post.title # => "A title"
approved_post.approved # => true
```
================================================
FILE: docs/src/inheritance/summary.md
================================================
# Inheritance
================================================
FILE: docs/src/intro.md
================================================
# Intro
factory_bot is a fixtures replacement with a straightforward definition syntax,
support for multiple build strategies (saved instances, unsaved instances,
attribute hashes, and stubbed objects), and support for multiple factories for
the same class (user, admin_user, and so on), including factory inheritance.
Its documentation is split as such:
- the [guide](setup/summary.html) is a great place to start for first-time users.
- the [cookbook](cookbook/has_many-associations.html) is the go-to place for creative solutions to common situations.
- the [wiki](https://github.com/thoughtbot/factory_bot/wiki) details considerations for integrating with other software.
- the [reference](ref/build-strategies.html) is terse facts for those who use this project often.
## License
factory_bot is Copyright © 2008 Joe Ferris and thoughtbot. It is free
software, and may be redistributed under the terms specified in the
[LICENSE] file.
[LICENSE]: https://github.com/thoughtbot/factory_bot/blob/main/LICENSE
## About thoughtbot
factory_bot is maintained and funded by thoughtbot, inc.
The names and logos for thoughtbot are trademarks of thoughtbot, inc.
We love open source software!
See [our other projects][community] or
[hire us][hire] to design, develop, and grow your product.
[community]: https://thoughtbot.com/community?utm_source=github
[hire]: https://thoughtbot.com/hire-us?utm_source=github
================================================
FILE: docs/src/linting-factories/summary.md
================================================
# Linting Factories
factory\_bot allows for linting known factories:
```ruby
FactoryBot.lint
```
`FactoryBot.lint` creates each factory and catches any exceptions raised during
the creation process. `FactoryBot::InvalidFactoryError` is raised with a list
of factories (and corresponding exceptions) for factories which could not be
created.
Recommended usage of `FactoryBot.lint` is to run this in a separate task before
your test suite is executed. Running it in a `before(:suite)` will negatively
impact the performance of your tests when running single tests.
Example Rake task:
```ruby
# lib/tasks/factory_bot.rake
namespace :factory_bot do
desc "Verify that all FactoryBot factories are valid"
task lint: :environment do
if Rails.env.test?
conn = ActiveRecord::Base.connection
conn.transaction do
FactoryBot.lint
raise ActiveRecord::Rollback
end
else
system("bundle exec rake factory_bot:lint RAILS_ENV='test'")
fail if $?.exitstatus.nonzero?
end
end
end
```
After calling `FactoryBot.lint`, you'll likely want to clear out the database,
as records will most likely be created. The provided example above uses an SQL
transaction and rollback to leave the database clean.
You can lint factories selectively by passing only factories you want linted:
```ruby
factories_to_lint = FactoryBot.factories.reject do |factory|
factory.name =~ /^old_/
end
FactoryBot.lint factories_to_lint
```
This would lint all factories that aren't prefixed with `old_`.
Traits can also be linted. This option verifies that each and every trait of a
factory generates a valid object on its own. This is turned on by passing
`traits: true` to the `lint` method:
```ruby
FactoryBot.lint traits: true
```
This can also be combined with other arguments:
```ruby
FactoryBot.lint factories_to_lint, traits: true
```
You can also specify the strategy used for linting:
```ruby
FactoryBot.lint strategy: :build
```
Verbose linting will include full backtraces for each error, which can be
helpful for debugging:
```ruby
FactoryBot.lint verbose: true
```
================================================
FILE: docs/src/method-name-reserved-word-attributes/summary.md
================================================
# Method Name / Reserved Word Attributes
If your attributes conflict with existing methods or reserved words (all
methods in the
[DefinitionProxy](https://github.com/thoughtbot/factory_bot/blob/main/lib/factory_bot/definition_proxy.rb)
class) you can define them with `add_attribute`.
```ruby
factory :dna do
add_attribute(:sequence) { 'GATTACA' }
end
factory :payment do
add_attribute(:method) { 'paypal' }
end
```
================================================
FILE: docs/src/modifying-factories/summary.md
================================================
# Modifying factories
If you're given a set of factories (say, from a gem developer) but want to
change them to fit into your application better, you can modify that factory
instead of creating a child factory and adding attributes there.
If a gem were to give you a User factory:
```ruby
FactoryBot.define do
factory :user do
full_name { "John Doe" }
sequence(:username) { |n| "user#{n}" }
password { "password" }
end
end
```
Instead of creating a child factory that added additional attributes:
```ruby
FactoryBot.define do
factory :application_user, parent: :user do
full_name { "Jane Doe" }
date_of_birth { 21.years.ago }
health { 90 }
end
end
```
You could modify that factory instead.
```ruby
FactoryBot.modify do
factory :user do
full_name { "Jane Doe" }
date_of_birth { 21.years.ago }
health { 90 }
end
end
```
When modifying a factory, you can change any of the attributes you want (aside from callbacks).
`FactoryBot.modify` must be called outside of a `FactoryBot.define` block as it
operates on factories differently.
A caveat: you can only modify factories (not sequences or traits), and
callbacks *still compound as they normally would*. So, if the factory you're
modifying defines an `after(:create)` callback, you defining an
`after(:create)` won't override it, it will instead be run after the first
callback.
================================================
FILE: docs/src/rails-preloaders-and-rspec/summary.md
================================================
# Rails Preloaders and RSpec
When running RSpec with a Rails preloader such as `spring` or `zeus`, it's
possible to encounter an `ActiveRecord::AssociationTypeMismatch` error when
creating a factory with associations, as below:
```ruby
FactoryBot.define do
factory :united_states, class: "Location" do
name { 'United States' }
association :location_group, factory: :north_america
end
factory :north_america, class: "LocationGroup" do
name { 'North America' }
end
end
```
The error occurs during the run of the test suite:
```
Failure/Error: united_states = create(:united_states)
ActiveRecord::AssociationTypeMismatch:
LocationGroup(#70251250797320) expected, got LocationGroup(#70251200725840)
```
The two possible solutions are to either run the suite without the preloader,
or to add `FactoryBot.reload` to the RSpec configuration, like so:
```ruby
RSpec.configure do |config|
config.before(:suite) { FactoryBot.reload }
end
```
================================================
FILE: docs/src/ref/add_attribute.md
================================================
# add_attribute
Within a factory definition, the `add_attribute` method defines a key/value
pair that will be set when the object is built.
The `add_attribute` method takes two arguments: a name (Symbol or String) and a
block. This block is called each time this object is constructed. The block is
not called when the attribute is overridden by a build strategy.
Assignment is done by calling the Ruby attribute setter. For example, given
```ruby
FactoryBot.define do
factory :user do
add_attribute(:name) { "Acid Burn" }
end
end
```
This will use the `#name=` setter:
```ruby
user = User.new
user.name = "Acid Burn"
```
Also see [method_missing](method_missing.html) for a shorthand.
================================================
FILE: docs/src/ref/association.md
================================================
# association
Within a factory block, use the `association` method to always make an
additional object alongside this one. This name best makes sense within the
context of ActiveRecord.
The `association` method takes a mandatory name and optional options.
The options are zero or more trait names (Symbols), followed by a hash
of attribute overrides. When constructing this association, factory\_bot uses
the trait and attribute overrides given.
See [method_missing](method_missing.html) for a shorthand. See [build
strategies](build-strategies.html) for an explanation of how each build
strategy handles associations.
================================================
FILE: docs/src/ref/build-and-create.md
================================================
# skip_create, to_create, and initialize_with
The `skip_create`, `to_create`, and `initialize_with` methods control how
factory\_bot interacts with the [build strategies](build-strategies.html).
These methods can be called within a `factory` definition block, to scope their
effects to just that factory; or within `FactoryBot.define`, to affect global
change.
## initialize_with
The `initialize_with` method takes a block and returns an instance of the
factory's class. It has access to the `attributes` method, which is a hash of
all the fields and values for the object.
The default definition is:
```ruby
initialize_with { new }
```
## to_create
The `to_create` method lets you control the `FactoryBot.create` strategy. This
method takes a block which takes the object as constructed by
`initialize_with`, and the factory\_bot context. The context has additional
data from any [`transient`] blocks.
[`transient`]: transient.html
The default definition is:
```ruby
to_create { |obj, context| obj.save! }
```
The `skip_create` method is a shorthand for turning `to_create` into a no-op.
This allows you to use the `create` strategy as a synonym for `build`, except
you additionally get any `create` hooks.
================================================
FILE: docs/src/ref/build-strategies.md
================================================
# Build strategies
Once a factory\_bot factory is defined, it can be constructed using any of the
built-in build strategies, or a custom build strategy.
All of these strategies notify on the `factory_bot.run_factory`
instrumentation using [ActiveSupport::Notifications], passing a payload with
`:name`, `:strategy`, `:traits`, `:overrides`, and `:factory` keys.
[ActiveSupport::Notifications]: https://api.rubyonrails.org/classes/ActiveSupport/Notifications.html
The non-list (`.build`, `.build_pair`, `.create`, etc.) methods take one
mandatory argument: the name of the factory. They can then optionally take
names of traits, and then a hash of attributes to override. Finally, they can
take a block. This block takes the produced object as an argument, and returns
an updated object.
The list methods (`.build_list`, `.create_list`, etc.) have two required
arguments: the name of the factory, and the number of instances to build. They
then can optionally take traits and overrides. Finally, they can take a block.
This block takes the produced object and the zero-based index as arguments, and
returns an updated object.
## `build`
The `FactoryBot.build` method constructs an instance of the class according to
`initialize_with`, which defaults to calling the `.new` class method.
`.build_list` constructs multiple instances, and `.build_pair` is a shorthand
to construct two instances.
After it calls `initialize_with`, it invokes the `after_build` hook.
Associations are constructed using the `build` build strategy.
## `create`
The `FactoryBot.create` method constructs an instance of the class according to
`initialize_with`, and then persists it using `to_create`. The `.create_list`
class method constructs multiple instances, and `.create_pair` is a shorthand
to construct two instances.
After it calls `initialize_with`, it invokes the following hooks in order:
1. `after_build`
1. `before_create`
1. non-hook: `to_create`
1. `after_create`
Associations are constructed using the `create` build strategy.
The `to_create` hook controls how objects are persisted. It takes a block with
the object and the factory\_bot context, and runs it for its side effect. By
default, it calls `#save!`.
## `attributes_for`
The `FactoryBot.attributes_for` method constructs a Hash with the attributes
and their values, using `initialize_with`. The `attributes_for_pair` and
`attributes_for_list` methods work similarly as `build_pair` and `build_list`.
Associations are constructed using the `null` build strategy (they are not built).
No hooks are called.
## `build_stubbed`
The `FactoryBot.build_stubbed` method returns a fake ActiveRecord object. The
`.build_stubbed_pair` and `.build_stubbed_list` methods are defined similarly
to `.build_pair` and `.build_list`.
It uses `initialize_with` to construct the object, but then stubs methods and
data as appropriate:
- `id` is set sequentially (unless overridden by attributes)
- `created_at` and `updated_at` are set to the current time (unless overridden by attributes)
- all [ActiveModel::Dirty] change tracking is cleared
- `persisted?` is true
- `new_record?` is false
- `destroyed?` is false
- persistence methods raise a `RuntimeError` (`#connection`, `#delete`, `#save`, `#update`, etc.)
[ActiveModel::Dirty]: https://api.rubyonrails.org/classes/ActiveModel/Dirty.html
After it sets up the object it invokes the `after_stub` hook.
## `null`
The `FactoryBot.null` method returns `nil`. The `.null_pair` method gives you a
pair of nils, and `.null_list` gives as many nils as you desire. This is used
internally.
================================================
FILE: docs/src/ref/define.md
================================================
# FactoryBot.define
Each file loaded by factory\_bot is expected to call `FactoryBot.define` with a
block. The block is evaluated within an instance of
`FactoryBot::Syntax::Default::DSL`, giving access to `factory`, `sequence`,
`trait`, and other methods.
================================================
FILE: docs/src/ref/factory.md
================================================
# factory
Within a `FactoryBot.define` block, you can define factories. Anything defined
using `factory` can be built using a [build strategy](build-strategies.html).
The `factory` method takes three arguments: a required name, an optional hash
of options, and an optional block.
The name is expected to be a Symbol.
## Options
- `:class` - what class to construct. This can be either a class, or a String
or Symbol (anything that responds to `#to_s`). By default it is either the
parent's class name or the factory's name.
- `:parent`- the name of another factory that this factory should inherit from.
Defaults to `nil`.
- `:aliases` - alternative names for this factory. Any of these names can be
used with a build strategy. Defaults to the empty list.
- `:traits` - base traits that are used by default when building this factory.
Defaults to the empty list.
## Block
You can use the block to define your factory. Within here you have access to the following methods:
- [`add_attribute`](add_attribute.md)
- [`association`](association.md)
- [`sequence`](sequence.md)
- [`trait`](trait.md)
- [`method_missing`](method_missing.md)
- [`transient`](transient.md)
- [`traits_for_enum`](traits_for_enum.md)
- [`initialize_with`](build-and-create.md#initialize_with)
- [`skip_create`](build-and-create.md)
- [`to_create`](build-and-create.md#to_create)
- [`before`](hooks.md#after-and-before-methods)
- [`after`](hooks.md#after-and-before-methods)
- [`callback`](hooks.md#callback)
- `factory`
You can use `factory` inside a `factory` block to define a new factory with an
implied parent.
================================================
FILE: docs/src/ref/find_definitions.md
================================================
# FactoryBot.find_definitions
The `FactoryBot.find_definitions` method loads in all factory\_bot definitions
across the project.
The load order is controlled by the `FactoryBot.definition_file_paths`
attribute. The default load order is:
1. `factories.rb`
1. `factories/**/*.rb`
1. `test/factories.rb`
1. `test/factories/**/*.rb`
1. `spec/factories.rb`
1. `spec/factories/**/*.rb`
## Rails
The `.find_definitions` method is called automatically by `factory_bot_rails`
after initialize. The `.definition_file_paths` can be set during initialization
(e.g. `config/initializers`), or via
`Rails.application.config.factory_bot.definition_file_paths`.
================================================
FILE: docs/src/ref/hooks.md
================================================
# Hooks
Within a `factory` definition block and the `FactoryBot.define` block, you have
access to the `after`, `before`, and `callback` methods. This allow you to hook
into parts of the [build strategies].
[build strategies]: build-strategies.html
Within a `factory` definition block, these callbacks are scoped to just that
factory. Within a `FactoryBot.define` block, they are global to all factories.
## `callback`
The `callback` method allows you to hook into any factory\_bot callback by
name. The pre-defined names, as seen in the [build strategies] reference, are
`before_all`, `after_build`, `before_create`, `after_create`, `after_stub`, and `after_all`.
This method takes a splat of names, and a block. It invokes the block any time
one of the names is activated. The block can be anything that responds to
`#to_proc`.
This block takes two arguments: the instance of the factory, and the
factory\_bot context. The context holds [transient](transient.html)
attributes.
The same callback name can be hooked into multiple times. Every block is run,
in the order it was defined. Callbacks are inherited from their parents; the
parents' callbacks are run first.
## `after` and `before` methods
The `after` and `before` methods add some nice syntax to `callback`:
```ruby
after(:create) do |user, context|
user.post_first_article(context.article)
end
callback(:after_create) do |user, context|
user.post_first_article(context.article)
end
```
================================================
FILE: docs/src/ref/lint.md
================================================
# FactoryBot.lint
The `FactoryBot.lint` method tries each factory and raises
`FactoryBot::InvalidFactoryError` on failure.
It can take the following optional arguments:
- A splat of factory names. This will restrict the linting to just the ones listed. The default is all.
- `:strategy` - the [build strategy] to use. The default is `:create`.
- `:traits` - whether to try building each trait, too. The default is `false`.
- `:verbose` - whether to show a stack trace on error. The default is `false`.
[build strategy]: build-strategies.html
Suggested techniques for hooking `.lint` into your system is discussed in [the
guide](../linting-factories/summary.html).
================================================
FILE: docs/src/ref/method_missing.md
================================================
# method_missing
With a `factory` definition block, you can use `add_attribute`, `association`,
`sequence`, and `trait` to define a factory. You can also level a default
`method_missing` definition for potential shortcuts.
Calling an unknown method (e.g. `name`, `admin`, `email`, `account`) connects
an association, sequence, trait, or attribute to the factory:
1. If the method missing is passed a block, it always defines an attribute.
This allows you to set the value for the attribute.
1. If the method missing is passed a hash as a argument with the key
`:factory`, then it always defines an association. This allows you to
override the factory used for the association.
1. If there is another factory of the same name, then it defines an
association.
1. If there is a global sequence of the same name, then it defines an attribute
with a value that pulls from the sequence.
1. If there is a trait of the same name for that factory, then it turns that
trait on for all builds of this factory.
Using `method_missing` can turn an explicit definition:
```ruby
FactoryBot.define do
sequence(:email) { |n| "person#{n}@example.com" }
factory :account
factory :organization
factory :user, traits: [:admin] do
add_attribute(:name) { "Lord Nikon" }
add_attribute(:email) { generate(:email) }
association :account
association :org, factory: :organization
trait :admin do
add_attribute(:admin) { true }
end
end
end
```
... into a more implicit definition:
```ruby
FactoryBot.define do
sequence(:email) { |n| "person#{n}@example.com" }
factory :account
factory :organization
factory :user do
name { "Lord Nikon" } # no more `add_attribute`
admin # no more :traits
email # no more `add_attribute`
account # no more `association`
org factory: :organization # no more `association`
trait :admin do
admin { true }
end
end
end
```
================================================
FILE: docs/src/ref/modify.md
================================================
# FactoryBot.modify
The `FactoryBot.modify` class method defines a block with an _overriding_
`factory` method available. That is the only method you can call within the
block.
The `factory` method within this block takes a mandatory factory name, and a
block. All other arguments are ignored. The factory name must already be
defined. The block is a normal [factory definition block](factory.html). Take
note that [hooks](hooks.html) cannot be cleared and continue to compound.
For details on why you'd want to use this, see [the
guide](../modifying-factories/summary.html).
================================================
FILE: docs/src/ref/register_strategy.md
================================================
# FactoryBot.register_strategy
The `FactoryBot.register_strategy` method is how to add a [build
strategy](build-strategies.html).
It takes two mandatory arguments: name and class. The name is a Symbol, and
registering it exposes a method under `FactoryBot::Syntax::Methods`.
The class must define the methods `association` and `result`.
The `association` method takes an instance of `FactoryRunner`. You can `#run`
this runner, passing a strategy name (it defaults to the current one) and an
optional block. The block is called after the association is built, and is
passed the object that was built.
The `result` method takes the object that was built for this factory (using
`initalize_with`), and returns the result of this factory for this build
strategy.
================================================
FILE: docs/src/ref/sequence.md
================================================
# sequence
A factory\_bot set up supports two levels of sequences: global and factory-specific.
## Global sequences
With a [`Factory.define`] block, use the `sequence` method to define global
sequences that can be shared with other factories.
[`Factory.define`]: define.html
The `sequence` method takes a name, optional arguments, and a block. The name
is expected to be a Symbol.
The supported arguments are a number representing the starting value (default:
`1`), and `:aliases` (default `[]`). The starting value must respond to `#next`.
The block takes a value as an argument, and returns a result.
The sequence value is incremented globally. Using an `:email_address` sequence
from multiple places increments the value each time.
See [method_missing](method_missing.html) for a shorthand.
## Factory sequences
Sequences can be localized within `factory` blocks. The syntax is the same as
for a global sequence, but the scope of the incremented value is limited to the
factory definition.
In addition, using `sequence` with a `factory` block implicitly calls
`add_attribute` for that value.
These two are similar, except the second example does not cause any global
sequences to exist:
```ruby
# A global sequence
sequence(:user_factory_email) { |n| "person#{n}@example.com" }
factory :user do
# Using a global sequence
email { generate(:user_factory_email) }
end
```
```ruby
# A factory-scoped sequence
factory :user do
sequence(:email) { |n| "person#{n}@example.com" }
end
```
================================================
FILE: docs/src/ref/trait.md
================================================
# trait
Within a `factory` definition block, use the `trait` method to define named permutations of the factory.
The trait method takes a name (Symbol) and a block. Treat the block like you
would a [`factory`] definition block.
[`factory`]: factory.html
See [method_missing](method_missing.html) for a shorthand.
================================================
FILE: docs/src/ref/traits_for_enum.md
================================================
# traits_for_enum
With a `factory` definition block, the `traits_for_enum` method is a helper for
any object with an attribute that can be one of a few values. The original
inspiration was [`ActiveRecord::Enum`] but it can apply to any attribute with a
restricted set of values.
[`ActiveRecord::Enum`]: https://api.rubyonrails.org/classes/ActiveRecord/Enum.html
This method creates a trait for each value.
The `traits_for_enum` method takes a required attribute name and an optional
set of values. The values can be any Enumerable, such as Array or Hash. By
default, the values are `nil`.
If the values are an Array, this method defines a trait for each element in the
array. The trait's name is the array element, and it sets the attribute to the
same array element.
If the values are a Hash, this method defines traits based on the keys,
setting the attribute to the values. The trait's name is the key, and it sets
the attribute to the value.
If the value is any other Enumerable, it treats it like an Array or Hash based
on whether `#each` iterates in pairs like it does for Hashes.
If the value is nil, it uses a class method named after the pluralized
attribute name.
```ruby
FactoryBot.define do
factory :article do
traits_for_enum :visibility, [:public, :private]
# trait :public do
# visibility { :public }
# end
# trait :private do
# visibility { :private }
# end
traits_for_enum :collaborative, draft: 0, shared: 1
# trait :draft do
# collaborative { 0 }
# end
# trait :shared do
# collaborative { 1 }
# end
traits_for_enum :status
# Article.statuses.each do |key, value|
# trait key do
# status { value }
# end
# end
end
end
```
================================================
FILE: docs/src/ref/transient.md
================================================
# transient
Within a `factory` definition block, the goal is to construct an instance of
the class. While factory\_bot does this, it keeps track of data in a
context. To set data on this context, use a `transient` block.
Treat a `transient` block like a `factory` definition block. However, none of
the attributes, associations, traits, or sequences you set will impact the
final object.
This is most useful when paired with [hooks](hooks.html) or
[to_create](build-and-create.html).
================================================
FILE: docs/src/sequences/aliases.md
================================================
# Aliases
Sequences can also have aliases. The sequence aliases share the same counter:
```ruby
factory :user do
sequence(:email, 1000, aliases: [:sender, :receiver]) { |n| "person#{n}@example.com" }
end
# will increase value counter for :email which is shared by :sender and :receiver
generate(:sender)
```
Define aliases and use default value (1) for the counter
```ruby
factory :user do
sequence(:email, aliases: [:sender, :receiver]) { |n| "person#{n}@example.com" }
end
```
Setting the value:
```ruby
factory :user do
sequence(:email, 'a', aliases: [:sender, :receiver]) { |n| "person#{n}@example.com" }
end
```
The value needs to support the `#next` method. Here the next value will be 'a',
then 'b', etc.
================================================
FILE: docs/src/sequences/as-implicit-attributes.md
================================================
# As implicit attributes
Or as implicit attributes:
```ruby
FactoryBot.define do
sequence :email do |n|
"person#{n}@example.com"
end
end
factory :user do
email # Same as `email { generate(:email) }`
end
```
Note that defining sequences as implicit attributes will not work if you have a
factory with the same name as the sequence.
================================================
FILE: docs/src/sequences/factory-sequences.md
================================================
# Factory sequences
And it's also possible to define a sequence that is only used in
a particular factory:
```ruby
factory :user do
sequence(:email) { |n| "person#{n}@example.com" }
end
```
With Ruby 2.7's support for [numbered parameters][], inline definitions can be
even more abbreviated:
```ruby
factory :user do
sequence(:email) { "person#{_1}@example.com" }
end
```
[numbered parameters]: https://ruby-doc.org/core-2.7.1/Proc.html#class-Proc-label-Numbered+parameters
================================================
FILE: docs/src/sequences/generating.md
================================================
# Generating a Sequence
Being able to directly generate a sequence, without having to build the object can really speed up testing. This can be achieved by passing the [sequence URI](sequence-uris.md) to `:generate` for a single value or `:generate_list` for an Array of sequential values.
```ruby
FactoryBot.define do
sequence(:char, 'a') {|c| "global_character_#{c}" }
factory :user do
sequence(:name, %w[Jane Joe Josh Jayde John].to_enum)
trait :with_age do
sequence(:age, 21)
end
end
end
##
# char
generate(:char) # "global_character_a"
generate_list(:char, 2) # ["global_character_b", "global_character_c"]
generate(:char) # "global_character_d"
##
# user name
generate(:user, :name) # "Jane"
generate_list(:user, :name, 3) # ['Joe', 'Josh', 'Jayde']
generate(:user, :name) # "John"
##
# user age
generate(:user, :with_age, :age) # 21
generate_list(:user, :with_age, :age, 5) # [22, 23, 24, 25, 26]
generate(:user, :with_age, :age) # 27
```
## Scope
On occasion a sequence block may refer to a scoped attribute. In this case, the scope must be provided, or else an exception will be raised:
```ruby
FactoryBot.define do
factory :user do
sequence(:email) { |n| "#{name}-#{n}@example.com" }
end
end
generate(:user, :email)
# ArgumentError, Sequence user:email failed to return a value. Perhaps it needs a scope to operate? (scope: <object>)
jester = build(:user, name: "Jester")
jester.email # "Jester-1@example.com"
generate(:user, :email, scope: jester)
# "Jester-2@example.com"
generate_list(:user, :email, 2, scope: jester)
# ["Jester-3@example.com", "Jester-4@example.com"]
```
When testing, the scope can be any object that responds to the referenced attributes:
```ruby
require 'ostruct'
FactoryBot.define
factory :user do
sequence(:info) { |n| "#{name}-#{n}-#{age + n}" }
end
end
test_scope = OpenStruct.new(name: "Jester", age: 23)
generate_list('user/info', 3, scope: test_scope)
# ["Jester-1-24", "Jester-2-25", "Jester-3-26"]
```
================================================
FILE: docs/src/sequences/global-sequences.md
================================================
# Global sequences
Unique values in a specific format (for example, e-mail addresses) can be
generated using sequences. Sequences are defined by calling `sequence` in a
definition block, and values in a sequence are generated by calling `generate`:
```ruby
# Defines a new sequence
FactoryBot.define do
sequence :email do |n|
"person#{n}@example.com"
end
end
generate :email
# => "person1@example.com"
generate :email
# => "person2@example.com"
```
================================================
FILE: docs/src/sequences/initial-value.md
================================================
# Initial value
You can override the initial value. Any value that responds to the `#next`
method will work (e.g. 1, 2, 3, 'a', 'b', 'c')
```ruby
factory :user do
sequence(:email, 1000) { |n| "person#{n}@example.com" }
end
```
The initial value can also be lazily set by passing a Proc as the value. This Proc will be called the first time the `sequence.next` is called.
```ruby
factory :user do
sequence(:email, proc { Person.count + 1 }) { |n| "person#{n}@example.com" }
end
```
================================================
FILE: docs/src/sequences/rewinding.md
================================================
# Rewinding
Sequences can also be rewound to their starting value:
## All sequences
Rewind all global and factory sequences with `FactoryBot.rewind_sequences`:
```ruby
FactoryBot.define do
sequence(:email) {|n| "person#{n}@example.com" }
factory :user do
sequence(:email) {|n| "user#{n}@example.com" }
end
end
generate(:email) # "person1@example.com"
generate(:email) # "person2@example.com"
generate(:email) # "person3@example.com"
generate(:user, :email) # "user1@example.com"
generate(:user, :email) # "user2@example.com"
generate(:user, :email) # "user3@example.com"
FactoryBot.rewind_sequences
generate(:email) # "person1@example.com"
generate(:user, :email) # "user1@example.com"
```
## Individual sequences
An individual sequence can be rewound by passing the [sequence URI](sequence-uris.md) to `FactoryBot.rewind_sequence`:
```ruby
FactoryBot.define do
sequence(:email) {|n| "global_email_#{n}@example.com" }
factory :user do
sequence(:email) {|n| "user_email_#{n}@example.com" }
end
end
FactoryBot.rewind_sequence(:email)
generate(:email)
#=> "global_email_1@example.com"
factoryBot.rewind_sequence(:user, :email)
generate(:user, :email)
#=> "user_email_1@example.com"
```
================================================
FILE: docs/src/sequences/sequence-uris.md
================================================
# Sequence URIs
There are many reasons to manipulate a specific sequence:
- generating a single value with: `generate`
- generating multiple values with: `generate_list`
- setting it to a new value with `FactoryBot.set_sequence`
- rewinding it with: `rewind_sequence`
To accomplish this we need to be able to reference the desired sequence. This is achieved with its unique URI.
## URI Composition
Each URI is composed of up to three names:
| position | name | required |
| :------: | -------------- | -------------------------------------------------------------------- |
| 1. | factory name: | **if** - the sequence is defined within a Factory or a Factory Trait |
| 2. | trait name: | **if** - the sequence is defined within a Trait |
| 3. | sequence name: | **always required** |
The URI can be entered as individual symbols:
```ruby
generate(:my_factory_name, :my_trait_name, :my_sequence_name)
```
**or** as individual strings:
```ruby
generate('my_factory_name', 'my_trait_name', 'my_sequence_name')
```
**or** as a single resource string:
```ruby
generate("my_factory_name/my_trait_name/my_sequence_name")
```
## Full URI example
This example details all the possible scenarios, with the comments showing the URI used to generate a value for each specific sequence:
```ruby
FactoryBot.define do
sequence(:sequence) {|n| "global_sequence_#{n}"}
# generate(:sequence)
trait :global_trait do
sequence(:sequence) {|n| "global_trait_sequence_#{n}"}
# generate(:global_trait, :sequence)
end
factory :user do
sequence(:sequence) {|n| "user_sequence_#{n}"}
# generate(:user, :sequence)
trait :user_trait do
sequence(:sequence) {|n| "user_trait_sequence_#{n}"}
# generate(:user, :user_trait, :sequence)
end
factory :author do
sequence(:sequence) {|n| "author_sequence_#{n}"}
# generate(:author, :sequence)
trait :author_trait do
sequence(:sequence) {|n| "author_trait_sequence_#{n}"}
# generate(:author, :author_trait, :sequence)
end
end
end
end
```
## Multi URIs
It is possible for a single sequence to have multiple URIs.
If the factory or trait has aliases, the sequence will have an additional URI for each alias, or combination of aliases.
In this example, the same sequence can referenced in four different ways:
```ruby
factory :user, aliases: [:author] do
trait :user_trait, aliases: [:author_trait] do
sequence(:sequence) {|n| "author_trait_sequence_#{n}"}
end
end
# generate(:user, :user_trait, :sequence)
# generate(:user, :author_trait, :sequence)
# generate(:author, :user_trait, :sequence)
# generate(:author, :author_trait, :sequence)
```
<div class='warning'>
## Important
- No matter how deeply nested, the factory name component of the URI is always the factory where the sequence is defined, not any parent factories.
- If a factory inherits a sequence, the URI must reference the factory where it was defined, not the one in which it is used.
</div>
================================================
FILE: docs/src/sequences/setting-the-value.md
================================================
# Setting the value
When testing or working in the console, being able to set the sequence to a specific value, is incredibly helpful. This can be achieved by passing the [sequence URI](sequence-uris.md) and the new value to `FactoryBot.set_sequence`:
## Global Sequences
Global sequences are set with the sequence name and the new value:
```ruby
FactoryBot.define do
sequence(:char, 'a') {|c| "global_character_#{c}" }
factory :user do
sequence(:name, %w[Jane Joe Josh Jayde John].to_enum)
trait :with_email do
sequence(:email) {|n| "user_#{n}@example.com" }
end
end
end
##
# char
generate(:char) # "global_character_a"
FactoryBot.set_sequence(:char, 'z')
generate(:char) # "global_character_z"
##
# user name
generate(:user, :name) # "Jane"
FactoryBot.set_sequence(:user, :name, 'Jayde')
generate(:user, :name) # "Jayde"
##
# user email
generate(:user, :with_email, :email) # "user_1@example.com"
FactoryBot.set_sequence(:user, :with_email, :email, 1_234_567)
generate(:user, :with_email, :email) # "user_1234567@example.com"
```
<div class='warning'>
## Note
- The new value must match the sequence collection: You cannot pass a String to an Integer based sequence!
- An integer based sequence, such as a record ID, can accept any positive integer as the value.
- A fixed collection sequence can accept any value within the collection.
- An unlimited sequence, such as a character `sequence(:unlimited,'a')` will timeout if not found within the default maximum search time of three seconds.
- The timeout can be configured with: `FactoryBot.sequence_setting_timeout = 1.5`
</div>
================================================
FILE: docs/src/sequences/summary.md
================================================
# Sequences
================================================
FILE: docs/src/sequences/uniqueness.md
================================================
# Uniqueness
When working with uniqueness constraints, be careful not to pass in override
values that will conflict with the generated sequence values.
In this example the email will be the same for both users. If email must be
unique, this code will error:
```rb
factory :user do
sequence(:email) { |n| "person#{n}@example.com" }
end
FactoryBot.create(:user, email: "person1@example.com")
FactoryBot.create(:user)
```
================================================
FILE: docs/src/sequences/with-dynamic-attributes.md
================================================
# With dynamic attributes
Sequences can be used in dynamic attributes:
```ruby
FactoryBot.define do
sequence :email do |n|
"person#{n}@example.com"
end
end
factory :invite do
invitee { generate(:email) }
end
```
================================================
FILE: docs/src/sequences/without-a-block.md
================================================
# Without a block
Without a block, the value will increment itself, starting at its initial value:
```ruby
factory :post do
sequence(:position)
end
```
Note that the value for the sequence could be any Enumerable instance, as long
as it responds to `#next`:
```ruby
factory :task do
sequence :priority, %i[low medium high urgent].cycle
end
```
================================================
FILE: docs/src/setup/summary.md
================================================
# Setup
Installation varies based on the framework you are using, if any, and
optionally the test framework.
Since installation varies based on code that we do not control, those docs are
kept up-to-date in [our wiki]. We encourage you to edit the wiki as the
frameworks change.
Below we document the most common setup. However, **we go into more detail in
[our wiki]**.
[our wiki]: https://github.com/thoughtbot/factory_bot/wiki/Installation
## Update Your Gemfile
If you're using Rails:
```ruby
gem "factory_bot_rails"
```
If you're *not* using Rails:
```ruby
gem "factory_bot"
```
For more, see [our wiki].
## Configure your test suite
### RSpec
```ruby
RSpec.configure do |config|
config.include FactoryBot::Syntax::Methods
end
```
### Test::Unit
```ruby
class Test::Unit::TestCase
include FactoryBot::Syntax::Methods
end
```
For more, see [our wiki].
================================================
FILE: docs/src/traits/as-implicit-attributes.md
================================================
# As implicit attributes
Traits can be used as implicit attributes:
```ruby
factory :week_long_published_story_with_title, parent: :story do
published
week_long_publishing
title { "Publishing that was started at #{start_at}" }
end
```
Note that defining traits as implicit attributes will not work if you have a
factory or sequence with the same name as the trait.
================================================
FILE: docs/src/traits/attribute-precedence.md
================================================
# Attribute precedence
Traits that define the same attributes won't raise AttributeDefinitionErrors;
the trait that defines the attribute last gets precedence.
```ruby
factory :user do
name { "Friendly User" }
login { name }
trait :active do
name { "John Doe" }
status { :active }
login { "#{name} (active)" }
end
trait :inactive do
name { "Jane Doe" }
status { :inactive }
login { "#{name} (inactive)" }
end
trait :admin do
admin { true }
login { "admin-#{name}" }
end
factory :active_admin, traits: [:active, :admin] # login will be "admin-John Doe"
factory :inactive_admin, traits: [:admin, :inactive] # login will be "Jane Doe (inactive)"
end
```
================================================
FILE: docs/src/traits/defining-traits.md
================================================
# Defining traits
Traits allow you to group attributes together and then apply them
to any factory.
```ruby
factory :user, aliases: [:author]
factory :story do
title { "My awesome story" }
author
trait :published do
published { true }
end
trait :unpublished do
published { false }
end
trait :week_long_publishing do
start_at { 1.week.ago }
end_at { Time.now }
end
trait :month_long_publishing do
start_at { 1.month.ago }
end_at { Time.now }
end
factory :week_long_published_story, traits: [:published, :week_long_publishing]
factory :month_long_published_story, traits: [:published, :month_long_publishing]
factory :week_long_unpublished_story, traits: [:unpublished, :week_long_publishing]
factory :month_long_unpublished_story, traits: [:unpublished, :month_long_publishing]
end
```
================================================
FILE: docs/src/traits/enum.md
================================================
# Enum traits
Given an Active Record model with an enum attribute:
```rb
class Task < ActiveRecord::Base
enum status: {queued: 0, started: 1, finished: 2}
end
```
factory\_bot will automatically define traits for each possible value of the
enum:
```rb
FactoryBot.define do
factory :task
end
FactoryBot.build(:task, :queued)
FactoryBot.build(:task, :started)
FactoryBot.build(:task, :finished)
```
Writing the traits out manually would be cumbersome, and is not necessary:
```rb
FactoryBot.define do
factory :task do
trait :queued do
status { :queued }
end
trait :started do
status { :started }
end
trait :finished do
status { :finished }
end
end
end
```
If automatically defining traits for enum attributes on every factory is not
desired, it is possible to disable the feature by setting
`FactoryBot.automatically_define_enum_traits = false`
In that case, it is still possible to explicitly define traits for an enum
attribute in a particular factory:
```rb
FactoryBot.automatically_define_enum_traits = false
FactoryBot.define do
factory :task do
traits_for_enum(:status)
end
end
```
It is also possible to use this feature for other enumerable values, not
specifically tied to Active Record enum attributes.
With an array:
```rb
class Task
attr_accessor :status
end
FactoryBot.define do
factory :task do
traits_for_enum(:status, ["queued", "started", "finished"])
end
end
```
Or with a hash:
```rb
class Task
attr_accessor :status
end
FactoryBot.define do
factory :task do
traits_for_enum(:status, { queued: 0, started: 1, finished: 2 })
end
end
```
================================================
FILE: docs/src/traits/in-child-factories.md
================================================
# In child factories
You can override individual attributes granted by a trait in a child factory:
```ruby
factory :user do
name { "Friendly User" }
login { name }
trait :active do
name { "John Doe" }
status { :active }
login { "#{name} (M)" }
end
factory :brandon do
active
name { "Brandon" }
end
end
```
================================================
FILE: docs/src/traits/mixins.md
================================================
# As mixins
Traits can be defined outside of factories and used as mixins to compose shared
attributes:
```ruby
FactoryBot.define do
trait :timestamps do
created_at { 8.days.ago }
updated_at { 4.days.ago }
end
factory :user, traits: [:timestamps] do
username { "john_doe" }
end
factory :post do
timestamps
title { "Traits rock" }
end
end
```
================================================
FILE: docs/src/traits/summary.md
================================================
# Traits
Traits allow you to group attributes together and then apply them
to any factory.
```ruby
factory :user, aliases: [:author]
factory :story do
title { "My awesome story" }
author
trait :published do
published { true }
end
trait :unpublished do
published { false }
end
trait :week_long_publishing do
start_at { 1.week.ago }
end_at { Time.now }
end
trait :month_long_publishing do
start_at { 1.month.ago }
end_at { Time.now }
end
factory :week_long_published_story, traits: [:published, :week_long_publishing]
factory :month_long_published_story, traits: [:published, :month_long_publishing]
factory :week_long_unpublished_story, traits: [:unpublished, :week_long_publishing]
factory :month_long_unpublished_story, traits: [:unpublished, :month_long_publishing]
end
```
================================================
FILE: docs/src/traits/traits-within-traits.md
================================================
# Traits within traits
Traits can be used within other traits to mix in their attributes.
```ruby
factory :order do
trait :completed do
completed_at { 3.days.ago }
end
trait :refunded do
completed
refunded_at { 1.day.ago }
end
end
```
================================================
FILE: docs/src/traits/using.md
================================================
# Using traits
Traits can also be passed in as a list of Symbols when you construct an instance
from factory\_bot.
```ruby
factory :user do
name { "Friendly User" }
trait :active do
name { "John Doe" }
status { :active }
end
trait :admin do
admin { true }
end
end
# creates an admin user with :active status and name "Jon Snow"
create(:user, :admin, :active, name: "Jon Snow")
```
This ability works with `build`, `build_stubbed`, `attributes_for`, and `create`.
`create_list` and `build_list` methods are supported as well. Remember to pass
the number of instances to create/build as second parameter, as documented in
the "Building or Creating Multiple Records" section of this file.
```ruby
factory :user do
name { "Friendly User" }
trait :active do
name { "John Doe" }
status { :active }
end
trait :admin do
admin { true }
end
end
# creates 3 admin users with :active status and name "Jon Snow"
create_list(:user, 3, :admin, :active, name: "Jon Snow")
```
================================================
FILE: docs/src/traits/with-associations.md
================================================
# With associations
Traits can be used with associations easily too:
```ruby
factory :user do
name { "Friendly User" }
trait :admin do
admin { true }
end
end
factory :post do
association :user, :admin, name: 'John Doe'
end
# creates an admin user with name "John Doe"
create(:post).user
```
When you're using association names that are different than the factory:
```ruby
factory :user do
name { "Friendly User" }
trait :admin do
admin { true }
end
end
factory :post do
association :author, :admin, factory: :user, name: 'John Doe'
# or
association :author, factory: [:user, :admin], name: 'John Doe'
end
# creates an admin user with name "John Doe"
create(:post).author
```
===============================
gitextract_cvhgehfx/
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.md
│ │ └── feature_request.md
│ ├── REPRODUCTION_SCRIPT.rb
│ ├── dependabot.yml
│ └── workflows/
│ ├── build.yml
│ ├── docs.yml
│ ├── dynamic-readme.yml
│ └── dynamic-security.yml
├── .gitignore
├── .irbrc
├── .rspec
├── .simplecov
├── .standard.yml
├── .standard_todo.yml
├── .yardopts
├── Appraisals
├── CODEOWNERS
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── GETTING_STARTED.md
├── Gemfile
├── LICENSE
├── NAME.md
├── NEWS.md
├── README.md
├── RELEASING.md
├── Rakefile
├── SECURITY.md
├── cucumber.yml
├── docs/
│ ├── book.toml
│ └── src/
│ ├── SUMMARY.md
│ ├── activesupport-instrumentation/
│ │ └── summary.md
│ ├── aliases/
│ │ └── summary.md
│ ├── associations/
│ │ ├── association-overrides.md
│ │ ├── build-strategies.md
│ │ ├── explicit-definition.md
│ │ ├── implicit-definition.md
│ │ ├── inline-definition.md
│ │ ├── overriding-attributes.md
│ │ ├── specifying-the-factory.md
│ │ └── summary.md
│ ├── building-or-creating-multiple-records/
│ │ └── summary.md
│ ├── callbacks/
│ │ ├── callback_order.md
│ │ ├── default-callbacks.md
│ │ ├── global-callbacks.md
│ │ ├── multiple-callbacks.md
│ │ ├── summary.md
│ │ └── symbol-to_proc.md
│ ├── cookbook/
│ │ ├── has_and_belongs_to_many-associations.md
│ │ ├── has_many-associations.md
│ │ ├── interconnected-associations.md
│ │ └── polymorphic-associations.md
│ ├── custom-callbacks/
│ │ └── summary.md
│ ├── custom-construction/
│ │ └── summary.md
│ ├── custom-methods-to-persist-objects/
│ │ └── summary.md
│ ├── custom-strategies/
│ │ └── summary.md
│ ├── defining/
│ │ ├── best-practices.md
│ │ ├── explicit-class.md
│ │ ├── file-paths.md
│ │ ├── hash-attributes.md
│ │ ├── name-attributes.md
│ │ ├── static-attributes.md
│ │ └── summary.md
│ ├── dependent-attributes/
│ │ └── summary.md
│ ├── inheritance/
│ │ ├── assigning-parent-explicitly.md
│ │ ├── best-practices.md
│ │ ├── nested-factories.md
│ │ └── summary.md
│ ├── intro.md
│ ├── linting-factories/
│ │ └── summary.md
│ ├── method-name-reserved-word-attributes/
│ │ └── summary.md
│ ├── modifying-factories/
│ │ └── summary.md
│ ├── rails-preloaders-and-rspec/
│ │ └── summary.md
│ ├── ref/
│ │ ├── add_attribute.md
│ │ ├── association.md
│ │ ├── build-and-create.md
│ │ ├── build-strategies.md
│ │ ├── define.md
│ │ ├── factory.md
│ │ ├── find_definitions.md
│ │ ├── hooks.md
│ │ ├── lint.md
│ │ ├── method_missing.md
│ │ ├── modify.md
│ │ ├── register_strategy.md
│ │ ├── sequence.md
│ │ ├── trait.md
│ │ ├── traits_for_enum.md
│ │ └── transient.md
│ ├── sequences/
│ │ ├── aliases.md
│ │ ├── as-implicit-attributes.md
│ │ ├── factory-sequences.md
│ │ ├── generating.md
│ │ ├── global-sequences.md
│ │ ├── initial-value.md
│ │ ├── rewinding.md
│ │ ├── sequence-uris.md
│ │ ├── setting-the-value.md
│ │ ├── summary.md
│ │ ├── uniqueness.md
│ │ ├── with-dynamic-attributes.md
│ │ └── without-a-block.md
│ ├── setup/
│ │ └── summary.md
│ ├── traits/
│ │ ├── as-implicit-attributes.md
│ │ ├── attribute-precedence.md
│ │ ├── defining-traits.md
│ │ ├── enum.md
│ │ ├── in-child-factories.md
│ │ ├── mixins.md
│ │ ├── summary.md
│ │ ├── traits-within-traits.md
│ │ ├── using.md
│ │ ├── with-associations.md
│ │ └── with-transient-attributes.md
│ ├── transient-attributes/
│ │ ├── summary.md
│ │ ├── with-associations.md
│ │ ├── with-attributes_for.md
│ │ ├── with-callbacks.md
│ │ └── with-other-attributes.md
│ ├── using-factories/
│ │ ├── attribute-overrides.md
│ │ ├── build-strategies.md
│ │ ├── build_stubbed-and-marshaldump.md
│ │ └── summary.md
│ └── using-without-bundler/
│ └── summary.md
├── factory_bot.gemspec
├── features/
│ ├── find_definitions.feature
│ ├── step_definitions/
│ │ ├── database_steps.rb
│ │ └── factory_bot_steps.rb
│ └── support/
│ ├── env.rb
│ └── factories.rb
├── gemfiles/
│ ├── 7.0.gemfile
│ ├── 7.1.gemfile
│ ├── 7.2.gemfile
│ ├── 8.0.gemfile
│ └── main.gemfile
├── lib/
│ ├── factory_bot/
│ │ ├── aliases.rb
│ │ ├── attribute/
│ │ │ ├── association.rb
│ │ │ ├── dynamic.rb
│ │ │ └── sequence.rb
│ │ ├── attribute.rb
│ │ ├── attribute_assigner.rb
│ │ ├── attribute_list.rb
│ │ ├── callback.rb
│ │ ├── callbacks_observer.rb
│ │ ├── configuration.rb
│ │ ├── declaration/
│ │ │ ├── association.rb
│ │ │ ├── dynamic.rb
│ │ │ └── implicit.rb
│ │ ├── declaration.rb
│ │ ├── declaration_list.rb
│ │ ├── decorator/
│ │ │ ├── attribute_hash.rb
│ │ │ ├── disallows_duplicates_registry.rb
│ │ │ ├── invocation_tracker.rb
│ │ │ └── new_constructor.rb
│ │ ├── decorator.rb
│ │ ├── definition.rb
│ │ ├── definition_hierarchy.rb
│ │ ├── definition_proxy.rb
│ │ ├── enum.rb
│ │ ├── errors.rb
│ │ ├── evaluation.rb
│ │ ├── evaluator.rb
│ │ ├── evaluator_class_definer.rb
│ │ ├── factory.rb
│ │ ├── factory_runner.rb
│ │ ├── find_definitions.rb
│ │ ├── internal.rb
│ │ ├── linter.rb
│ │ ├── null_factory.rb
│ │ ├── null_object.rb
│ │ ├── registry.rb
│ │ ├── reload.rb
│ │ ├── sequence.rb
│ │ ├── strategy/
│ │ │ ├── attributes_for.rb
│ │ │ ├── build.rb
│ │ │ ├── create.rb
│ │ │ ├── null.rb
│ │ │ └── stub.rb
│ │ ├── strategy.rb
│ │ ├── strategy_syntax_method_registrar.rb
│ │ ├── syntax/
│ │ │ ├── default.rb
│ │ │ └── methods.rb
│ │ ├── syntax.rb
│ │ ├── syntax_runner.rb
│ │ ├── trait.rb
│ │ ├── uri_manager.rb
│ │ └── version.rb
│ └── factory_bot.rb
└── spec/
├── acceptance/
│ ├── activesupport_instrumentation_spec.rb
│ ├── add_attribute_spec.rb
│ ├── associations_spec.rb
│ ├── attribute_aliases_spec.rb
│ ├── attribute_existing_on_object_spec.rb
│ ├── attributes_for_destructuring.rb
│ ├── attributes_for_spec.rb
│ ├── attributes_from_instance_spec.rb
│ ├── attributes_ordered_spec.rb
│ ├── build_list_spec.rb
│ ├── build_spec.rb
│ ├── build_stubbed_spec.rb
│ ├── callbacks_spec.rb
│ ├── create_list_spec.rb
│ ├── create_pair_spec.rb
│ ├── create_spec.rb
│ ├── define_child_before_parent_spec.rb
│ ├── defining_methods_inside_a_factory_spec.rb
│ ├── definition_camel_string_spec.rb
│ ├── definition_spec.rb
│ ├── definition_without_block_spec.rb
│ ├── enum_traits_spec.rb
│ ├── global_initialize_with_spec.rb
│ ├── global_to_create_spec.rb
│ ├── initialize_with_spec.rb
│ ├── keyed_by_class_spec.rb
│ ├── lint_spec.rb
│ ├── modify_factories_spec.rb
│ ├── modify_inherited_spec.rb
│ ├── nested_attributes_spec.rb
│ ├── overrides_spec.rb
│ ├── parent_spec.rb
│ ├── private_attributes_spec.rb
│ ├── register_strategies_spec.rb
│ ├── reload_spec.rb
│ ├── sequence_context_spec.rb
│ ├── sequence_setting_spec.rb
│ ├── sequence_spec.rb
│ ├── skip_create_spec.rb
│ ├── stub_spec.rb
│ ├── syntax_methods_within_dynamic_attributes_spec.rb
│ ├── traits_spec.rb
│ └── transient_attributes_spec.rb
├── factory_bot/
│ ├── aliases_spec.rb
│ ├── attribute/
│ │ ├── association_spec.rb
│ │ ├── dynamic_spec.rb
│ │ └── sequence_spec.rb
│ ├── attribute_assignment_spec.rb
│ ├── attribute_list_spec.rb
│ ├── attribute_spec.rb
│ ├── callback_spec.rb
│ ├── declaration/
│ │ ├── association_spec.rb
│ │ ├── dynamic_spec.rb
│ │ └── implicit_spec.rb
│ ├── declaration_list_spec.rb
│ ├── decorator/
│ │ └── attribute_hash_spec.rb
│ ├── definition_proxy_spec.rb
│ ├── definition_spec.rb
│ ├── disallows_duplicates_registry_spec.rb
│ ├── evaluator_class_definer_spec.rb
│ ├── factory_spec.rb
│ ├── find_definitions_spec.rb
│ ├── internal_spec.rb
│ ├── null_factory_spec.rb
│ ├── null_object_spec.rb
│ ├── registry_spec.rb
│ ├── sequence_spec.rb
│ ├── strategy/
│ │ ├── attributes_for_spec.rb
│ │ ├── build_spec.rb
│ │ ├── create_spec.rb
│ │ └── stub_spec.rb
│ ├── strategy_spec.rb
│ └── uri_manager_spec.rb
├── factory_bot_spec.rb
├── spec_helper.rb
└── support/
├── containers/
│ └── test_log.rb
├── macros/
│ ├── define_constant.rb
│ ├── deprecation.rb
│ └── temporary_assignment.rb
├── matchers/
│ ├── be_about_now.rb
│ ├── callback.rb
│ ├── declaration.rb
│ ├── delegate.rb
│ ├── raise_did_you_mean_error.rb
│ └── trait.rb
└── shared_examples/
└── strategy.rb
SYMBOL INDEX (549 symbols across 88 files)
FILE: .github/REPRODUCTION_SCRIPT.rb
class Post (line 28) | class Post < ActiveRecord::Base
class FactoryBotTest (line 38) | class FactoryBotTest < Minitest::Test
method test_factory_bot_stuff (line 39) | def test_factory_bot_stuff
FILE: features/step_definitions/factory_bot_steps.rb
type FactoryBotDefinitionsHelper (line 1) | module FactoryBotDefinitionsHelper
function append_file_to_factory_bot_definitions_path (line 2) | def append_file_to_factory_bot_definitions_path(path_to_file)
FILE: features/support/factories.rb
class CreateSchema (line 6) | class CreateSchema < ActiveRecord::Migration[5.0]
method up (line 7) | def self.up
class Category (line 16) | class Category < ActiveRecord::Base; end
FILE: lib/factory_bot.rb
type FactoryBot (line 48) | module FactoryBot
function lint (line 67) | def self.lint(*args)
function build_stubbed_starting_id= (line 76) | def self.build_stubbed_starting_id=(starting_id)
FILE: lib/factory_bot/aliases.rb
type FactoryBot (line 1) | module FactoryBot
function aliases_for (line 11) | def self.aliases_for(attribute)
FILE: lib/factory_bot/attribute.rb
type FactoryBot (line 5) | module FactoryBot
class Attribute (line 7) | class Attribute
method initialize (line 10) | def initialize(name, ignored)
method to_proc (line 15) | def to_proc
method association? (line 19) | def association?
method alias_for? (line 23) | def alias_for?(attr)
FILE: lib/factory_bot/attribute/association.rb
type FactoryBot (line 1) | module FactoryBot
class Attribute (line 2) | class Attribute
class Association (line 4) | class Association < Attribute
method initialize (line 7) | def initialize(name, factory, overrides)
method to_proc (line 13) | def to_proc
method association? (line 22) | def association?
FILE: lib/factory_bot/attribute/dynamic.rb
type FactoryBot (line 1) | module FactoryBot
class Attribute (line 2) | class Attribute
class Dynamic (line 4) | class Dynamic < Attribute
method initialize (line 5) | def initialize(name, ignored, block)
method to_proc (line 10) | def to_proc
FILE: lib/factory_bot/attribute/sequence.rb
type FactoryBot (line 1) | module FactoryBot
class Attribute (line 2) | class Attribute
class Sequence (line 4) | class Sequence < Attribute
method initialize (line 5) | def initialize(name, sequence, ignored)
method to_proc (line 10) | def to_proc
FILE: lib/factory_bot/attribute_assigner.rb
type FactoryBot (line 1) | module FactoryBot
class AttributeAssigner (line 3) | class AttributeAssigner
method initialize (line 4) | def initialize(evaluator, build_class, &instance_builder)
method object (line 13) | def object
method hash (line 24) | def hash
method method_tracking_evaluator (line 36) | def method_tracking_evaluator
method decorated_evaluator (line 43) | def decorated_evaluator
method methods_invoked_on_evaluator (line 50) | def methods_invoked_on_evaluator
method build_class_instance (line 54) | def build_class_instance
method build_hash (line 58) | def build_hash
method get (line 62) | def get(attribute_name)
method attributes_to_set_on_instance (line 66) | def attributes_to_set_on_instance
method attributes_to_set_on_hash (line 70) | def attributes_to_set_on_hash
method attribute_names_to_assign (line 75) | def attribute_names_to_assign
method non_ignored_attribute_names (line 85) | def non_ignored_attribute_names
method ignored_attribute_names (line 89) | def ignored_attribute_names
method association_names (line 93) | def association_names
method override_names (line 97) | def override_names
method attribute_names (line 101) | def attribute_names
method hash_instance_methods_to_respond_to (line 105) | def hash_instance_methods_to_respond_to
method attribute_names_overriden_by_alias (line 110) | def attribute_names_overriden_by_alias
method ignorable_alias? (line 128) | def ignorable_alias?(attribute, override)
method override_interrupts_association? (line 152) | def override_interrupts_association?(aliased_attribute, override)
method override_matches_declared_attribute? (line 164) | def override_matches_declared_attribute?(override)
FILE: lib/factory_bot/attribute_list.rb
type FactoryBot (line 1) | module FactoryBot
class AttributeList (line 3) | class AttributeList
method initialize (line 6) | def initialize(name = nil, attributes = [])
method define_attribute (line 11) | def define_attribute(attribute)
method each (line 18) | def each(&block)
method names (line 22) | def names
method associations (line 26) | def associations
method ignored (line 30) | def ignored
method non_ignored (line 34) | def non_ignored
method apply_attributes (line 38) | def apply_attributes(attributes_to_apply)
method add_attribute (line 44) | def add_attribute(attribute)
method ensure_attribute_not_defined! (line 49) | def ensure_attribute_not_defined!(attribute)
method ensure_attribute_not_self_referencing! (line 55) | def ensure_attribute_not_self_referencing!(attribute)
method attribute_defined? (line 62) | def attribute_defined?(attribute_name)
FILE: lib/factory_bot/callback.rb
type FactoryBot (line 1) | module FactoryBot
class Callback (line 2) | class Callback
method initialize (line 5) | def initialize(name, block)
method run (line 10) | def run(instance, evaluator)
method == (line 18) | def ==(other)
method syntax_runner (line 29) | def syntax_runner
FILE: lib/factory_bot/callbacks_observer.rb
type FactoryBot (line 1) | module FactoryBot
class CallbacksObserver (line 3) | class CallbacksObserver
method initialize (line 4) | def initialize(callbacks, evaluator)
method update (line 10) | def update(name, result_instance)
method callbacks_by_name (line 21) | def callbacks_by_name(name)
method completed? (line 25) | def completed?(instance, callback)
method record_completion! (line 30) | def record_completion!(instance, callback)
method completion_key_for (line 35) | def completion_key_for(instance, callback)
FILE: lib/factory_bot/configuration.rb
type FactoryBot (line 1) | module FactoryBot
class Configuration (line 3) | class Configuration
method initialize (line 13) | def initialize
method initialize_with (line 29) | def initialize_with(&block)
FILE: lib/factory_bot/declaration.rb
type FactoryBot (line 5) | module FactoryBot
class Declaration (line 7) | class Declaration
method initialize (line 10) | def initialize(name, ignored = false)
method to_attributes (line 15) | def to_attributes
FILE: lib/factory_bot/declaration/association.rb
type FactoryBot (line 1) | module FactoryBot
class Declaration (line 2) | class Declaration
class Association (line 4) | class Association < Declaration
method initialize (line 5) | def initialize(name, *options)
method == (line 13) | def ==(other)
method build (line 27) | def build
method raise_if_arguments_are_declarations! (line 39) | def raise_if_arguments_are_declarations!
FILE: lib/factory_bot/declaration/dynamic.rb
type FactoryBot (line 1) | module FactoryBot
class Declaration (line 2) | class Declaration
class Dynamic (line 4) | class Dynamic < Declaration
method initialize (line 5) | def initialize(name, ignored = false, block = nil)
method == (line 10) | def ==(other)
method build (line 23) | def build
FILE: lib/factory_bot/declaration/implicit.rb
type FactoryBot (line 1) | module FactoryBot
class Declaration (line 2) | class Declaration
class Implicit (line 4) | class Implicit < Declaration
method initialize (line 5) | def initialize(name, factory = nil, ignored = false)
method == (line 10) | def ==(other)
method build (line 23) | def build
FILE: lib/factory_bot/declaration_list.rb
type FactoryBot (line 1) | module FactoryBot
class DeclarationList (line 3) | class DeclarationList
method initialize (line 6) | def initialize(name = nil)
method declare_attribute (line 12) | def declare_attribute(declaration)
method overridable (line 19) | def overridable
method attributes (line 23) | def attributes
method each (line 31) | def each(&block)
method delete_declaration (line 37) | def delete_declaration(declaration)
method to_attributes (line 41) | def to_attributes
method overridable? (line 45) | def overridable?
FILE: lib/factory_bot/decorator.rb
type FactoryBot (line 1) | module FactoryBot
class Decorator (line 2) | class Decorator < BasicObject
method initialize (line 5) | def initialize(component)
method method_missing (line 9) | def method_missing(...) # rubocop:disable Style/MethodMissingSuper
method send (line 13) | def send(...)
method respond_to_missing? (line 17) | def respond_to_missing?(name, include_private = false)
method const_missing (line 21) | def self.const_missing(name)
FILE: lib/factory_bot/decorator/attribute_hash.rb
type FactoryBot (line 1) | module FactoryBot
class Decorator (line 2) | class Decorator
class AttributeHash (line 3) | class AttributeHash < Decorator
method initialize (line 4) | def initialize(component, attributes = [])
method attributes (line 9) | def attributes
FILE: lib/factory_bot/decorator/disallows_duplicates_registry.rb
type FactoryBot (line 1) | module FactoryBot
class Decorator (line 2) | class Decorator
class DisallowsDuplicatesRegistry (line 3) | class DisallowsDuplicatesRegistry < Decorator
method register (line 4) | def register(name, item)
FILE: lib/factory_bot/decorator/invocation_tracker.rb
type FactoryBot (line 1) | module FactoryBot
class Decorator (line 2) | class Decorator
class InvocationTracker (line 3) | class InvocationTracker < Decorator
method initialize (line 4) | def initialize(component)
method method_missing (line 9) | def method_missing(name, *args, &block) # rubocop:disable Style/Mi...
method __invoked_methods__ (line 15) | def __invoked_methods__
FILE: lib/factory_bot/decorator/new_constructor.rb
type FactoryBot (line 1) | module FactoryBot
class Decorator (line 2) | class Decorator
class NewConstructor (line 3) | class NewConstructor < Decorator
method initialize (line 4) | def initialize(component, build_class)
FILE: lib/factory_bot/definition.rb
type FactoryBot (line 1) | module FactoryBot
class Definition (line 3) | class Definition
method initialize (line 7) | def initialize(name, base_traits = [], **opts)
method attributes (line 25) | def attributes
method to_create (line 34) | def to_create(&block)
method constructor (line 42) | def constructor
method callbacks (line 46) | def callbacks
method compile (line 50) | def compile(klass = nil)
method overridable (line 74) | def overridable
method inherit_traits (line 79) | def inherit_traits(new_traits)
method append_traits (line 83) | def append_traits(new_traits)
method add_callback (line 87) | def add_callback(callback)
method skip_create (line 91) | def skip_create
method define_trait (line 95) | def define_trait(trait)
method defined_traits_names (line 99) | def defined_traits_names
method register_enum (line 103) | def register_enum(enum)
method define_constructor (line 107) | def define_constructor(&block)
method before (line 111) | def before(*names, &block)
method after (line 115) | def after(*names, &block)
method callback (line 119) | def callback(*names, &block)
method base_traits (line 127) | def base_traits
method error_with_definition_name (line 136) | def error_with_definition_name(error)
method error_with_definition_name (line 143) | def error_with_definition_name(error)
method additional_traits (line 156) | def additional_traits
method trait_by_name (line 160) | def trait_by_name(name)
method trait_for (line 164) | def trait_for(name)
method initialize_copy (line 169) | def initialize_copy(source)
method aggregate_from_traits_and_self (line 176) | def aggregate_from_traits_and_self(method_name, &block)
method expand_enum_traits (line 186) | def expand_enum_traits(klass)
method automatically_register_defined_enums (line 201) | def automatically_register_defined_enums(klass)
method automatically_register_defined_enums? (line 205) | def automatically_register_defined_enums?(klass)
FILE: lib/factory_bot/definition_hierarchy.rb
type FactoryBot (line 1) | module FactoryBot
class DefinitionHierarchy (line 2) | class DefinitionHierarchy
method build_from_definition (line 5) | def self.build_from_definition(definition)
method add_callbacks (line 11) | def self.add_callbacks(callbacks)
method build_constructor (line 20) | def self.build_constructor(&block)
method build_to_create (line 29) | def self.build_to_create(&block)
FILE: lib/factory_bot/definition_proxy.rb
type FactoryBot (line 1) | module FactoryBot
class DefinitionProxy (line 2) | class DefinitionProxy
method initialize (line 26) | def initialize(definition, ignore = false)
method singleton_method_added (line 32) | def singleton_method_added(name)
method add_attribute (line 47) | def add_attribute(name, &block)
method transient (line 52) | def transient(&block)
method method_missing (line 91) | def method_missing(name, *args, &block) # rubocop:disable Style/Miss...
method sequence (line 122) | def sequence(name, *args, &block)
method association (line 155) | def association(name, *options)
method to_create (line 167) | def to_create(&block)
method skip_create (line 171) | def skip_create
method factory (line 175) | def factory(name, options = {}, &block)
method trait (line 179) | def trait(name, &block)
method traits_for_enum (line 237) | def traits_for_enum(attribute_name, values = nil)
method initialize_with (line 241) | def initialize_with(&block)
method __declare_attribute__ (line 247) | def __declare_attribute__(name, block)
method __valid_association_options? (line 256) | def __valid_association_options?(options)
method __fetch_or_register_sequence (line 264) | def __fetch_or_register_sequence(sequence)
FILE: lib/factory_bot/enum.rb
type FactoryBot (line 1) | module FactoryBot
class Enum (line 3) | class Enum
method initialize (line 4) | def initialize(attribute_name, values = nil)
method build_traits (line 9) | def build_traits(klass)
method enum_values (line 17) | def enum_values(klass)
method build_trait (line 21) | def build_trait(trait_name, attribute_name, value)
FILE: lib/factory_bot/errors.rb
type FactoryBot (line 1) | module FactoryBot
class AssociationDefinitionError (line 3) | class AssociationDefinitionError < RuntimeError; end
class TraitDefinitionError (line 6) | class TraitDefinitionError < RuntimeError; end
class InvalidCallbackNameError (line 9) | class InvalidCallbackNameError < RuntimeError; end
class DuplicateDefinitionError (line 12) | class DuplicateDefinitionError < RuntimeError; end
class SequenceAbuseError (line 15) | class SequenceAbuseError < RuntimeError; end
class AttributeDefinitionError (line 18) | class AttributeDefinitionError < RuntimeError; end
class AssociationDefinitionError (line 21) | class AssociationDefinitionError < RuntimeError; end
class MethodDefinitionError (line 24) | class MethodDefinitionError < RuntimeError; end
class InvalidFactoryError (line 27) | class InvalidFactoryError < RuntimeError; end
FILE: lib/factory_bot/evaluation.rb
type FactoryBot (line 1) | module FactoryBot
class Evaluation (line 2) | class Evaluation
method initialize (line 3) | def initialize(evaluator, attribute_assigner, to_create, observer)
method create (line 12) | def create(result_instance)
method notify (line 19) | def notify(name, result_instance)
FILE: lib/factory_bot/evaluator.rb
type FactoryBot (line 3) | module FactoryBot
class Evaluator (line 5) | class Evaluator
method initialize (line 12) | def initialize(build_strategy, overrides = {})
method association (line 23) | def association(factory_name, *traits_and_overrides)
method method_missing (line 37) | def method_missing(method_name, ...)
method respond_to_missing? (line 45) | def respond_to_missing?(method_name, _include_private = false)
method __override_names__ (line 49) | def __override_names__
method increment_sequence (line 53) | def increment_sequence(sequence, scope: self)
method attribute_list (line 64) | def self.attribute_list
method define_attribute (line 72) | def self.define_attribute(name, &block)
FILE: lib/factory_bot/evaluator_class_definer.rb
type FactoryBot (line 1) | module FactoryBot
class EvaluatorClassDefiner (line 3) | class EvaluatorClassDefiner
method initialize (line 4) | def initialize(attributes, parent_class)
method evaluator_class (line 13) | def evaluator_class
FILE: lib/factory_bot/factory.rb
type FactoryBot (line 4) | module FactoryBot
class Factory (line 6) | class Factory
method initialize (line 9) | def initialize(name, options = {})
method build_class (line 24) | def build_class
method run (line 34) | def run(build_strategy, overrides, &block)
method human_names (line 54) | def human_names
method associations (line 58) | def associations
method names (line 87) | def names
method compile (line 91) | def compile
method with_traits (line 101) | def with_traits(traits)
method class_name (line 109) | def class_name
method evaluator_class (line 113) | def evaluator_class
method attributes (line 117) | def attributes
method hierarchy_class (line 124) | def hierarchy_class
method hierarchy_instance (line 128) | def hierarchy_instance
method build_hierarchy (line 132) | def build_hierarchy
method callbacks (line 136) | def callbacks
method compiled_to_create (line 140) | def compiled_to_create
method compiled_constructor (line 144) | def compiled_constructor
method assert_valid_options (line 150) | def assert_valid_options(options)
method parent (line 154) | def parent
method inherit_parent_traits (line 162) | def inherit_parent_traits
method initialize_copy (line 169) | def initialize_copy(source)
FILE: lib/factory_bot/factory_runner.rb
type FactoryBot (line 1) | module FactoryBot
class FactoryRunner (line 2) | class FactoryRunner
method initialize (line 3) | def initialize(name, strategy, traits_and_overrides)
method run (line 11) | def run(runner_strategy = @strategy, &block)
FILE: lib/factory_bot/find_definitions.rb
type FactoryBot (line 1) | module FactoryBot
function find_definitions (line 12) | def self.find_definitions
FILE: lib/factory_bot/internal.rb
type FactoryBot (line 1) | module FactoryBot
type Internal (line 3) | module Internal
function configuration (line 19) | def configuration
function reset_configuration (line 23) | def reset_configuration
function register_inline_sequence (line 27) | def register_inline_sequence(sequence)
function rewind_inline_sequences (line 32) | def rewind_inline_sequences
function register_trait (line 36) | def register_trait(trait)
function trait_by_name (line 43) | def trait_by_name(name, klass)
function register_sequence (line 47) | def register_sequence(sequence)
function sequence_by_name (line 54) | def sequence_by_name(name)
function rewind_sequences (line 58) | def rewind_sequences
function rewind_sequence (line 63) | def rewind_sequence(*uri_parts)
function set_sequence (line 72) | def set_sequence(*uri_parts, value)
function register_factory (line 79) | def register_factory(factory)
function factory_by_name (line 86) | def factory_by_name(name)
function register_strategy (line 90) | def register_strategy(strategy_name, strategy_class)
function strategy_by_name (line 95) | def strategy_by_name(name)
function register_default_strategies (line 99) | def register_default_strategies
function build_uri (line 109) | def build_uri(...)
function fail_argument_count (line 113) | def fail_argument_count(received, expected)
function fail_unregistered_sequence (line 118) | def fail_unregistered_sequence(uri)
FILE: lib/factory_bot/linter.rb
type FactoryBot (line 1) | module FactoryBot
class Linter (line 2) | class Linter
method initialize (line 3) | def initialize(factories, strategy: :create, traits: false, verbose:...
method lint! (line 11) | def lint!
method calculate_invalid_factories (line 21) | def calculate_invalid_factories
class FactoryError (line 28) | class FactoryError
method initialize (line 29) | def initialize(wrapped_error, factory)
method message (line 34) | def message
method verbose_message (line 39) | def verbose_message
method location (line 46) | def location
class FactoryTraitError (line 51) | class FactoryTraitError < FactoryError
method initialize (line 52) | def initialize(wrapped_error, factory, trait_name)
method location (line 57) | def location
method lint (line 62) | def lint(factory)
method lint_factory (line 70) | def lint_factory(factory)
method lint_traits (line 80) | def lint_traits(factory)
method error_message (line 90) | def error_message
method error_message_type (line 102) | def error_message_type
method in_transaction (line 110) | def in_transaction
FILE: lib/factory_bot/null_factory.rb
type FactoryBot (line 1) | module FactoryBot
class NullFactory (line 3) | class NullFactory
method initialize (line 6) | def initialize
method compile (line 13) | def compile
method class_name (line 16) | def class_name
method evaluator_class (line 19) | def evaluator_class
method hierarchy_class (line 23) | def hierarchy_class
FILE: lib/factory_bot/null_object.rb
type FactoryBot (line 1) | module FactoryBot
class NullObject (line 3) | class NullObject < ::BasicObject
method initialize (line 4) | def initialize(methods_to_respond_to)
method method_missing (line 8) | def method_missing(name, *args, &block) # rubocop:disable Style/Miss...
method respond_to? (line 16) | def respond_to?(method)
FILE: lib/factory_bot/registry.rb
type FactoryBot (line 3) | module FactoryBot
class Registry (line 4) | class Registry
method initialize (line 9) | def initialize(name)
method clear (line 14) | def clear
method each (line 18) | def each(&block)
method find (line 22) | def find(name)
method register (line 30) | def register(name, item)
method registered? (line 34) | def registered?(name)
method key_error_with_custom_message (line 40) | def key_error_with_custom_message(key_error)
method new_key_error (line 50) | def new_key_error(message, key_error)
method new_key_error (line 54) | def new_key_error(message, _)
FILE: lib/factory_bot/reload.rb
type FactoryBot (line 1) | module FactoryBot
function reload (line 2) | def self.reload
FILE: lib/factory_bot/sequence.rb
type FactoryBot (line 3) | module FactoryBot
class Sequence (line 7) | class Sequence
method find (line 10) | def self.find(*uri_parts)
method find_by_uri (line 18) | def self.find_by_uri(uri)
method initialize (line 24) | def initialize(name, *args, &proc)
method next (line 37) | def next(scope = nil)
method names (line 49) | def names
method has_name? (line 53) | def has_name?(test_name)
method has_uri? (line 57) | def has_uri?(uri)
method for_factory? (line 61) | def for_factory?(test_factory_name)
method rewind (line 65) | def rewind
method set_value (line 73) | def set_value(new_value)
method value (line 89) | def value
method increment_value (line 93) | def increment_value
method can_set_value_by_index? (line 97) | def can_set_value_by_index?
method set_value_by_index (line 104) | def set_value_by_index(value)
method seek_value (line 114) | def seek_value(value)
method reset_original_value (line 134) | def reset_original_value(original_value)
method can_set_value_directly? (line 142) | def can_set_value_directly?(value)
method fail_value_not_found (line 148) | def fail_value_not_found(value)
class EnumeratorAdapter (line 152) | class EnumeratorAdapter
method initialize (line 153) | def initialize(initial_value)
method peek (line 157) | def peek
method next (line 161) | def next
method rewind (line 165) | def rewind
method set_value (line 169) | def set_value(new_value)
method integer_value? (line 177) | def integer_value?
method first_value (line 183) | def first_value
method value (line 187) | def value
method initial_value (line 191) | def initial_value
FILE: lib/factory_bot/strategy.rb
type FactoryBot (line 7) | module FactoryBot
type Strategy (line 8) | module Strategy
function lookup_strategy (line 9) | def self.lookup_strategy(name_or_object)
FILE: lib/factory_bot/strategy/attributes_for.rb
type FactoryBot (line 1) | module FactoryBot
type Strategy (line 2) | module Strategy
class AttributesFor (line 3) | class AttributesFor
method association (line 4) | def association(runner)
method result (line 8) | def result(evaluation)
method to_sym (line 12) | def to_sym
FILE: lib/factory_bot/strategy/build.rb
type FactoryBot (line 1) | module FactoryBot
type Strategy (line 2) | module Strategy
class Build (line 3) | class Build
method association (line 4) | def association(runner)
method result (line 8) | def result(evaluation)
method to_sym (line 16) | def to_sym
FILE: lib/factory_bot/strategy/create.rb
type FactoryBot (line 1) | module FactoryBot
type Strategy (line 2) | module Strategy
class Create (line 3) | class Create
method association (line 4) | def association(runner)
method result (line 8) | def result(evaluation)
method to_sym (line 19) | def to_sym
FILE: lib/factory_bot/strategy/null.rb
type FactoryBot (line 1) | module FactoryBot
type Strategy (line 2) | module Strategy
class Null (line 3) | class Null
method association (line 4) | def association(runner)
method result (line 7) | def result(evaluation)
method to_sym (line 10) | def to_sym
FILE: lib/factory_bot/strategy/stub.rb
type FactoryBot (line 1) | module FactoryBot
type Strategy (line 2) | module Strategy
class Stub (line 3) | class Stub
method next_id= (line 27) | def self.next_id=(id)
method association (line 31) | def association(runner)
method result (line 35) | def result(evaluation)
method to_sym (line 44) | def to_sym
method next_id (line 50) | def next_id(result_instance)
method stub_database_interaction_on_result (line 58) | def stub_database_interaction_on_result(result_instance)
method has_settable_id? (line 85) | def has_settable_id?(result_instance)
method uuid_primary_key? (line 91) | def uuid_primary_key?(result_instance)
method clear_changes_information (line 98) | def clear_changes_information(result_instance)
method set_timestamps (line 104) | def set_timestamps(result_instance)
method missing_created_at? (line 116) | def missing_created_at?(result_instance)
method missing_updated_at? (line 122) | def missing_updated_at?(result_instance)
FILE: lib/factory_bot/strategy_syntax_method_registrar.rb
type FactoryBot (line 1) | module FactoryBot
class StrategySyntaxMethodRegistrar (line 3) | class StrategySyntaxMethodRegistrar
method initialize (line 4) | def initialize(strategy_name)
method define_strategy_methods (line 8) | def define_strategy_methods
method with_index (line 14) | def self.with_index(block, index)
method define_singular_strategy_method (line 24) | def define_singular_strategy_method
method define_list_strategy_method (line 32) | def define_list_strategy_method
method define_pair_strategy_method (line 47) | def define_pair_strategy_method
method define_syntax_method (line 55) | def define_syntax_method(name, &block)
FILE: lib/factory_bot/syntax.rb
type FactoryBot (line 4) | module FactoryBot
type Syntax (line 5) | module Syntax
FILE: lib/factory_bot/syntax/default.rb
type FactoryBot (line 1) | module FactoryBot
type Syntax (line 2) | module Syntax
type Default (line 3) | module Default
function define (line 6) | def define(&block)
function modify (line 10) | def modify(&block)
class DSL (line 14) | class DSL
method factory (line 15) | def factory(name, options = {}, &block)
method sequence (line 28) | def sequence(name, ...)
method trait (line 32) | def trait(name, &block)
method run (line 36) | def self.run(block)
class ModifyDSL (line 49) | class ModifyDSL
method factory (line 50) | def factory(name, _options = {}, &block)
method run (line 56) | def self.run(block)
FILE: lib/factory_bot/syntax/methods.rb
type FactoryBot (line 1) | module FactoryBot
type Syntax (line 2) | module Syntax
type Methods (line 32) | module Methods
function generate (line 120) | def generate(*uri_parts, scope: nil)
function generate_list (line 144) | def generate_list(*uri_parts, count, scope: nil)
function increment_sequence (line 169) | def increment_sequence(sequence, scope: nil)
FILE: lib/factory_bot/syntax_runner.rb
type FactoryBot (line 1) | module FactoryBot
class SyntaxRunner (line 3) | class SyntaxRunner
FILE: lib/factory_bot/trait.rb
type FactoryBot (line 1) | module FactoryBot
class Trait (line 3) | class Trait
method initialize (line 9) | def initialize(name, **options, &block)
method clone (line 22) | def clone
method names (line 26) | def names
method == (line 30) | def ==(other)
FILE: lib/factory_bot/uri_manager.rb
type FactoryBot (line 1) | module FactoryBot
class UriManager (line 3) | class UriManager
method build_uri (line 16) | def self.build_uri(*parts)
method initialize (line 35) | def initialize(*endpoints, paths: [])
method to_a (line 47) | def to_a
method build_uri_list (line 53) | def build_uri_list
FILE: lib/factory_bot/version.rb
type FactoryBot (line 1) | module FactoryBot
FILE: spec/acceptance/activesupport_instrumentation_spec.rb
type SubscribedBehavior (line 2) | module SubscribedBehavior
function subscribed (line 3) | def subscribed(callback, *args)
FILE: spec/acceptance/attribute_existing_on_object_spec.rb
function some_funky_method (line 28) | def some_funky_method(args)
function format (line 54) | def format
FILE: spec/acceptance/attributes_for_spec.rb
function initialize (line 87) | def initialize(arg1, arg2)
FILE: spec/acceptance/attributes_from_instance_spec.rb
function age (line 4) | def age
FILE: spec/acceptance/build_stubbed_spec.rb
function created_at (line 188) | def created_at
function updated_at (line 253) | def updated_at
FILE: spec/acceptance/callbacks_spec.rb
function confirmed? (line 280) | def confirmed?
function confirm! (line 284) | def confirm!
function result (line 336) | def result(evaluation)
function result (line 346) | def result(evaluation)
function result (line 356) | def result(evaluation)
function name (line 366) | def name
function title= (line 486) | def self.title=(new_title)
function title (line 490) | def self.title
FILE: spec/acceptance/create_spec.rb
function initialize (line 62) | def initialize
function persist (line 66) | def persist
function persisted? (line 70) | def persisted?
FILE: spec/acceptance/defining_methods_inside_a_factory_spec.rb
function generate_name (line 8) | def generate_name
FILE: spec/acceptance/enum_traits_spec.rb
function define_model_with_enum (line 2) | def define_model_with_enum(class_name, field, values)
function each (line 101) | def each(&block)
FILE: spec/acceptance/global_initialize_with_spec.rb
function initialize (line 6) | def initialize(name)
function initialize (line 14) | def initialize(name)
function initialize (line 68) | def initialize(name)
FILE: spec/acceptance/initialize_with_spec.rb
function construct (line 6) | def self.construct(name, age)
function construct (line 28) | def self.construct(name)
function initialize (line 55) | def initialize(name, data)
function initialize (line 88) | def initialize(name)
function initialize (line 128) | def initialize(name)
function initialize (line 155) | def initialize(name)
function initialize (line 185) | def initialize(attributes = {})
function initialize (line 220) | def initialize(attributes:)
function initialize (line 243) | def initialize(&block)
function initialize (line 263) | def initialize(contents)
FILE: spec/acceptance/lint_spec.rb
function save! (line 174) | def save!
function save! (line 194) | def save!
function save! (line 218) | def save!
FILE: spec/acceptance/overrides_spec.rb
function secure= (line 9) | def secure=(value)
FILE: spec/acceptance/register_strategies_spec.rb
function result (line 10) | def result(evaluation)
FILE: spec/acceptance/sequence_context_spec.rb
function awesome (line 8) | def awesome
FILE: spec/acceptance/sequence_spec.rb
function initialise (line 113) | def initialise
function called? (line 117) | def called?
function call (line 121) | def call
FILE: spec/acceptance/stub_spec.rb
function using_model (line 153) | def using_model(name, primary_key:)
FILE: spec/acceptance/syntax_methods_within_dynamic_attributes_spec.rb
function generate (line 6) | def generate
FILE: spec/acceptance/traits_spec.rb
function build_user_factory_with_admin_trait (line 293) | def build_user_factory_with_admin_trait(trait_name)
function initialize (line 700) | def initialize(name)
function initialize (line 777) | def initialize(name)
FILE: spec/acceptance/transient_attributes_spec.rb
function initialize (line 99) | def initialize(id, name)
FILE: spec/factory_bot/attribute/association_spec.rb
function association (line 13) | def association(*args)
FILE: spec/factory_bot/attribute/dynamic_spec.rb
function attribute_defined_on_attribute (line 33) | def attribute_defined_on_attribute(*args)
FILE: spec/factory_bot/attribute_list_spec.rb
type AttributeList (line 1) | module AttributeList
function build_attribute_list (line 2) | def build_attribute_list(*attributes)
function build_ignored_attribute (line 97) | def build_ignored_attribute(name)
function build_non_ignored_attribute (line 101) | def build_non_ignored_attribute(name)
function build_ignored_attribute (line 127) | def build_ignored_attribute(name)
function build_non_ignored_attribute (line 131) | def build_non_ignored_attribute(name)
function build_association (line 135) | def build_association(name)
FILE: spec/factory_bot/definition_proxy_spec.rb
function build_proxy (line 79) | def build_proxy(factory_name)
FILE: spec/factory_bot/evaluator_class_definer_spec.rb
function define_evaluator (line 57) | def define_evaluator(arguments = {})
function define_evaluator_class (line 62) | def define_evaluator_class(arguments = {})
function stub_attribute (line 70) | def stub_attribute(name = :attribute, &value)
FILE: spec/factory_bot/factory_spec.rb
function to_s (line 160) | def self.to_s
function build_factory (line 302) | def build_factory
FILE: spec/factory_bot/find_definitions_spec.rb
function in_directory_with_files (line 28) | def self.in_directory_with_files(*files)
FILE: spec/support/containers/test_log.rb
type TestLog (line 6) | module TestLog
function all (line 13) | def all
function reset! (line 17) | def reset!
function log_array (line 23) | def log_array
FILE: spec/support/macros/define_constant.rb
type DefineConstantMacros (line 3) | module DefineConstantMacros
function define_class (line 4) | def define_class(path, base = Object, &block)
function define_model (line 10) | def define_model(name, columns = {}, &block)
function create_table (line 20) | def create_table(table_name, &block)
function clear_generated_tables (line 34) | def clear_generated_tables
function clear_generated_table (line 41) | def clear_generated_table(table_name)
function created_tables (line 49) | def created_tables
FILE: spec/support/macros/temporary_assignment.rb
type TemporaryAssignment (line 1) | module TemporaryAssignment
function with_temporary_assignment (line 2) | def with_temporary_assignment(assignee, attribute, temporary_value)
FILE: spec/support/matchers/declaration.rb
type DeclarationMatchers (line 1) | module DeclarationMatchers
function have_dynamic_declaration (line 2) | def have_dynamic_declaration(name)
function have_association_declaration (line 6) | def have_association_declaration(name)
function have_implicit_declaration (line 10) | def have_implicit_declaration(name)
class DeclarationMatcher (line 14) | class DeclarationMatcher
method initialize (line 15) | def initialize(declaration_type)
method matches? (line 19) | def matches?(subject)
method named (line 23) | def named(name)
method ignored (line 28) | def ignored
method with_value (line 33) | def with_value(value)
method with_factory (line 38) | def with_factory(factory)
method with_options (line 43) | def with_options(options)
method failure_message (line 48) | def failure_message
method expected_declaration (line 57) | def expected_declaration
method ignored? (line 70) | def ignored?
method options (line 74) | def options
FILE: spec/support/shared_examples/strategy.rb
function association_named (line 5) | def association_named(name, overrides)
function association_named (line 24) | def association_named(name, strategy, overrides)
function association_named (line 49) | def association_named(name, overrides)
Condensed preview — 274 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (573K chars).
[
{
"path": ".github/ISSUE_TEMPLATE/bug_report.md",
"chars": 989,
"preview": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: 'bug'\nassignees: ''\n\n---\n\n<!-- By contr"
},
{
"path": ".github/ISSUE_TEMPLATE/feature_request.md",
"chars": 675,
"preview": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: 'feature'\nassignees: ''\n\n---\n\n<!-- B"
},
{
"path": ".github/REPRODUCTION_SCRIPT.rb",
"chars": 1242,
"preview": "require \"bundler/inline\"\n\ngemfile(true) do\n source \"https://rubygems.org\"\n git_source(:github) { |repo| \"https://githu"
},
{
"path": ".github/dependabot.yml",
"chars": 302,
"preview": "---\nversion: 2\n\nupdates:\n - package-ecosystem: \"bundler\"\n directory: \"/\"\n schedule:\n interval: weekly\n "
},
{
"path": ".github/workflows/build.yml",
"chars": 1768,
"preview": "name: Build\non:\n pull_request:\n push:\n branches: [ main ]\n\njobs:\n build:\n name: Ruby ${{ matrix.ruby }} / Rails"
},
{
"path": ".github/workflows/docs.yml",
"chars": 1035,
"preview": "name: Docs\non:\n push:\n branches:\n - main\n\njobs:\n deploy:\n runs-on: ubuntu-latest\n permissions:\n con"
},
{
"path": ".github/workflows/dynamic-readme.yml",
"chars": 353,
"preview": "name: update-templates\n\non:\n push:\n branches:\n - main\n paths:\n - README.md\n workflow_dispatch:\n\njobs:\n"
},
{
"path": ".github/workflows/dynamic-security.yml",
"chars": 355,
"preview": "name: update-security\n\non:\n push:\n paths:\n - SECURITY.md\n branches:\n - main\n workflow_dispatch:\n\njobs:"
},
{
"path": ".gitignore",
"chars": 221,
"preview": ".bundle\n.rubocop-https*\n.yardoc\n.zed\n*.swp\nbin\ncoverage\ntest.db\ntmp\n\n# yard\ndoc\n\n# gem builds\nfactory_bot-*.gem\nfactory_"
},
{
"path": ".irbrc",
"chars": 368,
"preview": "def reload!\n # Undefine FactoryBot so we can reload constants and fresh code\n Object.send(:remove_const, :FactoryBot) "
},
{
"path": ".rspec",
"chars": 48,
"preview": "--format progress\n--color\n--require spec_helper\n"
},
{
"path": ".simplecov",
"chars": 66,
"preview": "SimpleCov.start do\n add_filter \"/spec/\"\n add_filter \"/tmp/\"\nend\n"
},
{
"path": ".standard.yml",
"chars": 52,
"preview": "ruby_version: \"3.0\"\nparallel: true\nformat: progress\n"
},
{
"path": ".standard_todo.yml",
"chars": 164,
"preview": "# Auto generated files with errors to ignore.\n# Remove from this list as you refactor files.\n---\nignore:\n- lib/factory_b"
},
{
"path": ".yardopts",
"chars": 65,
"preview": "lib/**/*.rb\n-\nGETTING_STARTED.md\nCONTRIBUTING.md\nNAME.md\nLICENSE\n"
},
{
"path": "Appraisals",
"chars": 1190,
"preview": "appraise \"6.1\" do\n gem \"activerecord\", \"~> 6.1.0\"\n gem \"activerecord-jdbcsqlite3-adapter\", \"~> 61.0\", platforms: [:jru"
},
{
"path": "CODEOWNERS",
"chars": 528,
"preview": "# Lines starting with '#' are comments.\n# Each line is a file pattern followed by one or more owners.\n\n# More details ar"
},
{
"path": "CODE_OF_CONDUCT.md",
"chars": 169,
"preview": "# Code of conduct\n\nBy participating in this project, you agree to abide by the\n[thoughtbot code of conduct][1].\n\n[1]: ht"
},
{
"path": "CONTRIBUTING.md",
"chars": 3176,
"preview": "# Contributing to Factory Bot\n\nWe love pull requests from everyone. By participating in this project, you\nagree to abide"
},
{
"path": "GETTING_STARTED.md",
"chars": 52075,
"preview": "**Deprecated**\n\nSee our extensive reference, guides, and cookbook in [the factory_bot book][].\n\nFor information on integ"
},
{
"path": "Gemfile",
"chars": 154,
"preview": "source \"https://rubygems.org\"\n\ngem \"activerecord-jdbcsqlite3-adapter\", platforms: [:jruby]\ngem \"sqlite3\", platforms: [:r"
},
{
"path": "LICENSE",
"chars": 1080,
"preview": "Copyright (c) 2008-2019 Joe Ferris and thoughtbot, inc.\n\nPermission is hereby granted, free of charge, to any person obt"
},
{
"path": "NAME.md",
"chars": 777,
"preview": "# Project Naming History\n\n## Factory Girl\n\nThis library was [initially released](https://robots.thoughtbot.com/waiting-f"
},
{
"path": "NEWS.md",
"chars": 26448,
"preview": "# News\n\n## 6.5.6 (October 22, 2025)\n\n* Fix: Enforce association override precedence over trait foreign keys by @JinOketa"
},
{
"path": "README.md",
"chars": 3993,
"preview": "# factory_bot \n\n[![Build Status][ci-image]][ci] [![Gem Version][version-image]][version]\n\nfactory_bot is a fixtures repl"
},
{
"path": "RELEASING.md",
"chars": 2473,
"preview": "# Releasing\n\n1. Create a release branch using the naming scheme `release-x.x.x`\n\n ```shell\n git checkout main\n git"
},
{
"path": "Rakefile",
"chars": 927,
"preview": "require \"rubygems\"\nrequire \"bundler\"\nrequire \"rake\"\nrequire \"yard\"\nrequire \"rspec/core/rake_task\"\nrequire \"cucumber/rake"
},
{
"path": "SECURITY.md",
"chars": 660,
"preview": "<!-- START /templates/security.md -->\n# Security Policy\n\n## Supported Versions\n\nOnly the the latest version of this proj"
},
{
"path": "cucumber.yml",
"chars": 46,
"preview": "default: --publish-quiet -r features features\n"
},
{
"path": "docs/book.toml",
"chars": 1488,
"preview": "[book]\nauthors = [\"Mike Burns\"]\nlanguage = \"en\"\nmultilingual = false\nsrc = \"src\"\ntitle = \"factory_bot\"\n\n[output.html.red"
},
{
"path": "docs/src/SUMMARY.md",
"chars": 4880,
"preview": "# Summary\n\n[Intro](intro.md)\n\n## Reference\n\n- [Build strategies](ref/build-strategies.md)\n- [FactoryBot.find_definitions"
},
{
"path": "docs/src/activesupport-instrumentation/summary.md",
"chars": 2060,
"preview": "# ActiveSupport Instrumentation\n\nIn order to track what factories are created (and with what build strategy),\n`ActiveSup"
},
{
"path": "docs/src/aliases/summary.md",
"chars": 966,
"preview": "# Aliases\n\nfactory\\_bot allows you to define aliases to existing factories to make them\neasier to re-use. This could com"
},
{
"path": "docs/src/associations/association-overrides.md",
"chars": 637,
"preview": "# Association overrides\n\nAttribute overrides can be used to link associated objects:\n\n```ruby\nFactoryBot.define do\n fac"
},
{
"path": "docs/src/associations/build-strategies.md",
"chars": 1638,
"preview": "# Build strategies\n\nAssociations default to using the same build strategy as their parent object:\n\n```ruby\nFactoryBot.de"
},
{
"path": "docs/src/associations/explicit-definition.md",
"chars": 211,
"preview": "# Explicit definition\n\nYou can define associations explicitly. This can be handy especially when\n[Overriding attributes]"
},
{
"path": "docs/src/associations/implicit-definition.md",
"chars": 220,
"preview": "# Implicit definition\n\nIt's possible to set up associations within factories. If the factory name is\nthe same as the ass"
},
{
"path": "docs/src/associations/inline-definition.md",
"chars": 243,
"preview": "# Inline definition\n\nYou can also define associations inline within regular attributes, but note\nthat the value will be "
},
{
"path": "docs/src/associations/overriding-attributes.md",
"chars": 459,
"preview": "# Overriding attributes\n\nYou can also override attributes on associations.\n\nImplicitly:\n\n```ruby\nfactory :post do\n # .."
},
{
"path": "docs/src/associations/specifying-the-factory.md",
"chars": 390,
"preview": "# Specifying the factory\n\nYou can specify a different factory (although [Aliases](../aliases/summary.md)\nmight also help"
},
{
"path": "docs/src/associations/summary.md",
"chars": 15,
"preview": "# Associations\n"
},
{
"path": "docs/src/building-or-creating-multiple-records/summary.md",
"chars": 1507,
"preview": "# Building or Creating Multiple Records\n\nSometimes, you'll want to create or build multiple instances of a factory at\non"
},
{
"path": "docs/src/callbacks/callback_order.md",
"chars": 3119,
"preview": "# Callback Order\n\nWhen a callback event like `after_build` or `before_all` is triggered, all callbacks for that event ar"
},
{
"path": "docs/src/callbacks/default-callbacks.md",
"chars": 1075,
"preview": "# Default callbacks\n\nfactory\\_bot makes available four callbacks for injecting some code:\n\n* before(:all) - called be"
},
{
"path": "docs/src/callbacks/global-callbacks.md",
"chars": 323,
"preview": "# Global callbacks\n\nTo override callbacks for all factories, define them within the\n`FactoryBot.define` block:\n\n```ruby\n"
},
{
"path": "docs/src/callbacks/multiple-callbacks.md",
"chars": 1045,
"preview": "# Multiple callbacks\n\nYou can also define multiple types of callbacks on the same factory:\n\n```ruby\nfactory :user do\n a"
},
{
"path": "docs/src/callbacks/summary.md",
"chars": 2042,
"preview": "# Callbacks\n\nfactory\\_bot makes six callbacks available:\n\n| Callback | Timing "
},
{
"path": "docs/src/callbacks/symbol-to_proc.md",
"chars": 345,
"preview": "# Symbol#to_proc\n\nYou can call callbacks that rely on `Symbol#to_proc`:\n\n```ruby\n# app/models/user.rb\nclass User < Activ"
},
{
"path": "docs/src/cookbook/has_and_belongs_to_many-associations.md",
"chars": 1120,
"preview": "# has_and_belongs_to_many associations\n\nGenerating data for a `has_and_belongs_to_many` relationship is very similar\nto "
},
{
"path": "docs/src/cookbook/has_many-associations.md",
"chars": 3259,
"preview": "# has_many associations\n\nThere are a few ways to generate data for a `has_many` relationship. The\nsimplest approach is t"
},
{
"path": "docs/src/cookbook/interconnected-associations.md",
"chars": 1602,
"preview": "# Interconnected associations\n\nThere are limitless ways objects might be interconnected, and\nfactory\\_bot may not always"
},
{
"path": "docs/src/cookbook/polymorphic-associations.md",
"chars": 524,
"preview": "# Polymorphic associations\n\nPolymorphic associations can be handled with traits:\n\n```ruby\nFactoryBot.define do\n factory"
},
{
"path": "docs/src/custom-callbacks/summary.md",
"chars": 847,
"preview": "# Custom Callbacks\n\nCustom callbacks can be defined if you're using custom strategies:\n\n```ruby\nclass JsonStrategy\n def"
},
{
"path": "docs/src/custom-construction/summary.md",
"chars": 2844,
"preview": "# Custom Construction\n\nIf you want to use factory\\_bot to construct an object where some attributes\nare passed to `initi"
},
{
"path": "docs/src/custom-methods-to-persist-objects/summary.md",
"chars": 691,
"preview": "# Custom Methods to Persist Objects\n\nBy default, creating a record will call `save!` on the instance; since this may\nnot"
},
{
"path": "docs/src/custom-strategies/summary.md",
"chars": 1481,
"preview": "# Custom Strategies\n\nThere are times where you may want to extend behavior of factory\\_bot by adding\na custom build stra"
},
{
"path": "docs/src/defining/best-practices.md",
"chars": 504,
"preview": "# Best practices\n\nIt is recommended that you have one factory for each class that provides\nthe simplest set of attribute"
},
{
"path": "docs/src/defining/explicit-class.md",
"chars": 465,
"preview": "# Specifying the class explicitly\n\nIt is also possible to explicitly specify the class:\n\n```ruby\n# This will use the Use"
},
{
"path": "docs/src/defining/file-paths.md",
"chars": 337,
"preview": "# Definition file paths\n\nFactories can be defined anywhere, but will be automatically loaded after\ncalling `FactoryBot.f"
},
{
"path": "docs/src/defining/hash-attributes.md",
"chars": 930,
"preview": "# Hash attributes\n\nBecause of the block syntax in Ruby, defining attributes as `Hash`es (for\nserialized/JSON columns, fo"
},
{
"path": "docs/src/defining/name-attributes.md",
"chars": 309,
"preview": "# Factory name and attributes\n\nEach factory has a name and a set of attributes. The name is used to guess the\nclass of t"
},
{
"path": "docs/src/defining/static-attributes.md",
"chars": 254,
"preview": "# Static Attributes\n\nStatic attributes (without a block) are no longer available in factory\\_bot 5.\nYou can read more ab"
},
{
"path": "docs/src/defining/summary.md",
"chars": 21,
"preview": "# Defining factories\n"
},
{
"path": "docs/src/dependent-attributes/summary.md",
"chars": 354,
"preview": "# Dependent Attributes\n\nAttributes can be based on the values of other attributes using the context\nthat is yielded to d"
},
{
"path": "docs/src/inheritance/assigning-parent-explicitly.md",
"chars": 196,
"preview": "# Assigning parent explicitly\n\nYou can also assign the parent explicitly:\n\n```ruby\nfactory :post do\n title { \"A title\" "
},
{
"path": "docs/src/inheritance/best-practices.md",
"chars": 220,
"preview": "# Best practices\n\nAs mentioned above, it's good practice to define a basic factory for each class\nwith only the attribut"
},
{
"path": "docs/src/inheritance/nested-factories.md",
"chars": 355,
"preview": "# Nested factories\n\nYou can create multiple factories for the same class without repeating common\nattributes by nesting "
},
{
"path": "docs/src/inheritance/summary.md",
"chars": 14,
"preview": "# Inheritance\n"
},
{
"path": "docs/src/intro.md",
"chars": 1416,
"preview": "# Intro\n\nfactory_bot is a fixtures replacement with a straightforward definition syntax,\nsupport for multiple build stra"
},
{
"path": "docs/src/linting-factories/summary.md",
"chars": 2113,
"preview": "# Linting Factories\n\nfactory\\_bot allows for linting known factories:\n\n```ruby\nFactoryBot.lint\n```\n\n`FactoryBot.lint` cr"
},
{
"path": "docs/src/method-name-reserved-word-attributes/summary.md",
"chars": 423,
"preview": "# Method Name / Reserved Word Attributes\n\nIf your attributes conflict with existing methods or reserved words (all\nmetho"
},
{
"path": "docs/src/modifying-factories/summary.md",
"chars": 1385,
"preview": "# Modifying factories\n\nIf you're given a set of factories (say, from a gem developer) but want to\nchange them to fit int"
},
{
"path": "docs/src/rails-preloaders-and-rspec/summary.md",
"chars": 963,
"preview": "# Rails Preloaders and RSpec\n\nWhen running RSpec with a Rails preloader such as `spring` or `zeus`, it's\npossible to enc"
},
{
"path": "docs/src/ref/add_attribute.md",
"chars": 701,
"preview": "# add_attribute\n\nWithin a factory definition, the `add_attribute` method defines a key/value\npair that will be set when "
},
{
"path": "docs/src/ref/association.md",
"chars": 623,
"preview": "# association\n\nWithin a factory block, use the `association` method to always make an\nadditional object alongside this o"
},
{
"path": "docs/src/ref/build-and-create.md",
"chars": 1220,
"preview": "# skip_create, to_create, and initialize_with\n\nThe `skip_create`, `to_create`, and `initialize_with` methods control how"
},
{
"path": "docs/src/ref/build-strategies.md",
"chars": 3593,
"preview": "# Build strategies\n\nOnce a factory\\_bot factory is defined, it can be constructed using any of the\nbuilt-in build strate"
},
{
"path": "docs/src/ref/define.md",
"chars": 257,
"preview": "# FactoryBot.define\n\nEach file loaded by factory\\_bot is expected to call `FactoryBot.define` with a\nblock. The block is"
},
{
"path": "docs/src/ref/factory.md",
"chars": 1606,
"preview": "# factory\n\nWithin a `FactoryBot.define` block, you can define factories. Anything defined\nusing `factory` can be built u"
},
{
"path": "docs/src/ref/find_definitions.md",
"chars": 652,
"preview": "# FactoryBot.find_definitions\n\nThe `FactoryBot.find_definitions` method loads in all factory\\_bot definitions\nacross the"
},
{
"path": "docs/src/ref/hooks.md",
"chars": 1463,
"preview": "# Hooks\n\nWithin a `factory` definition block and the `FactoryBot.define` block, you have\naccess to the `after`, `before`"
},
{
"path": "docs/src/ref/lint.md",
"chars": 669,
"preview": "# FactoryBot.lint\n\nThe `FactoryBot.lint` method tries each factory and raises\n`FactoryBot::InvalidFactoryError` on failu"
},
{
"path": "docs/src/ref/method_missing.md",
"chars": 2003,
"preview": "# method_missing\n\nWith a `factory` definition block, you can use `add_attribute`, `association`,\n`sequence`, and `trait`"
},
{
"path": "docs/src/ref/modify.md",
"chars": 579,
"preview": "# FactoryBot.modify\n\nThe `FactoryBot.modify` class method defines a block with an _overriding_\n`factory` method availabl"
},
{
"path": "docs/src/ref/register_strategy.md",
"chars": 765,
"preview": "# FactoryBot.register_strategy\n\nThe `FactoryBot.register_strategy` method is how to add a [build\nstrategy](build-strateg"
},
{
"path": "docs/src/ref/sequence.md",
"chars": 1505,
"preview": "# sequence\n\nA factory\\_bot set up supports two levels of sequences: global and factory-specific.\n\n## Global sequences\n\nW"
},
{
"path": "docs/src/ref/trait.md",
"chars": 317,
"preview": "# trait\n\nWithin a `factory` definition block, use the `trait` method to define named permutations of the factory.\n\nThe t"
},
{
"path": "docs/src/ref/traits_for_enum.md",
"chars": 1752,
"preview": "# traits_for_enum\n\nWith a `factory` definition block, the `traits_for_enum` method is a helper for\nany object with an at"
},
{
"path": "docs/src/ref/transient.md",
"chars": 487,
"preview": "# transient\n\nWithin a `factory` definition block, the goal is to construct an instance of\nthe class. While factory\\_bot "
},
{
"path": "docs/src/sequences/aliases.md",
"chars": 726,
"preview": "# Aliases\n\nSequences can also have aliases. The sequence aliases share the same counter:\n\n```ruby\nfactory :user do\n seq"
},
{
"path": "docs/src/sequences/as-implicit-attributes.md",
"chars": 345,
"preview": "# As implicit attributes\n\nOr as implicit attributes:\n\n```ruby\nFactoryBot.define do\n sequence :email do |n|\n \"person#"
},
{
"path": "docs/src/sequences/factory-sequences.md",
"chars": 483,
"preview": "# Factory sequences\n\nAnd it's also possible to define a sequence that is only used in\na particular factory:\n\n```ruby\nfac"
},
{
"path": "docs/src/sequences/generating.md",
"chars": 2004,
"preview": "# Generating a Sequence\n\nBeing able to directly generate a sequence, without having to build the object can really speed"
},
{
"path": "docs/src/sequences/global-sequences.md",
"chars": 461,
"preview": "# Global sequences\n\nUnique values in a specific format (for example, e-mail addresses) can be\ngenerated using sequences."
},
{
"path": "docs/src/sequences/initial-value.md",
"chars": 489,
"preview": "# Initial value\n\nYou can override the initial value. Any value that responds to the `#next`\nmethod will work (e.g. 1, 2,"
},
{
"path": "docs/src/sequences/rewinding.md",
"chars": 1225,
"preview": "# Rewinding\n\nSequences can also be rewound to their starting value:\n\n## All sequences\n\nRewind all global and factory seq"
},
{
"path": "docs/src/sequences/sequence-uris.md",
"chars": 3174,
"preview": "# Sequence URIs\n\nThere are many reasons to manipulate a specific sequence:\n\n- generating a single value with: `generate`"
},
{
"path": "docs/src/sequences/setting-the-value.md",
"chars": 1624,
"preview": "# Setting the value\n\nWhen testing or working in the console, being able to set the sequence to a specific value, is incr"
},
{
"path": "docs/src/sequences/summary.md",
"chars": 12,
"preview": "# Sequences\n"
},
{
"path": "docs/src/sequences/uniqueness.md",
"chars": 425,
"preview": "# Uniqueness\n\nWhen working with uniqueness constraints, be careful not to pass in override\nvalues that will conflict wit"
},
{
"path": "docs/src/sequences/with-dynamic-attributes.md",
"chars": 225,
"preview": "# With dynamic attributes\n\nSequences can be used in dynamic attributes:\n\n```ruby\nFactoryBot.define do\n sequence :email "
},
{
"path": "docs/src/sequences/without-a-block.md",
"chars": 352,
"preview": "# Without a block\n\nWithout a block, the value will increment itself, starting at its initial value:\n\n```ruby\nfactory :po"
},
{
"path": "docs/src/setup/summary.md",
"chars": 876,
"preview": "# Setup\n\nInstallation varies based on the framework you are using, if any, and\noptionally the test framework.\n\nSince ins"
},
{
"path": "docs/src/traits/as-implicit-attributes.md",
"chars": 374,
"preview": "# As implicit attributes\n\nTraits can be used as implicit attributes:\n\n```ruby\nfactory :week_long_published_story_with_ti"
},
{
"path": "docs/src/traits/attribute-precedence.md",
"chars": 713,
"preview": "# Attribute precedence\n\nTraits that define the same attributes won't raise AttributeDefinitionErrors;\nthe trait that def"
},
{
"path": "docs/src/traits/defining-traits.md",
"chars": 851,
"preview": "# Defining traits\n\nTraits allow you to group attributes together and then apply them\nto any factory.\n\n```ruby\nfactory :u"
},
{
"path": "docs/src/traits/enum.md",
"chars": 1652,
"preview": "# Enum traits\n\nGiven an Active Record model with an enum attribute:\n\n```rb\nclass Task < ActiveRecord::Base\n enum status"
},
{
"path": "docs/src/traits/in-child-factories.md",
"chars": 342,
"preview": "# In child factories\n\nYou can override individual attributes granted by a trait in a child factory:\n\n```ruby\nfactory :us"
},
{
"path": "docs/src/traits/mixins.md",
"chars": 382,
"preview": "# As mixins\n\nTraits can be defined outside of factories and used as mixins to compose shared\nattributes:\n\n```ruby\nFactor"
},
{
"path": "docs/src/traits/summary.md",
"chars": 842,
"preview": "# Traits\n\nTraits allow you to group attributes together and then apply them\nto any factory.\n\n```ruby\nfactory :user, alia"
},
{
"path": "docs/src/traits/traits-within-traits.md",
"chars": 258,
"preview": "# Traits within traits\n\nTraits can be used within other traits to mix in their attributes.\n\n```ruby\nfactory :order do\n "
},
{
"path": "docs/src/traits/using.md",
"chars": 1015,
"preview": "# Using traits\n\nTraits can also be passed in as a list of Symbols when you construct an instance\nfrom factory\\_bot.\n\n```"
},
{
"path": "docs/src/traits/with-associations.md",
"chars": 713,
"preview": "# With associations\n\nTraits can be used with associations easily too:\n\n```ruby\nfactory :user do\n name { \"Friendly User\""
},
{
"path": "docs/src/traits/with-transient-attributes.md",
"chars": 338,
"preview": "# With transient attributes\n\nTraits can accept transient attributes.\n\n```ruby\nfactory :invoice do\n trait :with_amount d"
},
{
"path": "docs/src/transient-attributes/summary.md",
"chars": 409,
"preview": "# Transient Attributes\n\nTransient attributes are attributes only available within the factory\ndefinition, and not set on"
},
{
"path": "docs/src/transient-attributes/with-associations.md",
"chars": 400,
"preview": "# With associations\n\nTransient [associations](../associations/summary.md) are not supported in\nfactory\\_bot. Association"
},
{
"path": "docs/src/transient-attributes/with-attributes_for.md",
"chars": 175,
"preview": "# With attributes_for\n\nTransient attributes will be ignored within `attributes_for` and won't be set\non the model, even "
},
{
"path": "docs/src/transient-attributes/with-callbacks.md",
"chars": 525,
"preview": "# With callbacks\n\nIf you need to access the evaluated definition itself in a factory\\_bot callback, you'll\nneed to decla"
},
{
"path": "docs/src/transient-attributes/with-other-attributes.md",
"chars": 377,
"preview": "# With other attributes\n\nYou can access transient attributes within other attributes (see [Dependent\nAttributes](../depe"
},
{
"path": "docs/src/using-factories/attribute-overrides.md",
"chars": 690,
"preview": "# Attribute overrides\n\nNo matter which strategy is used, it's possible to override the defined\nattributes by passing a h"
},
{
"path": "docs/src/using-factories/build-strategies.md",
"chars": 926,
"preview": "# Build strategies\n\nfactory\\_bot supports several different build strategies: `build`, `create`,\n`attributes_for` and `b"
},
{
"path": "docs/src/using-factories/build_stubbed-and-marshaldump.md",
"chars": 186,
"preview": "# build_stubbed and Marshal.dump\n\nNote that objects created with `build_stubbed` cannot be serialized with\n`Marshal.dump"
},
{
"path": "docs/src/using-factories/summary.md",
"chars": 18,
"preview": "# Using factories\n"
},
{
"path": "docs/src/using-without-bundler/summary.md",
"chars": 813,
"preview": "# Using Without Bundler\n\nIf you're not using Bundler, be sure to have the gem installed and call:\n\n```ruby\nrequire 'fact"
},
{
"path": "factory_bot.gemspec",
"chars": 1553,
"preview": "$LOAD_PATH << File.expand_path(\"lib\", __dir__)\nrequire \"factory_bot/version\"\n\nGem::Specification.new do |s|\n s.name = \""
},
{
"path": "features/find_definitions.feature",
"chars": 2265,
"preview": "Feature: FactoryBot can find factory definitions correctly\n Scenario: Find definitions with a path\n Given a file nam"
},
{
"path": "features/step_definitions/database_steps.rb",
"chars": 220,
"preview": "Then(/^I should find the following for the last category:$/) do |table|\n table.hashes.first.each do |key, value|\n ex"
},
{
"path": "features/step_definitions/factory_bot_steps.rb",
"chars": 1033,
"preview": "module FactoryBotDefinitionsHelper\n def append_file_to_factory_bot_definitions_path(path_to_file)\n FactoryBot.defini"
},
{
"path": "features/support/env.rb",
"chars": 236,
"preview": "PROJECT_ROOT = File.expand_path(File.join(File.dirname(__FILE__), \"..\", \"..\"))\n\nrequire \"simplecov\" if RUBY_ENGINE == \"r"
},
{
"path": "features/support/factories.rb",
"chars": 345,
"preview": "ActiveRecord::Base.establish_connection(\n adapter: \"sqlite3\",\n database: \":memory:\"\n)\n\nclass CreateSchema < ActiveReco"
},
{
"path": "gemfiles/7.0.gemfile",
"chars": 292,
"preview": "# This file was generated by Appraisal\n\nsource \"https://rubygems.org\"\n\ngem \"activerecord-jdbcsqlite3-adapter\", \"~> 70.0\""
},
{
"path": "gemfiles/7.1.gemfile",
"chars": 248,
"preview": "# This file was generated by Appraisal\n\nsource \"https://rubygems.org\"\n\ngem \"activerecord-jdbcsqlite3-adapter\", platforms"
},
{
"path": "gemfiles/7.2.gemfile",
"chars": 238,
"preview": "# This file was generated by Appraisal\n\nsource \"https://rubygems.org\"\n\ngem \"activerecord-jdbcsqlite3-adapter\", platforms"
},
{
"path": "gemfiles/8.0.gemfile",
"chars": 247,
"preview": "# This file was generated by Appraisal\n\nsource \"https://rubygems.org\"\n\ngem \"activerecord-jdbcsqlite3-adapter\", \"~> 70.0\""
},
{
"path": "gemfiles/main.gemfile",
"chars": 296,
"preview": "# This file was generated by Appraisal\n\nsource \"https://rubygems.org\"\n\ngem \"activerecord-jdbcsqlite3-adapter\", \"~> 70.0\""
},
{
"path": "lib/factory_bot/aliases.rb",
"chars": 344,
"preview": "module FactoryBot\n class << self\n attr_accessor :aliases\n end\n\n self.aliases = [\n [/(.+)_id/, '\\1'],\n [/(.*)"
},
{
"path": "lib/factory_bot/attribute/association.rb",
"chars": 586,
"preview": "module FactoryBot\n class Attribute\n # @api private\n class Association < Attribute\n attr_reader :factory\n\n "
},
{
"path": "lib/factory_bot/attribute/dynamic.rb",
"chars": 514,
"preview": "module FactoryBot\n class Attribute\n # @api private\n class Dynamic < Attribute\n def initialize(name, ignored,"
},
{
"path": "lib/factory_bot/attribute/sequence.rb",
"chars": 321,
"preview": "module FactoryBot\n class Attribute\n # @api private\n class Sequence < Attribute\n def initialize(name, sequenc"
},
{
"path": "lib/factory_bot/attribute.rb",
"chars": 478,
"preview": "require \"factory_bot/attribute/dynamic\"\nrequire \"factory_bot/attribute/association\"\nrequire \"factory_bot/attribute/seque"
},
{
"path": "lib/factory_bot/attribute_assigner.rb",
"chars": 6017,
"preview": "module FactoryBot\n # @api private\n class AttributeAssigner\n def initialize(evaluator, build_class, &instance_builde"
},
{
"path": "lib/factory_bot/attribute_list.rb",
"chars": 1577,
"preview": "module FactoryBot\n # @api private\n class AttributeList\n include Enumerable\n\n def initialize(name = nil, attribut"
},
{
"path": "lib/factory_bot/callback.rb",
"chars": 633,
"preview": "module FactoryBot\n class Callback\n attr_reader :name\n\n def initialize(name, block)\n @name = name.to_sym\n "
},
{
"path": "lib/factory_bot/callbacks_observer.rb",
"chars": 960,
"preview": "module FactoryBot\n # @api private\n class CallbacksObserver\n def initialize(callbacks, evaluator)\n @callbacks ="
},
{
"path": "lib/factory_bot/configuration.rb",
"chars": 908,
"preview": "module FactoryBot\n # @api private\n class Configuration\n attr_reader(\n :callback_names,\n :factories,\n "
},
{
"path": "lib/factory_bot/declaration/association.rb",
"chars": 1429,
"preview": "module FactoryBot\n class Declaration\n # @api private\n class Association < Declaration\n def initialize(name, "
},
{
"path": "lib/factory_bot/declaration/dynamic.rb",
"chars": 537,
"preview": "module FactoryBot\n class Declaration\n # @api private\n class Dynamic < Declaration\n def initialize(name, igno"
},
{
"path": "lib/factory_bot/declaration/implicit.rb",
"chars": 947,
"preview": "module FactoryBot\n class Declaration\n # @api private\n class Implicit < Declaration\n def initialize(name, fac"
},
{
"path": "lib/factory_bot/declaration.rb",
"chars": 398,
"preview": "require \"factory_bot/declaration/dynamic\"\nrequire \"factory_bot/declaration/association\"\nrequire \"factory_bot/declaration"
},
{
"path": "lib/factory_bot/declaration_list.rb",
"chars": 978,
"preview": "module FactoryBot\n # @api private\n class DeclarationList\n include Enumerable\n\n def initialize(name = nil)\n "
},
{
"path": "lib/factory_bot/decorator/attribute_hash.rb",
"chars": 387,
"preview": "module FactoryBot\n class Decorator\n class AttributeHash < Decorator\n def initialize(component, attributes = [])"
},
{
"path": "lib/factory_bot/decorator/disallows_duplicates_registry.rb",
"chars": 332,
"preview": "module FactoryBot\n class Decorator\n class DisallowsDuplicatesRegistry < Decorator\n def register(name, item)\n "
},
{
"path": "lib/factory_bot/decorator/invocation_tracker.rb",
"chars": 478,
"preview": "module FactoryBot\n class Decorator\n class InvocationTracker < Decorator\n def initialize(component)\n supe"
},
{
"path": "lib/factory_bot/decorator/new_constructor.rb",
"chars": 246,
"preview": "module FactoryBot\n class Decorator\n class NewConstructor < Decorator\n def initialize(component, build_class)\n "
},
{
"path": "lib/factory_bot/decorator.rb",
"chars": 494,
"preview": "module FactoryBot\n class Decorator < BasicObject\n undef_method :==\n\n def initialize(component)\n @component ="
},
{
"path": "lib/factory_bot/definition.rb",
"chars": 5421,
"preview": "module FactoryBot\n # @api private\n class Definition\n attr_reader :defined_traits, :declarations, :name, :registered"
},
{
"path": "lib/factory_bot/definition_hierarchy.rb",
"chars": 872,
"preview": "module FactoryBot\n class DefinitionHierarchy\n delegate :callbacks, :constructor, :to_create, to: Internal\n\n def s"
},
{
"path": "lib/factory_bot/definition_proxy.rb",
"chars": 7567,
"preview": "module FactoryBot\n class DefinitionProxy\n UNPROXIED_METHODS = %w[\n __send__\n __id__\n nil?\n send\n"
},
{
"path": "lib/factory_bot/enum.rb",
"chars": 608,
"preview": "module FactoryBot\n # @api private\n class Enum\n def initialize(attribute_name, values = nil)\n @attribute_name ="
},
{
"path": "lib/factory_bot/errors.rb",
"chars": 1118,
"preview": "module FactoryBot\n # Raised when a factory is defined that attempts to instantiate itself.\n class AssociationDefinitio"
},
{
"path": "lib/factory_bot/evaluation.rb",
"chars": 582,
"preview": "module FactoryBot\n class Evaluation\n def initialize(evaluator, attribute_assigner, to_create, observer)\n @evalu"
},
{
"path": "lib/factory_bot/evaluator.rb",
"chars": 2454,
"preview": "require \"active_support/core_ext/class/attribute\"\n\nmodule FactoryBot\n # @api private\n class Evaluator\n class_attrib"
},
{
"path": "lib/factory_bot/evaluator_class_definer.rb",
"chars": 513,
"preview": "module FactoryBot\n # @api private\n class EvaluatorClassDefiner\n def initialize(attributes, parent_class)\n @par"
},
{
"path": "lib/factory_bot/factory.rb",
"chars": 4403,
"preview": "require \"active_support/core_ext/hash/keys\"\nrequire \"active_support/inflector\"\n\nmodule FactoryBot\n # @api private\n cla"
},
{
"path": "lib/factory_bot/factory_runner.rb",
"chars": 826,
"preview": "module FactoryBot\n class FactoryRunner\n def initialize(name, strategy, traits_and_overrides)\n @name = name\n "
},
{
"path": "lib/factory_bot/find_definitions.rb",
"chars": 840,
"preview": "module FactoryBot\n class << self\n # An Array of strings specifying locations that should be searched for\n # facto"
},
{
"path": "lib/factory_bot/internal.rb",
"chars": 3079,
"preview": "module FactoryBot\n # @api private\n module Internal\n class << self\n delegate :after,\n :before,\n :"
},
{
"path": "lib/factory_bot/linter.rb",
"chars": 2823,
"preview": "module FactoryBot\n class Linter\n def initialize(factories, strategy: :create, traits: false, verbose: false)\n @"
},
{
"path": "lib/factory_bot/null_factory.rb",
"chars": 460,
"preview": "module FactoryBot\n # @api private\n class NullFactory\n attr_reader :definition\n\n def initialize\n @definition"
},
{
"path": "lib/factory_bot/null_object.rb",
"chars": 457,
"preview": "module FactoryBot\n # @api private\n class NullObject < ::BasicObject\n def initialize(methods_to_respond_to)\n @m"
},
{
"path": "lib/factory_bot/registry.rb",
"chars": 1329,
"preview": "require \"active_support/hash_with_indifferent_access\"\n\nmodule FactoryBot\n class Registry\n include Enumerable\n\n at"
},
{
"path": "lib/factory_bot/reload.rb",
"chars": 141,
"preview": "module FactoryBot\n def self.reload\n Internal.reset_configuration\n Internal.register_default_strategies\n find_d"
},
{
"path": "lib/factory_bot/sequence.rb",
"chars": 4546,
"preview": "require \"timeout\"\n\nmodule FactoryBot\n # Sequences are defined using sequence within a FactoryBot.define block.\n # Sequ"
},
{
"path": "lib/factory_bot/strategy/attributes_for.rb",
"chars": 260,
"preview": "module FactoryBot\n module Strategy\n class AttributesFor\n def association(runner)\n runner.run(:null)\n "
},
{
"path": "lib/factory_bot/strategy/build.rb",
"chars": 367,
"preview": "module FactoryBot\n module Strategy\n class Build\n def association(runner)\n runner.run\n end\n\n de"
},
{
"path": "lib/factory_bot/strategy/create.rb",
"chars": 514,
"preview": "module FactoryBot\n module Strategy\n class Create\n def association(runner)\n runner.run\n end\n\n d"
},
{
"path": "lib/factory_bot/strategy/null.rb",
"chars": 191,
"preview": "module FactoryBot\n module Strategy\n class Null\n def association(runner)\n end\n\n def result(evaluation)"
},
{
"path": "lib/factory_bot/strategy/stub.rb",
"chars": 3304,
"preview": "module FactoryBot\n module Strategy\n class Stub\n @@next_id = 1000\n\n DISABLED_PERSISTENCE_METHODS = [\n "
},
{
"path": "lib/factory_bot/strategy.rb",
"chars": 413,
"preview": "require \"factory_bot/strategy/build\"\nrequire \"factory_bot/strategy/create\"\nrequire \"factory_bot/strategy/attributes_for\""
},
{
"path": "lib/factory_bot/strategy_syntax_method_registrar.rb",
"chars": 1793,
"preview": "module FactoryBot\n # @api private\n class StrategySyntaxMethodRegistrar\n def initialize(strategy_name)\n @strate"
},
{
"path": "lib/factory_bot/syntax/default.rb",
"chars": 1601,
"preview": "module FactoryBot\n module Syntax\n module Default\n include Methods\n\n def define(&block)\n DSL.run(blo"
},
{
"path": "lib/factory_bot/syntax/methods.rb",
"chars": 7238,
"preview": "module FactoryBot\n module Syntax\n ## This module is a container for all strategy methods provided by\n ## FactoryB"
},
{
"path": "lib/factory_bot/syntax.rb",
"chars": 119,
"preview": "require \"factory_bot/syntax/methods\"\nrequire \"factory_bot/syntax/default\"\n\nmodule FactoryBot\n module Syntax\n end\nend\n"
},
{
"path": "lib/factory_bot/syntax_runner.rb",
"chars": 94,
"preview": "module FactoryBot\n # @api private\n class SyntaxRunner\n include Syntax::Methods\n end\nend\n"
},
{
"path": "lib/factory_bot/trait.rb",
"chars": 882,
"preview": "module FactoryBot\n # @api private\n class Trait\n attr_reader :name, :uid, :definition\n\n delegate :add_callback, :"
},
{
"path": "lib/factory_bot/uri_manager.rb",
"chars": 1483,
"preview": "module FactoryBot\n # @api private\n class UriManager\n attr_reader :endpoints, :paths, :uri_list\n\n delegate :size,"
},
{
"path": "lib/factory_bot/version.rb",
"chars": 49,
"preview": "module FactoryBot\n VERSION = \"6.5.6\".freeze\nend\n"
},
{
"path": "lib/factory_bot.rb",
"chars": 4244,
"preview": "require \"set\"\nrequire \"active_support\"\nrequire \"active_support/core_ext/module/delegation\"\nrequire \"active_support/core_"
},
{
"path": "spec/acceptance/activesupport_instrumentation_spec.rb",
"chars": 6540,
"preview": "unless ActiveSupport::Notifications.respond_to?(:subscribed)\n module SubscribedBehavior\n def subscribed(callback, *a"
},
{
"path": "spec/acceptance/add_attribute_spec.rb",
"chars": 1022,
"preview": "describe \"#add_attribute\" do\n it \"assigns attributes for reserved words on .build\" do\n define_model(\"Post\", title: :"
},
{
"path": "spec/acceptance/associations_spec.rb",
"chars": 4068,
"preview": "describe \"associations\" do\n context \"when accidentally using an implicit declaration for the factory\" do\n it \"raises"
},
{
"path": "spec/acceptance/attribute_aliases_spec.rb",
"chars": 13603,
"preview": "describe \"attribute aliases\" do\n around do |example|\n original_aliases = FactoryBot.aliases.dup\n example.run\n en"
},
{
"path": "spec/acceptance/attribute_existing_on_object_spec.rb",
"chars": 1757,
"preview": "describe \"declaring attributes on a Factory that are private methods on Object\" do\n before do\n define_model(\"Website"
},
{
"path": "spec/acceptance/attributes_for_destructuring.rb",
"chars": 625,
"preview": "describe \"Ruby 3.0: attributes_for destructuring syntax\" do\n include FactoryBot::Syntax::Methods\n\n before do\n defin"
},
{
"path": "spec/acceptance/attributes_for_spec.rb",
"chars": 2229,
"preview": "if RUBY_ENGINE != \"truffleruby\"\n require_relative \"attributes_for_destructuring\"\nend\n\ndescribe \"a generated attributes "
},
{
"path": "spec/acceptance/attributes_from_instance_spec.rb",
"chars": 1443,
"preview": "describe \"calling methods on the model instance\" do\n before do\n define_model(\"User\", age: :integer, age_copy: :integ"
},
{
"path": "spec/acceptance/attributes_ordered_spec.rb",
"chars": 1390,
"preview": "describe \"a generated attributes hash where order matters\" do\n include FactoryBot::Syntax::Methods\n\n before do\n def"
},
{
"path": "spec/acceptance/build_list_spec.rb",
"chars": 1702,
"preview": "describe \"build multiple instances\" do\n before do\n define_model(\"Post\", title: :string, position: :integer)\n\n Fac"
},
{
"path": "spec/acceptance/build_spec.rb",
"chars": 2086,
"preview": "describe \"a built instance\" do\n include FactoryBot::Syntax::Methods\n\n before do\n define_model(\"User\")\n\n define_m"
},
{
"path": "spec/acceptance/build_stubbed_spec.rb",
"chars": 7470,
"preview": "describe \"a generated stub instance\" do\n include FactoryBot::Syntax::Methods\n\n before do\n define_model(\"User\")\n\n "
}
]
// ... and 74 more files (download for full content)
About this extraction
This page contains the full source code of the thoughtbot/factory_bot GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 274 files (517.8 KB), approximately 139.3k tokens, and a symbol index with 549 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.