Skip to content

Commit

Permalink
Move all block execution for dynamic attributes to the anonymous_inst…
Browse files Browse the repository at this point in the history
…ance
  • Loading branch information
joshuaclayton committed Nov 29, 2011
1 parent 56a6f67 commit b339c8f
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 25 deletions.
2 changes: 1 addition & 1 deletion lib/factory_girl/attribute/dynamic.rb
Expand Up @@ -10,7 +10,7 @@ def to_proc(proxy)
block = @block

lambda {
value = block.arity == 1 ? block.call(proxy) : proxy.instance_exec(&block)
value = block.arity == 1 ? block.call(self) : instance_exec(&block)
raise SequenceAbuseError if FactoryGirl::Sequence === value
value
}
Expand Down
33 changes: 18 additions & 15 deletions lib/factory_girl/proxy.rb
Expand Up @@ -11,12 +11,12 @@ def initialize(klass, callbacks = [])
@proxy = ObjectWrapper.new(klass)
end

delegate :get, :set, :set_ignored, :to => :@proxy
delegate :get, :set, :set_ignored, :anonymous_instance, :to => :@proxy

def run_callbacks(name)
if @callbacks[name]
@callbacks[name].each do |callback|
callback.run(result_instance, self)
callback.run(result_instance, anonymous_instance)
end
end
end
Expand Down Expand Up @@ -68,10 +68,6 @@ def self.ensure_strategy_exists!(strategy)

private

def method_missing(method, *args, &block)
get(method)
end

def process_callbacks(callbacks)
callbacks.inject({}) do |result, callback|
result[callback.name] ||= []
Expand All @@ -92,7 +88,7 @@ class ObjectWrapper
def initialize(klass)
@klass = klass
@attributes = []
@cached_attribute_values = {}
@assigned_attributes = []
end

def to_hash
Expand All @@ -118,27 +114,34 @@ def set_ignored(attribute, value)
end

def get(attribute)
@cached_attribute_values[attribute] ||= anonymous_instance.send(attribute)
anonymous_instance.send(attribute)
end

def anonymous_instance
@anonymous_instance ||= anonymous_class.new
end

private

def define_attribute(attribute, value)
anonymous_class.send(:define_method, attribute.name, value)
anonymous_class.send(:define_method, attribute.name) {
@cached_attributes[attribute.name] ||= instance_exec(&value)
}
end

def assign_object_attributes
(@attributes - @cached_attribute_values.keys).each do |attribute|
(@attributes - @assigned_attributes).each do |attribute|
@assigned_attributes << attribute
@object.send("#{attribute}=", get(attribute))
end
end

def anonymous_class
@anonymous_class ||= Class.new
end

def anonymous_instance
@anonymous_instance ||= anonymous_class.new
@anonymous_class ||= Class.new do
def initialize
@cached_attributes = {}
end
end
end
end
end
Expand Down
6 changes: 3 additions & 3 deletions spec/factory_girl/attribute/dynamic_spec.rb
Expand Up @@ -20,8 +20,8 @@
context "with a block returning its block-level variable" do
let(:block) { lambda {|thing| thing } }

it "returns the proxy when executing the proc" do
subject.to_proc(proxy).call.should == proxy
it "returns self when executing the proc" do
subject.to_proc(proxy).call.should == subject
end
end

Expand All @@ -30,7 +30,7 @@
let(:result) { "other attribute value" }

before do
proxy.stubs(:attribute_defined_on_proxy => result)
subject.stubs(:attribute_defined_on_proxy => result)
end

it "evaluates the attribute from the proxy" do
Expand Down
5 changes: 0 additions & 5 deletions spec/factory_girl/proxy_spec.rb
Expand Up @@ -10,11 +10,6 @@
expect { subject.set(name_attribute, lambda { "a name" }) }.to_not raise_error
end

it "calls get for a missing method" do
subject.stubs(:get).with(:name).returns("it's a name")
subject.name.should == "it's a name"
end

it "raises an error when asking for the result" do
expect { subject.result(nil) }.to raise_error(NotImplementedError)
end
Expand Down
2 changes: 1 addition & 1 deletion spec/support/shared_examples/proxy.rb
Expand Up @@ -73,7 +73,7 @@
subject.result(lambda {|instance| instance })
end

its(attribute) { should == value }
its(:"anonymous_instance.#{attribute}") { should == value }
it { instance.should have_received(:"#{attribute}=").with(value) }
end

Expand Down

0 comments on commit b339c8f

Please sign in to comment.