thoughtbot / thoughtbot/factory_bot
Associations blocks are being executed with invalid data at attributes_for
Nobody has claimed this yet.
- Dominant language
- Ruby
- Stars
- 8.2k
- Forks
- 2.6k
- PR merge metrics
- No merged PRs in 30d
Description
Description
Hi team!
I noticed that FactoryBot is executing the associations block even when I'm using attributes_for.
When I have one block which depends on another association, ruby is going to generate an undefined method "the-association-name" for nil:NilClass.
I expected that the associations blocks weren't executed.
Thanks. You're great 💜!
Reproduction Steps
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
create_table :blogs, force: true do |t|
t.string :name
end
create_table :authors, force: true do |t|
t.string :name
t.references :blog
end
create_table :posts, force: true do |t|
t.string :body
t.references :blog
t.references :author
end
end
class Blog < ActiveRecord::Base
has_many :authors
has_many :blogs
end
class Author < ActiveRecord::Base
belongs_to :blog
has_many :posts
end
class Post < ActiveRecord::Base
belongs_to :blog
belongs_to :author
end
FactoryBot.define do
factory :blog do
name { "the blog name" }
end
factory :author do
name { "the author name" }
end
factory :post do
body { "the post body" }
blog
# This block should not be executed
# on FactoryBot.attributes_for(:comment)
author { blog.authors.first }
end
end
class FactoryBotTest < Minitest::Test
def test_factory_bot_stuff
post = FactoryBot.create(:post)
assert_equal post.author, post.blog.authors.first
# true
FactoryBot.attributes_for(:post)
# NoMethodError: undefined method `authors' for nil:NilClass
end
end
Expected behavior
I expected that the associations blocks weren't executed or the associations data were valids.
Actual behavior
The associations blocks are being executed with invalid data.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the supplied ActiveRecord/SQLite reproduction and trace FactoryBot.attributes_for(:post), especially how the blog association and author block are evaluated. Add a regression test for the expected handling of association blocks, then run the relevant test suite to confirm attributes_for no longer raises.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rails, ruby, sqlite
- Domain
- testing
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100