class FactoryBot::DefinitionProxy
Constants
- UNPROXIED_METHODS
Attributes
Public Class Methods
# File lib/factory_bot/definition_proxy.rb, line 26 def initialize(definition, ignore = false) @definition = definition @ignore = ignore @child_factories = [] end
Public Instance Methods
Adds an attribute to the factory. The attribute value will be generated “lazily” by calling the block whenever an instance is generated. The block will not be called if the attribute is overridden for a specific instance.
Arguments:
-
name:
Symbol
orString
The name of this attribute. This will be assigned using “name=” for generated instances.
# File lib/factory_bot/definition_proxy.rb, line 47 def add_attribute(name, &block) declaration = Declaration::Dynamic.new(name, @ignore, block) @definition.declare_attribute(declaration) end
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
orString
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 151 def association(name, *options) if block_given? raise AssociationDefinitionError.new( "Unexpected block passed to '#{name}' association "\ "in '#{@definition.name}' factory" ) else declaration = Declaration::Association.new(name, *options) @definition.declare_attribute(declaration) end end
# File lib/factory_bot/definition_proxy.rb, line 171 def factory(name, options = {}, &block) @child_factories << [name, options, block] end
# File lib/factory_bot/definition_proxy.rb, line 237 def initialize_with(&block) @definition.define_constructor(&block) end
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 first look for an association, then for a sequence, and finally for a trait with the same name. This means that given an “admin” trait, an “email” sequence, and an “account” factory:
factory :user, traits: [:admin] do email { generate(:email) } association :account end
and:
factory :user do admin email account end
are equivalent.
# File lib/factory_bot/definition_proxy.rb, line 91 def method_missing(name, *args, &block) # rubocop:disable Style/MissingRespondToMissing association_options = args.first if association_options.nil? __declare_attribute__(name, block) elsif __valid_association_options?(association_options) association(name, association_options) else raise NoMethodError.new(<<~MSG) undefined method '#{name}' in '#{@definition.name}' factory Did you mean? '#{name} { #{association_options.inspect} }' MSG end end
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) FactoryBot::Internal.register_inline_sequence(sequence) add_attribute(name) { increment_sequence(sequence) } end
# File lib/factory_bot/definition_proxy.rb, line 32 def singleton_method_added(name) message = "Defining methods in blocks (trait or factory) is not supported (#{name})" raise FactoryBot::MethodDefinitionError, message end
# File lib/factory_bot/definition_proxy.rb, line 167 def skip_create @definition.skip_create end
# File lib/factory_bot/definition_proxy.rb, line 163 def to_create(&block) @definition.to_create(&block) end
# File lib/factory_bot/definition_proxy.rb, line 175 def trait(name, &block) @definition.define_trait(Trait.new(name, &block)) end
Creates traits for enumerable values.
Example:
factory :task do traits_for_enum :status, [:started, :finished] end
Equivalent to:
factory :task do trait :started do status { :started } end trait :finished do status { :finished } end end
Example:
factory :task do traits_for_enum :status, {started: 1, finished: 2} end
Example:
class Task def statuses {started: 1, finished: 2} end end factory :task do traits_for_enum :status end
Both equivalent to:
factory :task do trait :started do status { 1 } end trait :finished do status { 2 } end end
Arguments:
attribute_name: +Symbol+ or +String+ the name of the attribute these traits will set the value of values: +Array+, +Hash+, or other +Enumerable+ An array of trait names, or a mapping of trait names to values for those traits. When this argument is not provided, factory_bot will attempt to get the values by calling the pluralized `attribute_name` class method.
# File lib/factory_bot/definition_proxy.rb, line 233 def traits_for_enum(attribute_name, values = nil) @definition.register_enum(Enum.new(attribute_name, values)) end
# File lib/factory_bot/definition_proxy.rb, line 52 def transient(&block) proxy = DefinitionProxy.new(@definition, true) proxy.instance_eval(&block) end
Private Instance Methods
# File lib/factory_bot/definition_proxy.rb, line 243 def __declare_attribute__(name, block) if block.nil? declaration = Declaration::Implicit.new(name, @definition, @ignore) @definition.declare_attribute(declaration) else add_attribute(name, &block) end end
# File lib/factory_bot/definition_proxy.rb, line 252 def __valid_association_options?(options) options.respond_to?(:has_key?) && options.has_key?(:factory) end