rigor-factorybot
Validates every FactoryBot.create(:name, key: …) / .build(…) /
.build_stubbed(…) / .attributes_for(…) / *_list call against
an index of your factory definitions: an unknown factory name or an
attribute key the factory doesn’t declare is flagged (each with a
did-you-mean). When rigor-activerecord is
also active, attribute keys are additionally cross-checked against
the model’s columns. No FactoryBot runtime dependency.
It ships bundled in rigortype. Activate it under plugins::
plugins: - rigor-factorybot # - rigor-activerecord # optional: enables the AR column cross-checkWhat it checks
Section titled “What it checks”FactoryBot.define do factory :user do name { "Alice" } email { "alice@example.com" } endend
FactoryBot.create(:user, name: "X") # ✓ info traceFactoryBot.build(:post, headline: "Hi") # ✗ unknown-attribute (suggest :title)FactoryBot.create(:usre) # ✗ unknown-factory (suggest :user)| Rule | Severity | Fires when |
|---|---|---|
plugin.factorybot.factory-call | info | the call resolved to a known factory; lists its declared attributes |
plugin.factorybot.unknown-factory | error | the literal :name isn’t in the factory index (with a did-you-mean) |
plugin.factorybot.unknown-attribute | error | a keyword key isn’t a declared attribute (with a did-you-mean); also checked against the model’s columns when :model_index is available |
The legacy FactoryGirl constant is recognised the same way.
Recognised entry methods: create / build / build_stubbed /
attributes_for and the *_list variants. Inside a factory it
recognises name { … } (modern), name "…" (legacy positional),
and add_attribute(:name) { … }.
Configuration
Section titled “Configuration”plugins: - gem: rigor-factorybot config: factory_search_paths: ["spec/factories", "spec/factories.rb"] # default # Minitest projects: ["test/factories"]Limitations
Section titled “Limitations”- Literal arguments only —
FactoryBot.create(name)with a variable name passes through. - Traits / sequences / associations not collected yet — an
attribute defined only inside
trait :admin do … endcan surface a falseunknown-attributeuntil the trait slice ships. - Explicit receiver only — bare
create(:user)(frominclude FactoryBot::Syntax::Methods) is not recognised in this slice; it needs receiver-type inference, which would otherwise false-positive on every unrelatedcreatecall.
Plugin internals
Section titled “Plugin internals”The factory discoverer / index, the cached producer, the
:model_index consumption, the demo, and the contract surfaces
this plugin exercises are in the
plugin’s README. To
write a plugin, see examples/ and
the rigor-plugin-author skill.
© 2026 TypedDuck. Licensed under CC BY-SA 4.0.