Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions lib/factory_bot/callback.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ def initialize(name, block)
@block = block
end

def run_before_build
syntax_runner.instance_exec(&block)
end

def run(instance, evaluator)
case block.arity
when 1, -1, -2 then syntax_runner.instance_exec(instance, &block)
Expand All @@ -20,6 +24,10 @@ def ==(other)
block == other.block
end

def before_build?
name == :before_build
end

protected

attr_reader :block
Expand Down
7 changes: 7 additions & 0 deletions lib/factory_bot/factory.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ def build_class
def run(build_strategy, overrides, &block)
block ||= ->(result) { result }
compile
run_before_build_callbacks

strategy = StrategyCalculator.new(build_strategy).strategy.new

Expand Down Expand Up @@ -139,6 +140,12 @@ def compiled_constructor
hierarchy_instance.constructor
end

def run_before_build_callbacks
callbacks.each do |callback|
callback.run_before_build if callback.before_build?
end
end

private

def assert_valid_options(options)
Expand Down
30 changes: 30 additions & 0 deletions spec/acceptance/callbacks_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -249,3 +249,33 @@ def name
expect(build(:company).name).to eq "ACME SUPPLIERS"
end
end

describe "before build callback" do
class TitleSetter
def self.title=(new_title)
@@title = new_title
end

def self.title
@@title
end
end

before do
define_model("Article", title: :string)

FactoryBot.define do
factory :article_with_before_callbacks, class: :article do
before(:build) { TitleSetter.title = "title from before build" }
after(:build) { TitleSetter.title = "title from after build" }

title { TitleSetter.title }
end
end
end

it "runs the before callback" do
article = FactoryBot.build(:article_with_before_callbacks)
expect(article.title).to eq("title from before build")
end
end
11 changes: 11 additions & 0 deletions spec/factory_bot/callback_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,15 @@
FactoryBot::Callback.new(:after_create, ->(one, two) { ran_with = [one, two] }).run(:one, :two)
expect(ran_with).to eq [:one, :two]
end

it "runs run_before_build callback without attributes" do
ran_with = nil
FactoryBot::Callback.new(:before_build, -> { ran_with = "before build" }).run_before_build
expect(ran_with).to eq "before build"
end

it "#before_build?" do
expect(FactoryBot::Callback.new(:before_build, -> {}).before_build?).to be true
expect(FactoryBot::Callback.new(:after_create, -> {}).before_build?).to be false
end
end