From 9907826ee578677877303288e16ae0f41e9c0e73 Mon Sep 17 00:00:00 2001 From: Joshua Clayton Date: Mon, 23 Apr 2012 22:48:33 -0500 Subject: [PATCH] Base class is implied when calling .new within initialize_with Closes #343 --- GETTING_STARTED.md | 18 ++++++++++++- lib/factory_girl/evaluator.rb | 5 +++- lib/factory_girl/factory.rb | 2 +- spec/acceptance/initialize_with_spec.rb | 26 +++++++++++++++++++ .../evaluator_class_definer_spec.rb | 2 +- 5 files changed, 49 insertions(+), 4 deletions(-) diff --git a/GETTING_STARTED.md b/GETTING_STARTED.md index 916e697..7ec4f8d 100644 --- a/GETTING_STARTED.md +++ b/GETTING_STARTED.md @@ -723,7 +723,7 @@ factory :user do end email - initialize_with { User.new(name) } + initialize_with { new(name) } end FactoryGirl.build(:user).name # Bob Hope @@ -745,6 +745,22 @@ You can override the initializer in order to: * Use a method other than `new` to instantiate the instance * Do crazy things like decorate the instance after it's built +When using `initialize_with`, you don't have to declare the class itself when +calling `new`; however, any other class methods you want to call will have to +be called on the class explicitly. + +For example: + +```ruby +factory :user do + ignore do + name { Faker::Name.name } + end + + initialize_with { User.build_with_name(name) } +end +``` + Custom Strategies ----------------- diff --git a/lib/factory_girl/evaluator.rb b/lib/factory_girl/evaluator.rb index 6d79d01..d36cb12 100644 --- a/lib/factory_girl/evaluator.rb +++ b/lib/factory_girl/evaluator.rb @@ -17,7 +17,8 @@ module FactoryGirl undef_method(method) unless method =~ /^__|initialize/ end - def initialize(build_strategy, overrides = {}) + def initialize(build_class, build_strategy, overrides = {}) + @build_class = build_class @build_strategy = build_strategy @overrides = overrides @cached_attributes = overrides @@ -27,6 +28,8 @@ module FactoryGirl end end + delegate :new, to: :@build_class + def association(factory_name, overrides = {}) strategy_override = overrides.fetch(:strategy) { FactoryGirl.strategy_by_name(:create) } diff --git a/lib/factory_girl/factory.rb b/lib/factory_girl/factory.rb index eee9c4d..949899b 100644 --- a/lib/factory_girl/factory.rb +++ b/lib/factory_girl/factory.rb @@ -32,7 +32,7 @@ module FactoryGirl strategy = strategy_class.new - evaluator = evaluator_class.new(strategy, overrides.symbolize_keys) + evaluator = evaluator_class.new(build_class, strategy, overrides.symbolize_keys) attribute_assigner = AttributeAssigner.new(evaluator, build_class, &instance_builder) evaluation = Evaluation.new(attribute_assigner, to_create) diff --git a/spec/acceptance/initialize_with_spec.rb b/spec/acceptance/initialize_with_spec.rb index b2bfd41..aedc6ef 100644 --- a/spec/acceptance/initialize_with_spec.rb +++ b/spec/acceptance/initialize_with_spec.rb @@ -145,3 +145,29 @@ describe "initialize_with parent and child factories" do FactoryGirl.build(:super_awesome).name.should == "Super" end end + +describe "initialize_with implicit constructor" do + before do + define_class("Awesome") do + attr_reader :name + + def initialize(name) + @name = name + end + end + + FactoryGirl.define do + factory :awesome do + ignore do + name "Great" + end + + initialize_with { new(name) } + end + end + end + + it "instantiates the correct object" do + FactoryGirl.build(:awesome, name: "Awesome name").name.should == "Awesome name" + end +end diff --git a/spec/factory_girl/evaluator_class_definer_spec.rb b/spec/factory_girl/evaluator_class_definer_spec.rb index 3e65f34..2683a05 100644 --- a/spec/factory_girl/evaluator_class_definer_spec.rb +++ b/spec/factory_girl/evaluator_class_definer_spec.rb @@ -7,7 +7,7 @@ describe FactoryGirl::EvaluatorClassDefiner do let(:attributes) { [simple_attribute, relative_attribute, attribute_that_raises_a_second_time] } let(:class_definer) { FactoryGirl::EvaluatorClassDefiner.new(attributes, FactoryGirl::Evaluator) } - let(:evaluator) { class_definer.evaluator_class.new(stub("build strategy", add_observer: true)) } + let(:evaluator) { class_definer.evaluator_class.new(Object, stub("build strategy", add_observer: true)) } it "returns an evaluator when accessing the evaluator class" do evaluator.should be_a(FactoryGirl::Evaluator)