Navigation Menu

Skip to content

Commit

Permalink
Allow methods to be called from the instance in factory girl attributes
Browse files Browse the repository at this point in the history
This fixes a regression introduced with the introduction of the
anonymous class.

Closes #264
  • Loading branch information
joshuaclayton committed Jan 8, 2012
1 parent 4b6ada7 commit d918c1d
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 1 deletion.
11 changes: 11 additions & 0 deletions lib/factory_girl/attribute_assigner.rb
Expand Up @@ -8,6 +8,7 @@ def initialize(build_class, evaluator, attribute_list)
end

def object
@evaluator.instance = build_class_instance
build_class_instance.tap do |instance|
attributes_to_set_on_instance.each do |attribute|
instance.send("#{attribute}=", get(attribute))
Expand All @@ -17,6 +18,8 @@ def object
end

def hash
@evaluator.instance = null_object.new

attributes_to_set_on_hash.inject({}) do |result, attribute|
result[attribute] = get(attribute)
result
Expand All @@ -29,6 +32,14 @@ def build_class_instance
@build_class_instance ||= @build_class.new
end

def null_object
Class.new(BasicObject) do
def method_missing(*args)
nil
end
end
end

def get(attribute_name)
@evaluator.send(attribute_name)
end
Expand Down
6 changes: 5 additions & 1 deletion lib/factory_girl/evaluator.rb
Expand Up @@ -12,11 +12,15 @@ def initialize(build_strategy, overrides = {}, callbacks = [])

delegate :association, :to => :@build_strategy

def instance=(object_instance)
@instance = object_instance
end

def method_missing(method_name, *args, &block)
if @cached_attributes.key?(method_name)
@cached_attributes[method_name]
else
super
@instance.send(method_name, *args, &block)
end
end

Expand Down
53 changes: 53 additions & 0 deletions spec/acceptance/attributes_from_instance_spec.rb
@@ -0,0 +1,53 @@
require "spec_helper"

describe "calling methods on the model instance" do
before do
define_model('User', :age => :integer, :age_copy => :integer) do
def age
read_attribute(:age) || 18
end
end

FactoryGirl.define do
factory :user do
age_copy { age }
end
end
end

context "without the attribute being overridden" do
it "returns the correct value from the instance" do
FactoryGirl.build(:user).age_copy.should == 18
end

it "returns nil during attributes_for" do
FactoryGirl.attributes_for(:user)[:age_copy].should be_nil
end

it "doesn't instantiate a record with attributes_for" do
User.stubs(:new)
FactoryGirl.attributes_for(:user)
User.should have_received(:new).never
end
end

context "with the attribute being overridden" do
it "uses the overridden value" do
FactoryGirl.build(:user, :age_copy => nil).age_copy.should be_nil
end

it "uses the overridden value during attributes_for" do
FactoryGirl.attributes_for(:user, :age_copy => 25)[:age_copy].should == 25
end
end

context "with the referenced attribute being overridden" do
it "uses the overridden value" do
FactoryGirl.build(:user, :age => nil).age_copy.should be_nil
end

it "uses the overridden value during attributes_for" do
FactoryGirl.attributes_for(:user, :age => 25)[:age_copy].should == 25
end
end
end

0 comments on commit d918c1d

Please sign in to comment.