factory_bot 4.10.0 → 6.0.0
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 +4 -4
- data/.yardopts +1 -0
- data/CONTRIBUTING.md +52 -13
- data/GETTING_STARTED.md +613 -182
- data/LICENSE +1 -1
- data/NEWS.md +358 -0
- data/README.md +30 -26
- data/lib/factory_bot.rb +71 -140
- data/lib/factory_bot/aliases.rb +2 -2
- data/lib/factory_bot/attribute.rb +4 -39
- data/lib/factory_bot/attribute/association.rb +2 -2
- data/lib/factory_bot/attribute/dynamic.rb +2 -1
- data/lib/factory_bot/attribute_assigner.rb +24 -10
- data/lib/factory_bot/attribute_list.rb +3 -2
- data/lib/factory_bot/callback.rb +3 -10
- data/lib/factory_bot/configuration.rb +15 -19
- data/lib/factory_bot/declaration.rb +5 -5
- data/lib/factory_bot/declaration/association.rb +14 -1
- data/lib/factory_bot/declaration/dynamic.rb +3 -1
- data/lib/factory_bot/declaration/implicit.rb +7 -2
- data/lib/factory_bot/declaration_list.rb +3 -3
- data/lib/factory_bot/decorator.rb +5 -5
- data/lib/factory_bot/decorator/attribute_hash.rb +1 -1
- data/lib/factory_bot/decorator/invocation_tracker.rb +1 -1
- data/lib/factory_bot/definition.rb +49 -20
- data/lib/factory_bot/definition_hierarchy.rb +1 -11
- data/lib/factory_bot/definition_proxy.rb +125 -43
- data/lib/factory_bot/enum.rb +27 -0
- data/lib/factory_bot/errors.rb +7 -4
- data/lib/factory_bot/evaluation.rb +1 -1
- data/lib/factory_bot/evaluator.rb +9 -11
- data/lib/factory_bot/evaluator_class_definer.rb +1 -1
- data/lib/factory_bot/factory.rb +12 -12
- data/lib/factory_bot/factory_runner.rb +4 -4
- data/lib/factory_bot/find_definitions.rb +2 -2
- data/lib/factory_bot/internal.rb +91 -0
- data/lib/factory_bot/linter.rb +41 -28
- data/lib/factory_bot/null_factory.rb +13 -4
- data/lib/factory_bot/null_object.rb +2 -6
- data/lib/factory_bot/registry.rb +17 -8
- data/lib/factory_bot/reload.rb +2 -3
- data/lib/factory_bot/sequence.rb +5 -6
- data/lib/factory_bot/strategy/stub.rb +37 -37
- data/lib/factory_bot/strategy_calculator.rb +1 -1
- data/lib/factory_bot/strategy_syntax_method_registrar.rb +13 -2
- data/lib/factory_bot/syntax.rb +2 -2
- data/lib/factory_bot/syntax/default.rb +12 -24
- data/lib/factory_bot/syntax/methods.rb +32 -9
- data/lib/factory_bot/trait.rb +7 -4
- data/lib/factory_bot/version.rb +1 -1
- metadata +50 -65
- data/.autotest +0 -9
- data/.gitignore +0 -10
- data/.rspec +0 -3
- data/.simplecov +0 -4
- data/.travis.yml +0 -58
- data/Appraisals +0 -23
- data/Gemfile +0 -8
- data/Gemfile.lock +0 -103
- data/NEWS +0 -298
- data/Rakefile +0 -36
- data/cucumber.yml +0 -1
- data/factory_bot.gemspec +0 -36
- data/factory_girl.gemspec +0 -40
- data/gemfiles/3.2.gemfile +0 -10
- data/gemfiles/3.2.gemfile.lock +0 -107
- data/gemfiles/4.0.gemfile +0 -10
- data/gemfiles/4.0.gemfile.lock +0 -107
- data/gemfiles/4.1.gemfile +0 -10
- data/gemfiles/4.1.gemfile.lock +0 -106
- data/gemfiles/4.2.gemfile +0 -10
- data/gemfiles/4.2.gemfile.lock +0 -106
- data/gemfiles/5.0.gemfile +0 -10
- data/gemfiles/5.0.gemfile.lock +0 -104
- data/gemfiles/5.1.gemfile +0 -10
- data/gemfiles/5.1.gemfile.lock +0 -104
- data/lib/factory_bot/attribute/static.rb +0 -16
- data/lib/factory_bot/declaration/static.rb +0 -26
- data/lib/factory_bot/decorator/class_key_hash.rb +0 -28
- data/lib/factory_girl.rb +0 -5
@@ -1,21 +1,25 @@
|
|
1
1
|
module FactoryBot
|
2
2
|
# @api private
|
3
3
|
class Configuration
|
4
|
-
attr_reader
|
5
|
-
|
6
|
-
|
4
|
+
attr_reader(
|
5
|
+
:callback_names,
|
6
|
+
:factories,
|
7
|
+
:inline_sequences,
|
8
|
+
:sequences,
|
9
|
+
:strategies,
|
10
|
+
:traits
|
11
|
+
)
|
7
12
|
|
8
13
|
def initialize
|
9
|
-
@factories
|
10
|
-
@sequences
|
11
|
-
@traits
|
12
|
-
@strategies
|
14
|
+
@factories = Decorator::DisallowsDuplicatesRegistry.new(Registry.new("Factory"))
|
15
|
+
@sequences = Decorator::DisallowsDuplicatesRegistry.new(Registry.new("Sequence"))
|
16
|
+
@traits = Decorator::DisallowsDuplicatesRegistry.new(Registry.new("Trait"))
|
17
|
+
@strategies = Registry.new("Strategy")
|
13
18
|
@callback_names = Set.new
|
14
|
-
@definition
|
15
|
-
|
16
|
-
@allow_class_lookup = true
|
19
|
+
@definition = Definition.new(:configuration)
|
20
|
+
@inline_sequences = []
|
17
21
|
|
18
|
-
to_create
|
22
|
+
to_create(&:save!)
|
19
23
|
initialize_with { new }
|
20
24
|
end
|
21
25
|
|
@@ -25,13 +29,5 @@ module FactoryBot
|
|
25
29
|
def initialize_with(&block)
|
26
30
|
@definition.define_constructor(&block)
|
27
31
|
end
|
28
|
-
|
29
|
-
def duplicate_attribute_assignment_from_initialize_with
|
30
|
-
false
|
31
|
-
end
|
32
|
-
|
33
|
-
def duplicate_attribute_assignment_from_initialize_with=(value)
|
34
|
-
ActiveSupport::Deprecation.warn 'Assignment of duplicate_attribute_assignment_from_initialize_with is unnecessary as this is now default behavior in FactoryBot 4.0; this line can be removed', caller
|
35
|
-
end
|
36
32
|
end
|
37
33
|
end
|
@@ -1,7 +1,6 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require 'factory_bot/declaration/implicit'
|
1
|
+
require "factory_bot/declaration/dynamic"
|
2
|
+
require "factory_bot/declaration/association"
|
3
|
+
require "factory_bot/declaration/implicit"
|
5
4
|
|
6
5
|
module FactoryBot
|
7
6
|
# @api private
|
@@ -9,7 +8,7 @@ module FactoryBot
|
|
9
8
|
attr_reader :name
|
10
9
|
|
11
10
|
def initialize(name, ignored = false)
|
12
|
-
@name
|
11
|
+
@name = name
|
13
12
|
@ignored = ignored
|
14
13
|
end
|
15
14
|
|
@@ -18,6 +17,7 @@ module FactoryBot
|
|
18
17
|
end
|
19
18
|
|
20
19
|
protected
|
20
|
+
|
21
21
|
attr_reader :ignored
|
22
22
|
end
|
23
23
|
end
|
@@ -10,19 +10,32 @@ module FactoryBot
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def ==(other)
|
13
|
-
|
13
|
+
self.class == other.class &&
|
14
|
+
name == other.name &&
|
14
15
|
options == other.options
|
15
16
|
end
|
16
17
|
|
17
18
|
protected
|
19
|
+
|
18
20
|
attr_reader :options
|
19
21
|
|
20
22
|
private
|
21
23
|
|
22
24
|
def build
|
25
|
+
ensure_factory_is_not_a_declaration!
|
26
|
+
|
23
27
|
factory_name = @overrides[:factory] || name
|
24
28
|
[Attribute::Association.new(name, factory_name, [@traits, @overrides.except(:factory)].flatten)]
|
25
29
|
end
|
30
|
+
|
31
|
+
def ensure_factory_is_not_a_declaration!
|
32
|
+
if @overrides[:factory].is_a?(Declaration)
|
33
|
+
raise ArgumentError.new(<<~MSG)
|
34
|
+
Association '#{name}' received an invalid factory argument.
|
35
|
+
Did you mean? 'factory: :#{@overrides[:factory].name}'
|
36
|
+
MSG
|
37
|
+
end
|
38
|
+
end
|
26
39
|
end
|
27
40
|
end
|
28
41
|
end
|
@@ -8,12 +8,14 @@ module FactoryBot
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def ==(other)
|
11
|
-
|
11
|
+
self.class == other.class &&
|
12
|
+
name == other.name &&
|
12
13
|
factory == other.factory &&
|
13
14
|
ignored == other.ignored
|
14
15
|
end
|
15
16
|
|
16
17
|
protected
|
18
|
+
|
17
19
|
attr_reader :factory
|
18
20
|
|
19
21
|
private
|
@@ -21,8 +23,11 @@ module FactoryBot
|
|
21
23
|
def build
|
22
24
|
if FactoryBot.factories.registered?(name)
|
23
25
|
[Attribute::Association.new(name, name, {})]
|
24
|
-
elsif FactoryBot.sequences.registered?(name)
|
26
|
+
elsif FactoryBot::Internal.sequences.registered?(name)
|
25
27
|
[Attribute::Sequence.new(name, name, @ignored)]
|
28
|
+
elsif @factory.name.to_s == name.to_s
|
29
|
+
message = "Self-referencing trait '#{@name}'"
|
30
|
+
raise TraitDefinitionError, message
|
26
31
|
else
|
27
32
|
@factory.inherit_traits([name])
|
28
33
|
[]
|
@@ -5,8 +5,8 @@ module FactoryBot
|
|
5
5
|
|
6
6
|
def initialize(name = nil)
|
7
7
|
@declarations = []
|
8
|
-
@name
|
9
|
-
@overridable
|
8
|
+
@name = name
|
9
|
+
@overridable = false
|
10
10
|
end
|
11
11
|
|
12
12
|
def declare_attribute(declaration)
|
@@ -39,7 +39,7 @@ module FactoryBot
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def to_attributes
|
42
|
-
@declarations.
|
42
|
+
@declarations.reduce([]) { |result, declaration| result + declaration.to_attributes }
|
43
43
|
end
|
44
44
|
|
45
45
|
def overridable?
|
@@ -6,16 +6,16 @@ module FactoryBot
|
|
6
6
|
@component = component
|
7
7
|
end
|
8
8
|
|
9
|
-
def method_missing(name, *args, &block)
|
9
|
+
def method_missing(name, *args, &block) # rubocop:disable Style/MethodMissingSuper
|
10
10
|
@component.send(name, *args, &block)
|
11
11
|
end
|
12
12
|
|
13
|
-
def
|
14
|
-
|
13
|
+
def respond_to_missing?(name, include_private = false)
|
14
|
+
@component.respond_to?(name, true) || super
|
15
15
|
end
|
16
16
|
|
17
|
-
def
|
18
|
-
|
17
|
+
def send(symbol, *args, &block)
|
18
|
+
__send__(symbol, *args, &block)
|
19
19
|
end
|
20
20
|
end
|
21
21
|
end
|
@@ -1,18 +1,20 @@
|
|
1
1
|
module FactoryBot
|
2
2
|
# @api private
|
3
3
|
class Definition
|
4
|
-
attr_reader :defined_traits, :declarations
|
5
|
-
|
6
|
-
def initialize(name
|
7
|
-
@
|
8
|
-
@
|
9
|
-
@
|
10
|
-
@
|
11
|
-
@
|
4
|
+
attr_reader :defined_traits, :declarations, :name, :registered_enums
|
5
|
+
|
6
|
+
def initialize(name, base_traits = [])
|
7
|
+
@name = name
|
8
|
+
@declarations = DeclarationList.new(name)
|
9
|
+
@callbacks = []
|
10
|
+
@defined_traits = Set.new
|
11
|
+
@registered_enums = []
|
12
|
+
@to_create = nil
|
13
|
+
@base_traits = base_traits
|
12
14
|
@additional_traits = []
|
13
|
-
@constructor
|
14
|
-
@attributes
|
15
|
-
@compiled
|
15
|
+
@constructor = nil
|
16
|
+
@attributes = nil
|
17
|
+
@compiled = false
|
16
18
|
end
|
17
19
|
|
18
20
|
delegate :declare_attribute, to: :declarations
|
@@ -42,13 +44,15 @@ module FactoryBot
|
|
42
44
|
aggregate_from_traits_and_self(:callbacks) { @callbacks }
|
43
45
|
end
|
44
46
|
|
45
|
-
def compile
|
47
|
+
def compile(klass = nil)
|
46
48
|
unless @compiled
|
49
|
+
expand_enum_traits(klass) unless klass.nil?
|
50
|
+
|
47
51
|
declarations.attributes
|
48
52
|
|
49
53
|
defined_traits.each do |defined_trait|
|
50
|
-
base_traits.each
|
51
|
-
additional_traits.each { |
|
54
|
+
base_traits.each { |bt| bt.define_trait defined_trait }
|
55
|
+
additional_traits.each { |at| at.define_trait defined_trait }
|
52
56
|
end
|
53
57
|
|
54
58
|
@compiled = true
|
@@ -73,13 +77,17 @@ module FactoryBot
|
|
73
77
|
end
|
74
78
|
|
75
79
|
def skip_create
|
76
|
-
@to_create = ->(instance) {
|
80
|
+
@to_create = ->(instance) {}
|
77
81
|
end
|
78
82
|
|
79
83
|
def define_trait(trait)
|
80
84
|
@defined_traits.add(trait)
|
81
85
|
end
|
82
86
|
|
87
|
+
def register_enum(enum)
|
88
|
+
@registered_enums << enum
|
89
|
+
end
|
90
|
+
|
83
91
|
def define_constructor(&block)
|
84
92
|
@constructor = block
|
85
93
|
end
|
@@ -94,7 +102,6 @@ module FactoryBot
|
|
94
102
|
|
95
103
|
def callback(*names, &block)
|
96
104
|
names.each do |name|
|
97
|
-
FactoryBot.register_callback(name)
|
98
105
|
add_callback(Callback.new(name, block))
|
99
106
|
end
|
100
107
|
end
|
@@ -110,17 +117,19 @@ module FactoryBot
|
|
110
117
|
end
|
111
118
|
|
112
119
|
def trait_by_name(name)
|
113
|
-
trait_for(name) ||
|
120
|
+
trait_for(name) || Internal.trait_by_name(name)
|
114
121
|
end
|
115
122
|
|
116
123
|
def trait_for(name)
|
117
|
-
defined_traits.
|
124
|
+
@defined_traits_by_name ||= defined_traits.each_with_object({}) { |t, memo| memo[t.name] ||= t }
|
125
|
+
@defined_traits_by_name[name.to_s]
|
118
126
|
end
|
119
127
|
|
120
128
|
def initialize_copy(source)
|
121
129
|
super
|
122
130
|
@attributes = nil
|
123
|
-
@compiled
|
131
|
+
@compiled = false
|
132
|
+
@defined_traits_by_name = nil
|
124
133
|
end
|
125
134
|
|
126
135
|
def aggregate_from_traits_and_self(method_name, &block)
|
@@ -129,8 +138,28 @@ module FactoryBot
|
|
129
138
|
[
|
130
139
|
base_traits.map(&method_name),
|
131
140
|
instance_exec(&block),
|
132
|
-
additional_traits.map(&method_name)
|
141
|
+
additional_traits.map(&method_name)
|
133
142
|
].flatten.compact
|
134
143
|
end
|
144
|
+
|
145
|
+
def expand_enum_traits(klass)
|
146
|
+
if automatically_register_defined_enums?(klass)
|
147
|
+
automatically_register_defined_enums(klass)
|
148
|
+
end
|
149
|
+
|
150
|
+
registered_enums.each do |enum|
|
151
|
+
traits = enum.build_traits(klass)
|
152
|
+
traits.each { |trait| define_trait(trait) }
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def automatically_register_defined_enums(klass)
|
157
|
+
klass.defined_enums.each_key { |name| register_enum(Enum.new(name)) }
|
158
|
+
end
|
159
|
+
|
160
|
+
def automatically_register_defined_enums?(klass)
|
161
|
+
FactoryBot.automatically_define_enum_traits &&
|
162
|
+
klass.respond_to?(:defined_enums)
|
163
|
+
end
|
135
164
|
end
|
136
165
|
end
|
@@ -1,16 +1,6 @@
|
|
1
1
|
module FactoryBot
|
2
2
|
class DefinitionHierarchy
|
3
|
-
|
4
|
-
FactoryBot.callbacks
|
5
|
-
end
|
6
|
-
|
7
|
-
def constructor
|
8
|
-
FactoryBot.constructor
|
9
|
-
end
|
10
|
-
|
11
|
-
def to_create
|
12
|
-
FactoryBot.to_create
|
13
|
-
end
|
3
|
+
delegate :callbacks, :constructor, :to_create, to: Internal
|
14
4
|
|
15
5
|
def self.build_from_definition(definition)
|
16
6
|
build_to_create(&definition.to_create)
|
@@ -1,6 +1,19 @@
|
|
1
1
|
module FactoryBot
|
2
2
|
class DefinitionProxy
|
3
|
-
UNPROXIED_METHODS = %w
|
3
|
+
UNPROXIED_METHODS = %w[
|
4
|
+
__send__
|
5
|
+
__id__
|
6
|
+
nil?
|
7
|
+
send
|
8
|
+
object_id
|
9
|
+
extend
|
10
|
+
instance_eval
|
11
|
+
initialize
|
12
|
+
block_given?
|
13
|
+
raise
|
14
|
+
caller
|
15
|
+
method
|
16
|
+
].freeze
|
4
17
|
|
5
18
|
(instance_methods + private_instance_methods).each do |method|
|
6
19
|
undef_method(method) unless UNPROXIED_METHODS.include?(method.to_s)
|
@@ -11,8 +24,8 @@ module FactoryBot
|
|
11
24
|
attr_reader :child_factories
|
12
25
|
|
13
26
|
def initialize(definition, ignore = false)
|
14
|
-
@definition
|
15
|
-
@ignore
|
27
|
+
@definition = definition
|
28
|
+
@ignore = ignore
|
16
29
|
@child_factories = []
|
17
30
|
end
|
18
31
|
|
@@ -21,42 +34,21 @@ module FactoryBot
|
|
21
34
|
raise FactoryBot::MethodDefinitionError, message
|
22
35
|
end
|
23
36
|
|
24
|
-
# Adds an attribute
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
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
|
37
|
+
# Adds an attribute to the factory.
|
38
|
+
# The attribute value will be generated "lazily"
|
39
|
+
# by calling the block whenever an instance is generated.
|
40
|
+
# The block will not be called if the
|
30
41
|
# attribute is overridden for a specific instance.
|
31
42
|
#
|
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
43
|
# Arguments:
|
37
44
|
# * name: +Symbol+ or +String+
|
38
45
|
# The name of this attribute. This will be assigned using "name=" for
|
39
46
|
# generated instances.
|
40
|
-
|
41
|
-
|
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
|
-
|
47
|
+
def add_attribute(name, &block)
|
48
|
+
declaration = Declaration::Dynamic.new(name, @ignore, block)
|
51
49
|
@definition.declare_attribute(declaration)
|
52
50
|
end
|
53
51
|
|
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
52
|
def transient(&block)
|
61
53
|
proxy = DefinitionProxy.new(@definition, true)
|
62
54
|
proxy.instance_eval(&block)
|
@@ -66,40 +58,48 @@ module FactoryBot
|
|
66
58
|
# attribute, so that:
|
67
59
|
#
|
68
60
|
# factory :user do
|
69
|
-
# name 'Billy Idol'
|
61
|
+
# name { 'Billy Idol' }
|
70
62
|
# end
|
71
63
|
#
|
72
64
|
# and:
|
73
65
|
#
|
74
66
|
# factory :user do
|
75
|
-
# add_attribute
|
67
|
+
# add_attribute(:name) { 'Billy Idol' }
|
76
68
|
# end
|
77
69
|
#
|
78
70
|
# are equivalent.
|
79
71
|
#
|
80
|
-
# If no argument or block is given, factory_bot will look for
|
81
|
-
#
|
72
|
+
# If no argument or block is given, factory_bot will first look for an
|
73
|
+
# association, then for a sequence, and finally for a trait with the same
|
74
|
+
# name. This means that given an "admin" trait, an "email" sequence, and an
|
75
|
+
# "account" factory:
|
82
76
|
#
|
83
|
-
# factory :user do
|
84
|
-
# email {
|
77
|
+
# factory :user, traits: [:admin] do
|
78
|
+
# email { generate(:email) }
|
85
79
|
# association :account
|
86
80
|
# end
|
87
81
|
#
|
88
82
|
# and:
|
89
83
|
#
|
90
84
|
# factory :user do
|
85
|
+
# admin
|
91
86
|
# email
|
92
87
|
# account
|
93
88
|
# end
|
94
89
|
#
|
95
90
|
# are equivalent.
|
96
|
-
def method_missing(name, *args, &block)
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
91
|
+
def method_missing(name, *args, &block) # rubocop:disable Style/MissingRespondToMissing, Style/MethodMissingSuper
|
92
|
+
association_options = args.first
|
93
|
+
|
94
|
+
if association_options.nil?
|
95
|
+
__declare_attribute__(name, block)
|
96
|
+
elsif __valid_association_options?(association_options)
|
97
|
+
association(name, association_options)
|
101
98
|
else
|
102
|
-
|
99
|
+
raise NoMethodError.new(<<~MSG)
|
100
|
+
undefined method '#{name}' in '#{@definition.name}' factory
|
101
|
+
Did you mean? '#{name} { #{association_options.inspect} }'
|
102
|
+
MSG
|
103
103
|
end
|
104
104
|
end
|
105
105
|
|
@@ -121,6 +121,7 @@ module FactoryBot
|
|
121
121
|
# Except that no globally available sequence will be defined.
|
122
122
|
def sequence(name, *args, &block)
|
123
123
|
sequence = Sequence.new(name, *args, &block)
|
124
|
+
FactoryBot::Internal.register_inline_sequence(sequence)
|
124
125
|
add_attribute(name) { increment_sequence(sequence) }
|
125
126
|
end
|
126
127
|
|
@@ -148,7 +149,15 @@ module FactoryBot
|
|
148
149
|
# name of the factory. For example, a "user" association will by
|
149
150
|
# default use the "user" factory.
|
150
151
|
def association(name, *options)
|
151
|
-
|
152
|
+
if block_given?
|
153
|
+
raise AssociationDefinitionError.new(
|
154
|
+
"Unexpected block passed to '#{name}' association "\
|
155
|
+
"in '#{@definition.name}' factory"
|
156
|
+
)
|
157
|
+
else
|
158
|
+
declaration = Declaration::Association.new(name, *options)
|
159
|
+
@definition.declare_attribute(declaration)
|
160
|
+
end
|
152
161
|
end
|
153
162
|
|
154
163
|
def to_create(&block)
|
@@ -167,8 +176,81 @@ module FactoryBot
|
|
167
176
|
@definition.define_trait(Trait.new(name, &block))
|
168
177
|
end
|
169
178
|
|
179
|
+
# Creates traits for enumerable values.
|
180
|
+
#
|
181
|
+
# Example:
|
182
|
+
# factory :task do
|
183
|
+
# traits_for_enum :status, [:started, :finished]
|
184
|
+
# end
|
185
|
+
#
|
186
|
+
# Equivalent to:
|
187
|
+
# factory :task do
|
188
|
+
# trait :started do
|
189
|
+
# status { :started }
|
190
|
+
# end
|
191
|
+
#
|
192
|
+
# trait :finished do
|
193
|
+
# status { :finished }
|
194
|
+
# end
|
195
|
+
# end
|
196
|
+
#
|
197
|
+
# Example:
|
198
|
+
# factory :task do
|
199
|
+
# traits_for_enum :status, {started: 1, finished: 2}
|
200
|
+
# end
|
201
|
+
#
|
202
|
+
# Example:
|
203
|
+
# class Task
|
204
|
+
# def statuses
|
205
|
+
# {started: 1, finished: 2}
|
206
|
+
# end
|
207
|
+
# end
|
208
|
+
#
|
209
|
+
# factory :task do
|
210
|
+
# traits_for_enum :status
|
211
|
+
# end
|
212
|
+
#
|
213
|
+
# Both equivalent to:
|
214
|
+
# factory :task do
|
215
|
+
# trait :started do
|
216
|
+
# status { 1 }
|
217
|
+
# end
|
218
|
+
#
|
219
|
+
# trait :finished do
|
220
|
+
# status { 2 }
|
221
|
+
# end
|
222
|
+
# end
|
223
|
+
#
|
224
|
+
#
|
225
|
+
# Arguments:
|
226
|
+
# attribute_name: +Symbol+ or +String+
|
227
|
+
# the name of the attribute these traits will set the value of
|
228
|
+
# values: +Array+, +Hash+, or other +Enumerable+
|
229
|
+
# An array of trait names, or a mapping of trait names to values for
|
230
|
+
# those traits. When this argument is not provided, factory_bot will
|
231
|
+
# attempt to get the values by calling the pluralized `attribute_name`
|
232
|
+
# class method.
|
233
|
+
def traits_for_enum(attribute_name, values = nil)
|
234
|
+
@definition.register_enum(Enum.new(attribute_name, values))
|
235
|
+
end
|
236
|
+
|
170
237
|
def initialize_with(&block)
|
171
238
|
@definition.define_constructor(&block)
|
172
239
|
end
|
240
|
+
|
241
|
+
private
|
242
|
+
|
243
|
+
def __declare_attribute__(name, block)
|
244
|
+
if block.nil?
|
245
|
+
declaration = Declaration::Implicit.new(name, @definition, @ignore)
|
246
|
+
@definition.declare_attribute(declaration)
|
247
|
+
else
|
248
|
+
add_attribute(name, &block)
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
def __valid_association_options?(options)
|
253
|
+
options.respond_to?(:has_key?) && options.has_key?(:factory)
|
254
|
+
end
|
173
255
|
end
|
174
256
|
end
|