class FactoryBot::DefinitionProxy

Constants

UNPROXIED_METHODS

Attributes

child_factories[R]

Public Class Methods

new(definition, ignore = false) click to toggle source
# File lib/factory_bot/definition_proxy.rb, line 13
def initialize(definition, ignore = false)
  @definition      = definition
  @ignore          = ignore
  @child_factories = []
end

Public Instance Methods

add_attribute(name, value = nil, &block) click to toggle source

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.

When defining lazy attributes, an instance of FactoryBot::Strategy will be yielded, allowing associations to be built using the correct build strategy.

Arguments:

  • name: Symbol or String 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.

# File lib/factory_bot/definition_proxy.rb, line 42
def add_attribute(name, value = nil, &block)
  raise AttributeDefinitionError, 'Both value and block given' if value && block_given?

  declaration = if block_given?
    Declaration::Dynamic.new(name, @ignore, block)
  else
    Declaration::Static.new(name, value, @ignore)
  end

  @definition.declare_attribute(declaration)
end
association(name, *options) click to toggle source

Adds an attribute that builds an association. The associated instance will be built using the same build strategy as the parent instance.

Example:

factory :user do
  name 'Joey'
end

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.
# File lib/factory_bot/definition_proxy.rb, line 150
def association(name, *options)
  @definition.declare_attribute(Declaration::Association.new(name, *options))
end
factory(name, options = {}, &block) click to toggle source
# File lib/factory_bot/definition_proxy.rb, line 162
def factory(name, options = {}, &block)
  @child_factories << [name, options, block]
end
ignore(&block) click to toggle source
# File lib/factory_bot/definition_proxy.rb, line 54
def ignore(&block)
  ActiveSupport::Deprecation.warn "`#ignore` is deprecated and will be "\
    "removed in 5.0. Please use `#transient` instead."
  transient(&block)
end
initialize_with(&block) click to toggle source
# File lib/factory_bot/definition_proxy.rb, line 170
def initialize_with(&block)
  @definition.define_constructor(&block)
end
method_missing(name, *args, &block) click to toggle source

Calls add_attribute using the missing method name as the name of the attribute, so that:

factory :user do
  name 'Billy Idol'
end

and:

factory :user do
  add_attribute :name, 'Billy Idol'
end

are equivalent.

If no argument or block is given, factory_bot will look for a sequence or association with the same name. This means that:

factory :user do
  email { create(:email) }
  association :account
end

and:

factory :user do
  email
  account
end

are equivalent.

# File lib/factory_bot/definition_proxy.rb, line 96
def method_missing(name, *args, &block)
  if args.empty? && block.nil?
    @definition.declare_attribute(Declaration::Implicit.new(name, @definition, @ignore))
  elsif args.first.respond_to?(:has_key?) && args.first.has_key?(:factory)
    association(name, *args)
  else
    add_attribute(name, *args, &block)
  end
end
sequence(name, *args, &block) click to toggle source

Adds an attribute that will have unique values generated by a sequence with a specified format.

The result of:

factory :user do
  sequence(:email) { |n| "person#{n}@example.com" }
end

Is equal to:

sequence(:email) { |n| "person#{n}@example.com" }

factory :user do
  email { FactoryBot.generate(:email) }
end

Except that no globally available sequence will be defined.

# File lib/factory_bot/definition_proxy.rb, line 122
def sequence(name, *args, &block)
  sequence = Sequence.new(name, *args, &block)
  add_attribute(name) { increment_sequence(sequence) }
end
singleton_method_added(name) click to toggle source
# File lib/factory_bot/definition_proxy.rb, line 19
def singleton_method_added(name)
  message = "Defining methods in blocks (trait or factory) is not supported (#{name})"
  raise FactoryBot::MethodDefinitionError, message
end
skip_create() click to toggle source
# File lib/factory_bot/definition_proxy.rb, line 158
def skip_create
  @definition.skip_create
end
to_create(&block) click to toggle source
# File lib/factory_bot/definition_proxy.rb, line 154
def to_create(&block)
  @definition.to_create(&block)
end
trait(name, &block) click to toggle source
# File lib/factory_bot/definition_proxy.rb, line 166
def trait(name, &block)
  @definition.define_trait(Trait.new(name, &block))
end
transient(&block) click to toggle source
# File lib/factory_bot/definition_proxy.rb, line 60
def transient(&block)
  proxy = DefinitionProxy.new(@definition, true)
  proxy.instance_eval(&block)
end