diff --git a/GETTING_STARTED.md b/GETTING_STARTED.md index e763ebf..880c197 100644 --- a/GETTING_STARTED.md +++ b/GETTING_STARTED.md @@ -762,6 +762,15 @@ factory :user do end ``` +You can define `initialize_with` for all factories by including it in the +`FactoryGirl.define` block: + +```ruby +FactoryGirl.define do + initialize_with { new("Awesome first argument") } +end +``` + Custom Strategies ----------------- diff --git a/lib/factory_girl.rb b/lib/factory_girl.rb index 5d532ff..cc3f270 100644 --- a/lib/factory_girl.rb +++ b/lib/factory_girl.rb @@ -50,7 +50,7 @@ module FactoryGirl class << self delegate :factories, :sequences, :traits, :strategies, :callback_names, - :to_create, :skip_create, to: :configuration + :to_create, :skip_create, :initialize_with, :constructor, to: :configuration end def self.register_factory(factory) diff --git a/lib/factory_girl/configuration.rb b/lib/factory_girl/configuration.rb index 687b831..20f24b7 100644 --- a/lib/factory_girl/configuration.rb +++ b/lib/factory_girl/configuration.rb @@ -12,8 +12,13 @@ module FactoryGirl @definition = Definition.new to_create {|instance| instance.save! } + initialize_with { new } end - delegate :to_create, :skip_create, to: :@definition + delegate :to_create, :skip_create, :constructor, to: :@definition + + def initialize_with(&block) + @definition.define_constructor(&block) + end end end diff --git a/lib/factory_girl/factory.rb b/lib/factory_girl/factory.rb index dd9ff8d..6218fb2 100644 --- a/lib/factory_girl/factory.rb +++ b/lib/factory_girl/factory.rb @@ -34,8 +34,7 @@ module FactoryGirl strategy = StrategyCalculator.new(build_strategy).strategy.new evaluator = evaluator_class.new(build_class, strategy, overrides.symbolize_keys) - constructor = compiled_constructor || -> { new } - attribute_assigner = AttributeAssigner.new(evaluator, build_class, &constructor) + attribute_assigner = AttributeAssigner.new(evaluator, build_class, &compiled_constructor) evaluation = Evaluation.new(attribute_assigner, compiled_to_create) evaluation.add_observer(CallbacksObserver.new(callbacks, evaluator)) @@ -121,7 +120,7 @@ module FactoryGirl end def compiled_constructor - @definition.compiled_constructor || parent.compiled_constructor + @definition.compiled_constructor || parent.compiled_constructor || FactoryGirl.constructor end private diff --git a/lib/factory_girl/syntax/default.rb b/lib/factory_girl/syntax/default.rb index 734bcb5..039467f 100644 --- a/lib/factory_girl/syntax/default.rb +++ b/lib/factory_girl/syntax/default.rb @@ -41,6 +41,10 @@ module FactoryGirl FactoryGirl.skip_create end + def initialize_with(&block) + FactoryGirl.initialize_with(&block) + end + def self.run(block) new.instance_eval(&block) end diff --git a/spec/acceptance/global_initialize_with_spec.rb b/spec/acceptance/global_initialize_with_spec.rb new file mode 100644 index 0000000..cebd05e --- /dev/null +++ b/spec/acceptance/global_initialize_with_spec.rb @@ -0,0 +1,82 @@ +require 'spec_helper' + +describe 'global initialize_with' do + before do + define_class('User') do + attr_accessor:name + + def initialize(name) + @name = name + end + end + + define_class('Post') do + attr_reader :name + + def initialize(name) + @name = name + end + end + + FactoryGirl.define do + initialize_with { new("initialize_with") } + + trait :with_initialize_with do + initialize_with { new("trait initialize_with") } + end + + factory :user do + factory :child_user + + factory :child_user_with_trait do + with_initialize_with + end + end + + factory :post do + factory :child_post + + factory :child_post_with_trait do + with_initialize_with + end + end + end + end + + it 'handles base initialize_with' do + FactoryGirl.build(:user).name.should == 'initialize_with' + FactoryGirl.build(:post).name.should == 'initialize_with' + end + + it 'handles child initialize_with' do + FactoryGirl.build(:child_user).name.should == 'initialize_with' + FactoryGirl.build(:child_post).name.should == 'initialize_with' + end + + it 'handles child initialize_with with trait' do + FactoryGirl.build(:child_user_with_trait).name.should == 'trait initialize_with' + FactoryGirl.build(:child_post_with_trait).name.should == 'trait initialize_with' + end + + it 'handles inline trait override' do + FactoryGirl.build(:child_user, :with_initialize_with).name.should == 'trait initialize_with' + FactoryGirl.build(:child_post, :with_initialize_with).name.should == 'trait initialize_with' + end + + it 'uses initialize_with globally across FactoryGirl.define' do + define_class('Company') do + attr_reader :name + + def initialize(name) + @name = name + end + end + + FactoryGirl.define do + factory :company + end + + FactoryGirl.build(:company).name.should == 'initialize_with' + FactoryGirl.build(:company, :with_initialize_with).name.should == 'trait initialize_with' + end +end