factory_bot 4.11.1 → 6.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +58 -13
  3. data/GETTING_STARTED.md +785 -153
  4. data/LICENSE +1 -1
  5. data/NEWS.md +379 -0
  6. data/README.md +20 -30
  7. data/lib/factory_bot/aliases.rb +2 -2
  8. data/lib/factory_bot/attribute/association.rb +2 -2
  9. data/lib/factory_bot/attribute/dynamic.rb +3 -2
  10. data/lib/factory_bot/attribute.rb +4 -39
  11. data/lib/factory_bot/attribute_assigner.rb +24 -10
  12. data/lib/factory_bot/attribute_list.rb +3 -2
  13. data/lib/factory_bot/callback.rb +4 -11
  14. data/lib/factory_bot/configuration.rb +15 -19
  15. data/lib/factory_bot/declaration/association.rb +33 -3
  16. data/lib/factory_bot/declaration/dynamic.rb +3 -1
  17. data/lib/factory_bot/declaration/implicit.rb +7 -2
  18. data/lib/factory_bot/declaration.rb +5 -5
  19. data/lib/factory_bot/declaration_list.rb +3 -3
  20. data/lib/factory_bot/decorator/attribute_hash.rb +1 -1
  21. data/lib/factory_bot/decorator/invocation_tracker.rb +2 -1
  22. data/lib/factory_bot/decorator.rb +20 -4
  23. data/lib/factory_bot/definition.rb +69 -21
  24. data/lib/factory_bot/definition_hierarchy.rb +1 -11
  25. data/lib/factory_bot/definition_proxy.rb +119 -64
  26. data/lib/factory_bot/enum.rb +27 -0
  27. data/lib/factory_bot/errors.rb +7 -4
  28. data/lib/factory_bot/evaluation.rb +1 -1
  29. data/lib/factory_bot/evaluator.rb +10 -11
  30. data/lib/factory_bot/evaluator_class_definer.rb +1 -1
  31. data/lib/factory_bot/factory.rb +12 -12
  32. data/lib/factory_bot/factory_runner.rb +4 -4
  33. data/lib/factory_bot/find_definitions.rb +2 -2
  34. data/lib/factory_bot/internal.rb +91 -0
  35. data/lib/factory_bot/linter.rb +41 -28
  36. data/lib/factory_bot/null_factory.rb +13 -4
  37. data/lib/factory_bot/null_object.rb +2 -6
  38. data/lib/factory_bot/registry.rb +17 -8
  39. data/lib/factory_bot/reload.rb +2 -3
  40. data/lib/factory_bot/sequence.rb +5 -6
  41. data/lib/factory_bot/strategy/stub.rb +37 -32
  42. data/lib/factory_bot/strategy_calculator.rb +1 -1
  43. data/lib/factory_bot/strategy_syntax_method_registrar.rb +13 -2
  44. data/lib/factory_bot/syntax/default.rb +13 -25
  45. data/lib/factory_bot/syntax/methods.rb +32 -9
  46. data/lib/factory_bot/syntax.rb +2 -2
  47. data/lib/factory_bot/trait.rb +7 -4
  48. data/lib/factory_bot/version.rb +1 -1
  49. data/lib/factory_bot.rb +71 -140
  50. metadata +46 -34
  51. data/NEWS +0 -306
  52. data/lib/factory_bot/attribute/static.rb +0 -16
  53. data/lib/factory_bot/declaration/static.rb +0 -26
  54. data/lib/factory_bot/decorator/class_key_hash.rb +0 -28
@@ -1,6 +1,19 @@
1
1
  module FactoryBot
2
2
  class DefinitionProxy
3
- UNPROXIED_METHODS = %w(__send__ __id__ nil? send object_id extend instance_eval initialize block_given? raise caller method)
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 = definition
15
- @ignore = ignore
27
+ @definition = definition
28
+ @ignore = ignore
16
29
  @child_factories = []
17
30
  end
18
31
 
@@ -21,43 +34,21 @@ module FactoryBot
21
34
  raise FactoryBot::MethodDefinitionError, message
22
35
  end
23
36
 
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
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
- # * 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
- warn_static_attribute_deprecation(name, value)
49
- Declaration::Static.new(name, value, @ignore)
50
- end
51
-
47
+ def add_attribute(name, &block)
48
+ declaration = Declaration::Dynamic.new(name, @ignore, block)
52
49
  @definition.declare_attribute(declaration)
53
50
  end
54
51
 
55
- def ignore(&block)
56
- ActiveSupport::Deprecation.warn "`#ignore` is deprecated and will be "\
57
- "removed in 5.0. Please use `#transient` instead."
58
- transient(&block)
59
- end
60
-
61
52
  def transient(&block)
62
53
  proxy = DefinitionProxy.new(@definition, true)
63
54
  proxy.instance_eval(&block)
@@ -67,40 +58,48 @@ module FactoryBot
67
58
  # attribute, so that:
68
59
  #
69
60
  # factory :user do
70
- # name 'Billy Idol'
61
+ # name { 'Billy Idol' }
71
62
  # end
72
63
  #
73
64
  # and:
74
65
  #
75
66
  # factory :user do
76
- # add_attribute :name, 'Billy Idol'
67
+ # add_attribute(:name) { 'Billy Idol' }
77
68
  # end
78
69
  #
79
70
  # are equivalent.
80
71
  #
81
- # If no argument or block is given, factory_bot will look for a sequence
82
- # or association with the same name. This means that:
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:
83
76
  #
84
- # factory :user do
85
- # email { create(:email) }
77
+ # factory :user, traits: [:admin] do
78
+ # email { generate(:email) }
86
79
  # association :account
87
80
  # end
88
81
  #
89
82
  # and:
90
83
  #
91
84
  # factory :user do
85
+ # admin
92
86
  # email
93
87
  # account
94
88
  # end
95
89
  #
96
90
  # are equivalent.
97
- def method_missing(name, *args, &block)
98
- if args.empty? && block.nil?
99
- @definition.declare_attribute(Declaration::Implicit.new(name, @definition, @ignore))
100
- elsif args.first.respond_to?(:has_key?) && args.first.has_key?(:factory)
101
- association(name, *args)
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)
102
98
  else
103
- add_attribute(name, *args, &block)
99
+ raise NoMethodError.new(<<~MSG)
100
+ undefined method '#{name}' in '#{@definition.name}' factory
101
+ Did you mean? '#{name} { #{association_options.inspect} }'
102
+ MSG
104
103
  end
105
104
  end
106
105
 
@@ -122,6 +121,7 @@ module FactoryBot
122
121
  # Except that no globally available sequence will be defined.
123
122
  def sequence(name, *args, &block)
124
123
  sequence = Sequence.new(name, *args, &block)
124
+ FactoryBot::Internal.register_inline_sequence(sequence)
125
125
  add_attribute(name) { increment_sequence(sequence) }
126
126
  end
127
127
 
@@ -149,7 +149,15 @@ module FactoryBot
149
149
  # name of the factory. For example, a "user" association will by
150
150
  # default use the "user" factory.
151
151
  def association(name, *options)
152
- @definition.declare_attribute(Declaration::Association.new(name, *options))
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
153
161
  end
154
162
 
155
163
  def to_create(&block)
@@ -168,34 +176,81 @@ module FactoryBot
168
176
  @definition.define_trait(Trait.new(name, &block))
169
177
  end
170
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
+
171
237
  def initialize_with(&block)
172
238
  @definition.define_constructor(&block)
173
239
  end
174
240
 
175
241
  private
176
242
 
177
- def warn_static_attribute_deprecation(name, value)
178
- attribute_caller = caller(2)
179
-
180
- if attribute_caller[0].include?("method_missing")
181
- attribute_caller = caller(3)
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)
182
249
  end
250
+ end
183
251
 
184
- ActiveSupport::Deprecation.warn(<<-MSG, attribute_caller)
185
- Static attributes will be removed in FactoryBot 5.0. Please use dynamic
186
- attributes instead by wrapping the attribute value in a block:
187
-
188
- #{name} { #{value.inspect} }
189
-
190
- To automatically update from static attributes to dynamic ones,
191
- install rubocop-rspec and run:
192
-
193
- rubocop \\
194
- --require rubocop-rspec \\
195
- --only FactoryBot/AttributeDefinedStatically \\
196
- --auto-correct
197
-
198
- MSG
252
+ def __valid_association_options?(options)
253
+ options.respond_to?(:has_key?) && options.has_key?(:factory)
199
254
  end
200
255
  end
201
256
  end
@@ -0,0 +1,27 @@
1
+ module FactoryBot
2
+ # @api private
3
+ class Enum
4
+ def initialize(attribute_name, values = nil)
5
+ @attribute_name = attribute_name
6
+ @values = values
7
+ end
8
+
9
+ def build_traits(klass)
10
+ enum_values(klass).map do |trait_name, value|
11
+ build_trait(trait_name, @attribute_name, value || trait_name)
12
+ end
13
+ end
14
+
15
+ private
16
+
17
+ def enum_values(klass)
18
+ @values || klass.send(@attribute_name.to_s.pluralize)
19
+ end
20
+
21
+ def build_trait(trait_name, attribute_name, value)
22
+ Trait.new(trait_name) do
23
+ add_attribute(attribute_name) { value }
24
+ end
25
+ end
26
+ end
27
+ end
@@ -2,6 +2,9 @@ module FactoryBot
2
2
  # Raised when a factory is defined that attempts to instantiate itself.
3
3
  class AssociationDefinitionError < RuntimeError; end
4
4
 
5
+ # Raised when a trait is defined that references itself.
6
+ class TraitDefinitionError < RuntimeError; end
7
+
5
8
  # Raised when a callback is defined that has an invalid name
6
9
  class InvalidCallbackNameError < RuntimeError; end
7
10
 
@@ -11,12 +14,12 @@ module FactoryBot
11
14
  # Raised when attempting to register a sequence from a dynamic attribute block
12
15
  class SequenceAbuseError < RuntimeError; end
13
16
 
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
17
+ # Raised when defining an attribute twice in the same factory
18
18
  class AttributeDefinitionError < RuntimeError; end
19
19
 
20
+ # Raised when attempting to pass a block to an association definition
21
+ class AssociationDefinitionError < RuntimeError; end
22
+
20
23
  # Raised when a method is defined in a factory or trait with arguments
21
24
  class MethodDefinitionError < RuntimeError; end
22
25
 
@@ -1,4 +1,4 @@
1
- require 'observer'
1
+ require "observer"
2
2
 
3
3
  module FactoryBot
4
4
  class Evaluation
@@ -1,5 +1,5 @@
1
- require 'active_support/core_ext/hash/except'
2
- require 'active_support/core_ext/class/attribute'
1
+ require "active_support/core_ext/hash/except"
2
+ require "active_support/core_ext/class/attribute"
3
3
 
4
4
  module FactoryBot
5
5
  # @api private
@@ -7,7 +7,7 @@ module FactoryBot
7
7
  class_attribute :attribute_lists
8
8
 
9
9
  private_instance_methods.each do |method|
10
- undef_method(method) unless method =~ /^__|initialize/
10
+ undef_method(method) unless method.match?(/^__|initialize/)
11
11
  end
12
12
 
13
13
  def initialize(build_strategy, overrides = {})
@@ -23,9 +23,9 @@ module FactoryBot
23
23
 
24
24
  def association(factory_name, *traits_and_overrides)
25
25
  overrides = traits_and_overrides.extract_options!
26
- strategy_override = overrides.fetch(:strategy) do
26
+ strategy_override = overrides.fetch(:strategy) {
27
27
  FactoryBot.use_parent_strategy ? @build_strategy.class : :create
28
- end
28
+ }
29
29
 
30
30
  traits_and_overrides += [overrides.except(:strategy)]
31
31
 
@@ -33,19 +33,18 @@ module FactoryBot
33
33
  @build_strategy.association(runner)
34
34
  end
35
35
 
36
- def instance=(object_instance)
37
- @instance = object_instance
38
- end
36
+ attr_accessor :instance
39
37
 
40
- def method_missing(method_name, *args, &block)
38
+ def method_missing(method_name, *args, &block) # rubocop:disable Style/MethodMissingSuper, Style/MissingRespondToMissing
41
39
  if @instance.respond_to?(method_name)
42
40
  @instance.send(method_name, *args, &block)
43
41
  else
44
42
  SyntaxRunner.new.send(method_name, *args, &block)
45
43
  end
46
44
  end
45
+ ruby2_keywords :method_missing if respond_to?(:ruby2_keywords, true)
47
46
 
48
- def respond_to_missing?(method_name, include_private = false)
47
+ def respond_to_missing?(method_name, _include_private = false)
49
48
  @instance.respond_to?(method_name) || SyntaxRunner.new.respond_to?(method_name)
50
49
  end
51
50
 
@@ -66,7 +65,7 @@ module FactoryBot
66
65
  end
67
66
 
68
67
  def self.define_attribute(name, &block)
69
- if method_defined?(name) || private_method_defined?(name)
68
+ if instance_methods(false).include?(name) || private_instance_methods(false).include?(name)
70
69
  undef_method(name)
71
70
  end
72
71
 
@@ -3,7 +3,7 @@ module FactoryBot
3
3
  class EvaluatorClassDefiner
4
4
  def initialize(attributes, parent_class)
5
5
  @parent_class = parent_class
6
- @attributes = attributes
6
+ @attributes = attributes
7
7
 
8
8
  attributes.each do |attribute|
9
9
  evaluator_class.define_attribute(attribute.name, &attribute.to_proc)
@@ -1,5 +1,5 @@
1
- require 'active_support/core_ext/hash/keys'
2
- require 'active_support/inflector'
1
+ require "active_support/core_ext/hash/keys"
2
+ require "active_support/inflector"
3
3
 
4
4
  module FactoryBot
5
5
  # @api private
@@ -8,16 +8,16 @@ module FactoryBot
8
8
 
9
9
  def initialize(name, options = {})
10
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
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
17
  end
18
18
 
19
19
  delegate :add_callback, :declare_attribute, :to_create, :define_trait, :constructor,
20
- :defined_traits, :inherit_traits, :append_traits, to: :@definition
20
+ :defined_traits, :inherit_traits, :append_traits, to: :@definition
21
21
 
22
22
  def build_class
23
23
  @build_class ||= if class_name.is_a? Class
@@ -84,14 +84,14 @@ module FactoryBot
84
84
  unless @compiled
85
85
  parent.compile
86
86
  parent.defined_traits.each { |trait| define_trait(trait) }
87
- @definition.compile
87
+ @definition.compile(build_class)
88
88
  build_hierarchy
89
89
  @compiled = true
90
90
  end
91
91
  end
92
92
 
93
93
  def with_traits(traits)
94
- self.clone.tap do |factory_with_traits|
94
+ clone.tap do |factory_with_traits|
95
95
  factory_with_traits.append_traits traits
96
96
  end
97
97
  end
@@ -145,7 +145,7 @@ module FactoryBot
145
145
 
146
146
  def parent
147
147
  if @parent
148
- FactoryBot.factory_by_name(@parent)
148
+ FactoryBot::Internal.factory_by_name(@parent)
149
149
  else
150
150
  NullFactory.new
151
151
  end
@@ -1,15 +1,15 @@
1
1
  module FactoryBot
2
2
  class FactoryRunner
3
3
  def initialize(name, strategy, traits_and_overrides)
4
- @name = name
4
+ @name = name
5
5
  @strategy = strategy
6
6
 
7
7
  @overrides = traits_and_overrides.extract_options!
8
- @traits = traits_and_overrides
8
+ @traits = traits_and_overrides
9
9
  end
10
10
 
11
11
  def run(runner_strategy = @strategy, &block)
12
- factory = FactoryBot.factory_by_name(@name)
12
+ factory = FactoryBot::Internal.factory_by_name(@name)
13
13
 
14
14
  factory.compile
15
15
 
@@ -25,7 +25,7 @@ module FactoryBot
25
25
  factory: factory
26
26
  }
27
27
 
28
- ActiveSupport::Notifications.instrument('factory_bot.run_factory', instrumentation_payload) do
28
+ ActiveSupport::Notifications.instrument("factory_bot.run_factory", instrumentation_payload) do
29
29
  factory.run(runner_strategy, @overrides, &block)
30
30
  end
31
31
  end
@@ -7,7 +7,7 @@ module FactoryBot
7
7
  attr_accessor :definition_file_paths
8
8
  end
9
9
 
10
- self.definition_file_paths = %w(factories test/factories spec/factories)
10
+ self.definition_file_paths = %w[factories test/factories spec/factories]
11
11
 
12
12
  def self.find_definitions
13
13
  absolute_definition_file_paths = definition_file_paths.map { |path| File.expand_path(path) }
@@ -16,7 +16,7 @@ module FactoryBot
16
16
  load("#{path}.rb") if File.exist?("#{path}.rb")
17
17
 
18
18
  if File.directory? path
19
- Dir[File.join(path, '**', '*.rb')].sort.each do |file|
19
+ Dir[File.join(path, "**", "*.rb")].sort.each do |file|
20
20
  load file
21
21
  end
22
22
  end
@@ -0,0 +1,91 @@
1
+ module FactoryBot
2
+ # @api private
3
+ module Internal
4
+ class << self
5
+ delegate :after,
6
+ :before,
7
+ :callbacks,
8
+ :constructor,
9
+ :factories,
10
+ :initialize_with,
11
+ :inline_sequences,
12
+ :sequences,
13
+ :skip_create,
14
+ :strategies,
15
+ :to_create,
16
+ :traits,
17
+ to: :configuration
18
+
19
+ def configuration
20
+ @configuration ||= Configuration.new
21
+ end
22
+
23
+ def reset_configuration
24
+ @configuration = nil
25
+ end
26
+
27
+ def register_inline_sequence(sequence)
28
+ inline_sequences.push(sequence)
29
+ end
30
+
31
+ def rewind_inline_sequences
32
+ inline_sequences.each(&:rewind)
33
+ end
34
+
35
+ def register_trait(trait)
36
+ trait.names.each do |name|
37
+ traits.register(name, trait)
38
+ end
39
+ trait
40
+ end
41
+
42
+ def trait_by_name(name)
43
+ traits.find(name)
44
+ end
45
+
46
+ def register_sequence(sequence)
47
+ sequence.names.each do |name|
48
+ sequences.register(name, sequence)
49
+ end
50
+ sequence
51
+ end
52
+
53
+ def sequence_by_name(name)
54
+ sequences.find(name)
55
+ end
56
+
57
+ def rewind_sequences
58
+ sequences.each(&:rewind)
59
+ rewind_inline_sequences
60
+ end
61
+
62
+ def register_factory(factory)
63
+ factory.names.each do |name|
64
+ factories.register(name, factory)
65
+ end
66
+ factory
67
+ end
68
+
69
+ def factory_by_name(name)
70
+ factories.find(name)
71
+ end
72
+
73
+ def register_strategy(strategy_name, strategy_class)
74
+ strategies.register(strategy_name, strategy_class)
75
+ StrategySyntaxMethodRegistrar.new(strategy_name).define_strategy_methods
76
+ end
77
+
78
+ def strategy_by_name(name)
79
+ strategies.find(name)
80
+ end
81
+
82
+ def register_default_strategies
83
+ register_strategy(:build, FactoryBot::Strategy::Build)
84
+ register_strategy(:create, FactoryBot::Strategy::Create)
85
+ register_strategy(:attributes_for, FactoryBot::Strategy::AttributesFor)
86
+ register_strategy(:build_stubbed, FactoryBot::Strategy::Stub)
87
+ register_strategy(:null, FactoryBot::Strategy::Null)
88
+ end
89
+ end
90
+ end
91
+ end