factory_bot 1.0.0.alpha
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.autotest +9 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.simplecov +4 -0
- data/.travis.yml +41 -0
- data/.yardopts +5 -0
- data/Appraisals +19 -0
- data/CONTRIBUTING.md +60 -0
- data/GETTING_STARTED.md +1387 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +123 -0
- data/LICENSE +19 -0
- data/NAME.md +11 -0
- data/NEWS +285 -0
- data/README.md +102 -0
- data/Rakefile +36 -0
- data/cucumber.yml +1 -0
- data/factory_bot.gemspec +38 -0
- data/factory_girl.gemspec +41 -0
- data/gemfiles/3.2.gemfile +10 -0
- data/gemfiles/3.2.gemfile.lock +112 -0
- data/gemfiles/4.0.gemfile +10 -0
- data/gemfiles/4.0.gemfile.lock +112 -0
- data/gemfiles/4.1.gemfile +10 -0
- data/gemfiles/4.1.gemfile.lock +111 -0
- data/gemfiles/4.2.gemfile +10 -0
- data/gemfiles/4.2.gemfile.lock +111 -0
- data/gemfiles/5.0.gemfile +10 -0
- data/gemfiles/5.0.gemfile.lock +110 -0
- data/lib/factory_bot.rb +154 -0
- data/lib/factory_bot/aliases.rb +18 -0
- data/lib/factory_bot/attribute.rb +62 -0
- data/lib/factory_bot/attribute/association.rb +27 -0
- data/lib/factory_bot/attribute/dynamic.rb +24 -0
- data/lib/factory_bot/attribute/sequence.rb +16 -0
- data/lib/factory_bot/attribute/static.rb +16 -0
- data/lib/factory_bot/attribute_assigner.rb +97 -0
- data/lib/factory_bot/attribute_list.rb +67 -0
- data/lib/factory_bot/callback.rb +40 -0
- data/lib/factory_bot/callbacks_observer.rb +21 -0
- data/lib/factory_bot/configuration.rb +37 -0
- data/lib/factory_bot/declaration.rb +23 -0
- data/lib/factory_bot/declaration/association.rb +28 -0
- data/lib/factory_bot/declaration/dynamic.rb +26 -0
- data/lib/factory_bot/declaration/implicit.rb +33 -0
- data/lib/factory_bot/declaration/static.rb +26 -0
- data/lib/factory_bot/declaration_list.rb +49 -0
- data/lib/factory_bot/decorator.rb +21 -0
- data/lib/factory_bot/decorator/attribute_hash.rb +16 -0
- data/lib/factory_bot/decorator/class_key_hash.rb +28 -0
- data/lib/factory_bot/decorator/disallows_duplicates_registry.rb +13 -0
- data/lib/factory_bot/decorator/invocation_tracker.rb +19 -0
- data/lib/factory_bot/decorator/new_constructor.rb +12 -0
- data/lib/factory_bot/definition.rb +136 -0
- data/lib/factory_bot/definition_hierarchy.rb +48 -0
- data/lib/factory_bot/definition_proxy.rb +174 -0
- data/lib/factory_bot/errors.rb +25 -0
- data/lib/factory_bot/evaluation.rb +23 -0
- data/lib/factory_bot/evaluator.rb +82 -0
- data/lib/factory_bot/evaluator_class_definer.rb +20 -0
- data/lib/factory_bot/factory.rb +162 -0
- data/lib/factory_bot/factory_runner.rb +33 -0
- data/lib/factory_bot/find_definitions.rb +25 -0
- data/lib/factory_bot/linter.rb +97 -0
- data/lib/factory_bot/null_factory.rb +18 -0
- data/lib/factory_bot/null_object.rb +24 -0
- data/lib/factory_bot/registry.rb +38 -0
- data/lib/factory_bot/reload.rb +8 -0
- data/lib/factory_bot/sequence.rb +62 -0
- data/lib/factory_bot/strategy/attributes_for.rb +13 -0
- data/lib/factory_bot/strategy/build.rb +15 -0
- data/lib/factory_bot/strategy/create.rb +18 -0
- data/lib/factory_bot/strategy/null.rb +11 -0
- data/lib/factory_bot/strategy/stub.rb +108 -0
- data/lib/factory_bot/strategy_calculator.rb +26 -0
- data/lib/factory_bot/strategy_syntax_method_registrar.rb +54 -0
- data/lib/factory_bot/syntax.rb +7 -0
- data/lib/factory_bot/syntax/default.rb +76 -0
- data/lib/factory_bot/syntax/methods.rb +111 -0
- data/lib/factory_bot/syntax_runner.rb +6 -0
- data/lib/factory_bot/trait.rb +30 -0
- data/lib/factory_bot/version.rb +3 -0
- data/lib/factory_girl.rb +5 -0
- data/lib/factory_girl/version.rb +1 -0
- metadata +302 -0
@@ -0,0 +1,174 @@
|
|
1
|
+
module FactoryBot
|
2
|
+
class DefinitionProxy
|
3
|
+
UNPROXIED_METHODS = %w(__send__ __id__ nil? send object_id extend instance_eval initialize block_given? raise caller method)
|
4
|
+
|
5
|
+
(instance_methods + private_instance_methods).each do |method|
|
6
|
+
undef_method(method) unless UNPROXIED_METHODS.include?(method.to_s)
|
7
|
+
end
|
8
|
+
|
9
|
+
delegate :before, :after, :callback, to: :@definition
|
10
|
+
|
11
|
+
attr_reader :child_factories
|
12
|
+
|
13
|
+
def initialize(definition, ignore = false)
|
14
|
+
@definition = definition
|
15
|
+
@ignore = ignore
|
16
|
+
@child_factories = []
|
17
|
+
end
|
18
|
+
|
19
|
+
def singleton_method_added(name)
|
20
|
+
message = "Defining methods in blocks (trait or factory) is not supported (#{name})"
|
21
|
+
raise FactoryBot::MethodDefinitionError, message
|
22
|
+
end
|
23
|
+
|
24
|
+
# Adds an attribute that should be assigned on generated instances for this
|
25
|
+
# factory.
|
26
|
+
#
|
27
|
+
# This method should be called with either a value or block, but not both. If
|
28
|
+
# called with a block, the attribute will be generated "lazily," whenever an
|
29
|
+
# instance is generated. Lazy attribute blocks will not be called if that
|
30
|
+
# attribute is overridden for a specific instance.
|
31
|
+
#
|
32
|
+
# When defining lazy attributes, an instance of FactoryBot::Strategy will
|
33
|
+
# be yielded, allowing associations to be built using the correct build
|
34
|
+
# strategy.
|
35
|
+
#
|
36
|
+
# Arguments:
|
37
|
+
# * name: +Symbol+ or +String+
|
38
|
+
# The name of this attribute. This will be assigned using "name=" for
|
39
|
+
# generated instances.
|
40
|
+
# * value: +Object+
|
41
|
+
# If no block is given, this value will be used for this attribute.
|
42
|
+
def add_attribute(name, value = nil, &block)
|
43
|
+
raise AttributeDefinitionError, 'Both value and block given' if value && block_given?
|
44
|
+
|
45
|
+
declaration = if block_given?
|
46
|
+
Declaration::Dynamic.new(name, @ignore, block)
|
47
|
+
else
|
48
|
+
Declaration::Static.new(name, value, @ignore)
|
49
|
+
end
|
50
|
+
|
51
|
+
@definition.declare_attribute(declaration)
|
52
|
+
end
|
53
|
+
|
54
|
+
def ignore(&block)
|
55
|
+
ActiveSupport::Deprecation.warn "`#ignore` is deprecated and will be "\
|
56
|
+
"removed in 5.0. Please use `#transient` instead."
|
57
|
+
transient(&block)
|
58
|
+
end
|
59
|
+
|
60
|
+
def transient(&block)
|
61
|
+
proxy = DefinitionProxy.new(@definition, true)
|
62
|
+
proxy.instance_eval(&block)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Calls add_attribute using the missing method name as the name of the
|
66
|
+
# attribute, so that:
|
67
|
+
#
|
68
|
+
# factory :user do
|
69
|
+
# name 'Billy Idol'
|
70
|
+
# end
|
71
|
+
#
|
72
|
+
# and:
|
73
|
+
#
|
74
|
+
# factory :user do
|
75
|
+
# add_attribute :name, 'Billy Idol'
|
76
|
+
# end
|
77
|
+
#
|
78
|
+
# are equivalent.
|
79
|
+
#
|
80
|
+
# If no argument or block is given, factory_bot will look for a sequence
|
81
|
+
# or association with the same name. This means that:
|
82
|
+
#
|
83
|
+
# factory :user do
|
84
|
+
# email { create(:email) }
|
85
|
+
# association :account
|
86
|
+
# end
|
87
|
+
#
|
88
|
+
# and:
|
89
|
+
#
|
90
|
+
# factory :user do
|
91
|
+
# email
|
92
|
+
# account
|
93
|
+
# end
|
94
|
+
#
|
95
|
+
# are equivalent.
|
96
|
+
def method_missing(name, *args, &block)
|
97
|
+
if args.empty? && block.nil?
|
98
|
+
@definition.declare_attribute(Declaration::Implicit.new(name, @definition, @ignore))
|
99
|
+
elsif args.first.respond_to?(:has_key?) && args.first.has_key?(:factory)
|
100
|
+
association(name, *args)
|
101
|
+
else
|
102
|
+
add_attribute(name, *args, &block)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Adds an attribute that will have unique values generated by a sequence with
|
107
|
+
# a specified format.
|
108
|
+
#
|
109
|
+
# The result of:
|
110
|
+
# factory :user do
|
111
|
+
# sequence(:email) { |n| "person#{n}@example.com" }
|
112
|
+
# end
|
113
|
+
#
|
114
|
+
# Is equal to:
|
115
|
+
# sequence(:email) { |n| "person#{n}@example.com" }
|
116
|
+
#
|
117
|
+
# factory :user do
|
118
|
+
# email { FactoryBot.generate(:email) }
|
119
|
+
# end
|
120
|
+
#
|
121
|
+
# Except that no globally available sequence will be defined.
|
122
|
+
def sequence(name, *args, &block)
|
123
|
+
sequence = Sequence.new(name, *args, &block)
|
124
|
+
add_attribute(name) { increment_sequence(sequence) }
|
125
|
+
end
|
126
|
+
|
127
|
+
# Adds an attribute that builds an association. The associated instance will
|
128
|
+
# be built using the same build strategy as the parent instance.
|
129
|
+
#
|
130
|
+
# Example:
|
131
|
+
# factory :user do
|
132
|
+
# name 'Joey'
|
133
|
+
# end
|
134
|
+
#
|
135
|
+
# factory :post do
|
136
|
+
# association :author, factory: :user
|
137
|
+
# end
|
138
|
+
#
|
139
|
+
# Arguments:
|
140
|
+
# * name: +Symbol+
|
141
|
+
# The name of this attribute.
|
142
|
+
# * options: +Hash+
|
143
|
+
#
|
144
|
+
# Options:
|
145
|
+
# * factory: +Symbol+ or +String+
|
146
|
+
# The name of the factory to use when building the associated instance.
|
147
|
+
# If no name is given, the name of the attribute is assumed to be the
|
148
|
+
# name of the factory. For example, a "user" association will by
|
149
|
+
# default use the "user" factory.
|
150
|
+
def association(name, *options)
|
151
|
+
@definition.declare_attribute(Declaration::Association.new(name, *options))
|
152
|
+
end
|
153
|
+
|
154
|
+
def to_create(&block)
|
155
|
+
@definition.to_create(&block)
|
156
|
+
end
|
157
|
+
|
158
|
+
def skip_create
|
159
|
+
@definition.skip_create
|
160
|
+
end
|
161
|
+
|
162
|
+
def factory(name, options = {}, &block)
|
163
|
+
@child_factories << [name, options, block]
|
164
|
+
end
|
165
|
+
|
166
|
+
def trait(name, &block)
|
167
|
+
@definition.define_trait(Trait.new(name, &block))
|
168
|
+
end
|
169
|
+
|
170
|
+
def initialize_with(&block)
|
171
|
+
@definition.define_constructor(&block)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module FactoryBot
|
2
|
+
# Raised when a factory is defined that attempts to instantiate itself.
|
3
|
+
class AssociationDefinitionError < RuntimeError; end
|
4
|
+
|
5
|
+
# Raised when a callback is defined that has an invalid name
|
6
|
+
class InvalidCallbackNameError < RuntimeError; end
|
7
|
+
|
8
|
+
# Raised when a factory is defined with the same name as a previously-defined factory.
|
9
|
+
class DuplicateDefinitionError < RuntimeError; end
|
10
|
+
|
11
|
+
# Raised when attempting to register a sequence from a dynamic attribute block
|
12
|
+
class SequenceAbuseError < RuntimeError; end
|
13
|
+
|
14
|
+
# Raised when defining an invalid attribute:
|
15
|
+
# * Defining an attribute which has a name ending in "="
|
16
|
+
# * Defining an attribute with both a static and lazy value
|
17
|
+
# * Defining an attribute twice in the same factory
|
18
|
+
class AttributeDefinitionError < RuntimeError; end
|
19
|
+
|
20
|
+
# Raised when a method is defined in a factory or trait with arguments
|
21
|
+
class MethodDefinitionError < RuntimeError; end
|
22
|
+
|
23
|
+
# Raised when any factory is considered invalid
|
24
|
+
class InvalidFactoryError < RuntimeError; end
|
25
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'observer'
|
2
|
+
|
3
|
+
module FactoryBot
|
4
|
+
class Evaluation
|
5
|
+
include Observable
|
6
|
+
|
7
|
+
def initialize(attribute_assigner, to_create)
|
8
|
+
@attribute_assigner = attribute_assigner
|
9
|
+
@to_create = to_create
|
10
|
+
end
|
11
|
+
|
12
|
+
delegate :object, :hash, to: :@attribute_assigner
|
13
|
+
|
14
|
+
def create(result_instance)
|
15
|
+
@to_create[result_instance]
|
16
|
+
end
|
17
|
+
|
18
|
+
def notify(name, result_instance)
|
19
|
+
changed
|
20
|
+
notify_observers(name, result_instance)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'active_support/core_ext/hash/except'
|
2
|
+
require 'active_support/core_ext/class/attribute'
|
3
|
+
|
4
|
+
module FactoryBot
|
5
|
+
# @api private
|
6
|
+
class Evaluator
|
7
|
+
class_attribute :attribute_lists
|
8
|
+
|
9
|
+
private_instance_methods.each do |method|
|
10
|
+
undef_method(method) unless method =~ /^__|initialize/
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(build_strategy, overrides = {})
|
14
|
+
@build_strategy = build_strategy
|
15
|
+
@overrides = overrides
|
16
|
+
@cached_attributes = overrides
|
17
|
+
@instance = nil
|
18
|
+
|
19
|
+
@overrides.each do |name, value|
|
20
|
+
singleton_class.define_attribute(name) { value }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def association(factory_name, *traits_and_overrides)
|
25
|
+
overrides = traits_and_overrides.extract_options!
|
26
|
+
strategy_override = overrides.fetch(:strategy) do
|
27
|
+
FactoryBot.use_parent_strategy ? @build_strategy.class : :create
|
28
|
+
end
|
29
|
+
|
30
|
+
traits_and_overrides += [overrides.except(:strategy)]
|
31
|
+
|
32
|
+
runner = FactoryRunner.new(factory_name, strategy_override, traits_and_overrides)
|
33
|
+
@build_strategy.association(runner)
|
34
|
+
end
|
35
|
+
|
36
|
+
def instance=(object_instance)
|
37
|
+
@instance = object_instance
|
38
|
+
end
|
39
|
+
|
40
|
+
def method_missing(method_name, *args, &block)
|
41
|
+
if @instance.respond_to?(method_name)
|
42
|
+
@instance.send(method_name, *args, &block)
|
43
|
+
else
|
44
|
+
SyntaxRunner.new.send(method_name, *args, &block)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def respond_to_missing?(method_name, include_private = false)
|
49
|
+
@instance.respond_to?(method_name) || SyntaxRunner.new.respond_to?(method_name)
|
50
|
+
end
|
51
|
+
|
52
|
+
def __override_names__
|
53
|
+
@overrides.keys
|
54
|
+
end
|
55
|
+
|
56
|
+
def increment_sequence(sequence)
|
57
|
+
sequence.next(self)
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.attribute_list
|
61
|
+
AttributeList.new.tap do |list|
|
62
|
+
attribute_lists.each do |attribute_list|
|
63
|
+
list.apply_attributes attribute_list.to_a
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.define_attribute(name, &block)
|
69
|
+
if method_defined?(name) || private_method_defined?(name)
|
70
|
+
undef_method(name)
|
71
|
+
end
|
72
|
+
|
73
|
+
define_method(name) do
|
74
|
+
if @cached_attributes.key?(name)
|
75
|
+
@cached_attributes[name]
|
76
|
+
else
|
77
|
+
@cached_attributes[name] = instance_exec(&block)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module FactoryBot
|
2
|
+
# @api private
|
3
|
+
class EvaluatorClassDefiner
|
4
|
+
def initialize(attributes, parent_class)
|
5
|
+
@parent_class = parent_class
|
6
|
+
@attributes = attributes
|
7
|
+
|
8
|
+
attributes.each do |attribute|
|
9
|
+
evaluator_class.define_attribute(attribute.name, &attribute.to_proc)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def evaluator_class
|
14
|
+
@evaluator_class ||= Class.new(@parent_class).tap do |klass|
|
15
|
+
klass.attribute_lists ||= []
|
16
|
+
klass.attribute_lists += [@attributes]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
require 'active_support/core_ext/hash/keys'
|
2
|
+
require 'active_support/inflector'
|
3
|
+
|
4
|
+
module FactoryBot
|
5
|
+
# @api private
|
6
|
+
class Factory
|
7
|
+
attr_reader :name, :definition
|
8
|
+
|
9
|
+
def initialize(name, options = {})
|
10
|
+
assert_valid_options(options)
|
11
|
+
@name = name.respond_to?(:to_sym) ? name.to_sym : name.to_s.underscore.to_sym
|
12
|
+
@parent = options[:parent]
|
13
|
+
@aliases = options[:aliases] || []
|
14
|
+
@class_name = options[:class]
|
15
|
+
@definition = Definition.new(@name, options[:traits] || [])
|
16
|
+
@compiled = false
|
17
|
+
end
|
18
|
+
|
19
|
+
delegate :add_callback, :declare_attribute, :to_create, :define_trait, :constructor,
|
20
|
+
:defined_traits, :inherit_traits, :append_traits, to: :@definition
|
21
|
+
|
22
|
+
def build_class
|
23
|
+
@build_class ||= if class_name.is_a? Class
|
24
|
+
class_name
|
25
|
+
else
|
26
|
+
class_name.to_s.camelize.constantize
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def run(build_strategy, overrides, &block)
|
31
|
+
block ||= ->(result) { result }
|
32
|
+
compile
|
33
|
+
|
34
|
+
strategy = StrategyCalculator.new(build_strategy).strategy.new
|
35
|
+
|
36
|
+
evaluator = evaluator_class.new(strategy, overrides.symbolize_keys)
|
37
|
+
attribute_assigner = AttributeAssigner.new(evaluator, build_class, &compiled_constructor)
|
38
|
+
|
39
|
+
evaluation = Evaluation.new(attribute_assigner, compiled_to_create)
|
40
|
+
evaluation.add_observer(CallbacksObserver.new(callbacks, evaluator))
|
41
|
+
|
42
|
+
strategy.result(evaluation).tap(&block)
|
43
|
+
end
|
44
|
+
|
45
|
+
def human_names
|
46
|
+
names.map { |name| name.to_s.humanize.downcase }
|
47
|
+
end
|
48
|
+
|
49
|
+
def associations
|
50
|
+
evaluator_class.attribute_list.associations
|
51
|
+
end
|
52
|
+
|
53
|
+
# Names for this factory, including aliases.
|
54
|
+
#
|
55
|
+
# Example:
|
56
|
+
#
|
57
|
+
# factory :user, aliases: [:author] do
|
58
|
+
# # ...
|
59
|
+
# end
|
60
|
+
#
|
61
|
+
# FactoryBot.create(:author).class
|
62
|
+
# # => User
|
63
|
+
#
|
64
|
+
# Because an attribute defined without a value or block will build an
|
65
|
+
# association with the same name, this allows associations to be defined
|
66
|
+
# without factories, such as:
|
67
|
+
#
|
68
|
+
# factory :user, aliases: [:author] do
|
69
|
+
# # ...
|
70
|
+
# end
|
71
|
+
#
|
72
|
+
# factory :post do
|
73
|
+
# author
|
74
|
+
# end
|
75
|
+
#
|
76
|
+
# FactoryBot.create(:post).author.class
|
77
|
+
# # => User
|
78
|
+
def names
|
79
|
+
[name] + @aliases
|
80
|
+
end
|
81
|
+
|
82
|
+
def compile
|
83
|
+
unless @compiled
|
84
|
+
parent.compile
|
85
|
+
parent.defined_traits.each { |trait| define_trait(trait) }
|
86
|
+
@definition.compile
|
87
|
+
build_hierarchy
|
88
|
+
@compiled = true
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def with_traits(traits)
|
93
|
+
self.clone.tap do |factory_with_traits|
|
94
|
+
factory_with_traits.append_traits traits
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
protected
|
99
|
+
|
100
|
+
def class_name
|
101
|
+
@class_name || parent.class_name || name
|
102
|
+
end
|
103
|
+
|
104
|
+
def evaluator_class
|
105
|
+
@evaluator_class ||= EvaluatorClassDefiner.new(attributes, parent.evaluator_class).evaluator_class
|
106
|
+
end
|
107
|
+
|
108
|
+
def attributes
|
109
|
+
compile
|
110
|
+
AttributeList.new(@name).tap do |list|
|
111
|
+
list.apply_attributes definition.attributes
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def hierarchy_class
|
116
|
+
@hierarchy_class ||= Class.new(parent.hierarchy_class)
|
117
|
+
end
|
118
|
+
|
119
|
+
def hierarchy_instance
|
120
|
+
@hierarchy_instance ||= hierarchy_class.new
|
121
|
+
end
|
122
|
+
|
123
|
+
def build_hierarchy
|
124
|
+
hierarchy_class.build_from_definition definition
|
125
|
+
end
|
126
|
+
|
127
|
+
def callbacks
|
128
|
+
hierarchy_instance.callbacks
|
129
|
+
end
|
130
|
+
|
131
|
+
def compiled_to_create
|
132
|
+
hierarchy_instance.to_create
|
133
|
+
end
|
134
|
+
|
135
|
+
def compiled_constructor
|
136
|
+
hierarchy_instance.constructor
|
137
|
+
end
|
138
|
+
|
139
|
+
private
|
140
|
+
|
141
|
+
def assert_valid_options(options)
|
142
|
+
options.assert_valid_keys(:class, :parent, :aliases, :traits)
|
143
|
+
end
|
144
|
+
|
145
|
+
def parent
|
146
|
+
if @parent
|
147
|
+
FactoryBot.factory_by_name(@parent)
|
148
|
+
else
|
149
|
+
NullFactory.new
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def initialize_copy(source)
|
154
|
+
super
|
155
|
+
@definition = @definition.clone
|
156
|
+
@evaluator_class = nil
|
157
|
+
@hierarchy_class = nil
|
158
|
+
@hierarchy_instance = nil
|
159
|
+
@compiled = false
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|