Skip to content

Commit

Permalink
Implemented add_attribute and attributes for Factory
Browse files Browse the repository at this point in the history
  • Loading branch information
jferris committed May 29, 2008
1 parent b01006c commit d3a5d85
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 0 deletions.
47 changes: 47 additions & 0 deletions lib/factory_girl/factory.rb
Expand Up @@ -23,6 +23,53 @@ def self.define (name)

def initialize (name) #:nodoc:
@name = name
@static_attributes = {}
@lazy_attributes = {}
end

# Adds an attribute that should be assigned or stubbed on generated instances for this factory.
#
# This method should be called with either a value or block, but not both. If
# called with a block, the attribute will be generated "lazily," whenever an
# instance is generated. Lazy attribute blocks will not be called if that
# attribute is overriden for a specific instance.
#
# Arguments:
# name: (Symbol)
# The name of this attribute. This will be assigned using :"#{name}=" for
# generated instances, and stubbed out with this name for generated
# stubs.
# value: (Object)
# If no block is given, this value will be used for this attribute.
def add_attribute (name, value = nil, &block)
if block_given?
unless value.nil?
raise ArgumentError, "Both value and block given"
end
@lazy_attributes[name] = block
else
@static_attributes[name] = value
end
end

# Generates and returns a Hash of attributes from this factory. Attributes
# can be individually overridden by passing in a Hash of attribute => value
# pairs.
#
# Arguments:
# attrs: (Hash)
# Attributes to overwrite for this set.
#
# Returns:
# A set of attributes that can be used to build an instance of the class
# this factory generates. (Hash)
def attributes (attrs = {})
result = {}
@lazy_attributes.each do |name, block|
result[name] = block.call unless attrs.key?(name)
end
result.update(@static_attributes)
result.update(attrs)
end

end
67 changes: 67 additions & 0 deletions test/factory_test.rb
Expand Up @@ -42,6 +42,73 @@ class FactoryTest < Test::Unit::TestCase
assert_equal @name, @factory.name
end

context "when adding an attribute with a value parameter" do

setup do
@attr = :name
@value = 'Elvis lives!'
@factory.add_attribute(@attr, @value)
end

should "include that value in the generated attributes hash" do
assert_equal @value, @factory.attributes[@attr]
end

end

context "when adding an attribute with a block" do

setup do
@attr = :name
end

should "not evaluate the block when the attribute is added" do
@factory.add_attribute(@attr) { flunk }
end

should "evaluate the block when attributes are generated" do
called = false
@factory.add_attribute(@attr) do
called = true
end
@factory.attributes
assert called
end

should "use the result of the block as the value of the attribute" do
value = "Watch out for snakes!"
@factory.add_attribute(@attr) { value }
assert_equal value, @factory.attributes[@attr]
end

end

should "not allow attributes to be added with both a value parameter and a block" do
assert_raise(ArgumentError) do
@factory.add_attribute(:name, 'value') {}
end
end

context "when overriding generated attributes with a hash" do

setup do
@attr = :name
@value = 'The price is right!'
@hash = { @attr => @value }
end

should "return the overridden value in the generated attributes" do
@factory.add_attribute(@attr, 'The price is wrong, Bob!')
assert_equal @value, @factory.attributes(@hash)[@attr]
end

should "not call a lazy attribute block for an overridden attribute" do
@factory.add_attribute(@attr) { flunk }
@factory.attributes(@hash)
end

end

end

end

0 comments on commit d3a5d85

Please sign in to comment.