1
0
Fork 0
mirror of https://github.com/thoughtbot/factory_bot.git synced 2022-11-09 11:43:51 -05:00
thoughtbot--factory_bot/lib/factory_girl/definition_proxy.rb

155 lines
4.3 KiB
Ruby
Raw Normal View History

module FactoryGirl
class DefinitionProxy
instance_methods.each do |method|
undef_method(method) unless method =~ /(^__|^nil\?$|^send$|^object_id$|^extend$|^instance_eval$)/
end
attr_reader :child_factories
def initialize(factory)
@factory = factory
@child_factories = []
end
# Adds an attribute that should be assigned 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 overridden for a specific instance.
#
2010-10-01 18:50:01 -04:00
# When defining lazy attributes, an instance of FactoryGirl::Proxy will
# be yielded, allowing associations to be built using the correct build
# strategy.
#
# Arguments:
# * name: +Symbol+ or +String+
2011-02-07 17:48:00 -05:00
# The name of this attribute. This will be assigned using "name=" for
# generated instances.
# * 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?
if value
raise AttributeDefinitionError, "Both value and block given"
else
attribute = Attribute::Dynamic.new(name, block)
end
else
attribute = Attribute::Static.new(name, value)
end
@factory.define_attribute(attribute)
end
# Calls add_attribute using the missing method name as the name of the
# attribute, so that:
#
2010-10-01 18:50:01 -04:00
# factory :user do
# name 'Billy Idol'
# end
#
# and:
#
2010-10-01 18:50:01 -04:00
# factory :user do
# add_attribute :name, 'Billy Idol'
# end
#
2011-07-01 19:08:03 -04:00
# are equivalent.
2010-10-01 18:50:01 -04:00
#
# If no argument or block is given, factory_girl will look for a sequence
# or association with the same name. This means that:
#
# factory :user do
# email { create(:email) }
2010-10-01 18:50:01 -04:00
# association :account
# end
#
# and:
#
# factory :user do
# email
# account
# end
#
2011-07-01 19:08:03 -04:00
# are equivalent.
def method_missing(name, *args, &block)
if args.empty? && block.nil?
@factory.define_attribute(Attribute::Implicit.new(name))
else
add_attribute(name, *args, &block)
end
end
# Adds an attribute that will have unique values generated by a sequence with
# a specified format.
#
# The result of:
2010-10-01 18:50:01 -04:00
# factory :user do
# sequence(:email) { |n| "person#{n}@example.com" }
# end
#
# Is equal to:
2010-10-01 18:50:01 -04:00
# sequence(:email) { |n| "person#{n}@example.com" }
#
2010-10-01 18:50:01 -04:00
# factory :user do
# email { FactoryGirl.create(:email) }
# end
#
# Except that no globally available sequence will be defined.
def sequence(name, start_value = 1, &block)
sequence = Sequence.new(name, start_value, &block)
add_attribute(name) { sequence.next }
end
# Adds an attribute that builds an association. The associated instance will
# be built using the same build strategy as the parent instance.
#
# Example:
2010-10-01 18:50:01 -04:00
# factory :user do
# name 'Joey'
# end
#
2010-10-01 18:50:01 -04:00
# factory :post do
# association :author, :factory => :user
# end
#
# Arguments:
# * name: +Symbol+
# The name of this attribute.
# * options: +Hash+
#
# Options:
# * factory: +Symbol+ or +String+
# The name of the factory to use when building the associated instance.
# If no name is given, the name of the attribute is assumed to be the
# name of the factory. For example, a "user" association will by
# default use the "user" factory.
def association(name, options = {})
factory_name = options.delete(:factory) || name
@factory.define_attribute(Attribute::Association.new(name, factory_name, options))
end
def after_build(&block)
@factory.add_callback(:after_build, &block)
end
def after_create(&block)
@factory.add_callback(:after_create, &block)
end
def after_stub(&block)
@factory.add_callback(:after_stub, &block)
end
def to_create(&block)
@factory.to_create(&block)
end
def factory(name, options = {}, &block)
@child_factories << [name, options, block]
end
end
end