Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Traits that imply other ones can cause double running of callbacks #1703

Open
saty9 opened this issue Oct 2, 2024 · 3 comments · May be fixed by #1712
Open

Traits that imply other ones can cause double running of callbacks #1703

saty9 opened this issue Oct 2, 2024 · 3 comments · May be fixed by #1712

Comments

@saty9
Copy link

saty9 commented Oct 2, 2024

Description

When i make a trait B that implies A and build with B and A traits the after(:build) in A runs twice

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 :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
  factory :post do
    body { "Post body" }

    trait :implies_foo do
      foo
    end

    trait :foo do
      after(:build) do |post|
        post.body += " with foo"
      end
    end
  end
end

class FactoryBotTest < Minitest::Test
  def test_factory_bot_stuff
    post = FactoryBot.build(:post, :foo, :implies_foo)

    assert_equal post.body, "Post body with foo"
  end
end

# Run the tests with `ruby <filename>`

Expected behavior

I expect the after(:build) block to be run once

Actual behavior

It runs twice instead

System configuration

factory_bot version: 6.4.5
rails version: 7.2.1
ruby version: 3.3.5

@saty9 saty9 added the bug label Oct 2, 2024
@colinross
Copy link
Contributor

The aggregate callbacks get a flatten.compact but maybe the context is making them dissimilar?
We could wrap them in a registry like the decorators, but then we would need to have a name/identifier for each callback, otherwise how distinguish between one after_save and another, right?

@CodeMeister
Copy link

Hi @saty9 & @colinross. I've added a pull-request that fixes this exact issue: #1712

Have a look and let me know if it works for you.

😀

@colinross
Copy link
Contributor

Looks promising to me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants