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.