factory_bot 5.0.2 → 6.2.1

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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +58 -13
  3. data/GETTING_STARTED.md +745 -149
  4. data/NEWS.md +53 -0
  5. data/README.md +19 -18
  6. data/lib/factory_bot/aliases.rb +4 -4
  7. data/lib/factory_bot/attribute/association.rb +2 -2
  8. data/lib/factory_bot/attribute/dynamic.rb +3 -2
  9. data/lib/factory_bot/attribute_assigner.rb +10 -10
  10. data/lib/factory_bot/attribute_list.rb +1 -1
  11. data/lib/factory_bot/callback.rb +3 -11
  12. data/lib/factory_bot/configuration.rb +6 -6
  13. data/lib/factory_bot/declaration/association.rb +30 -2
  14. data/lib/factory_bot/declaration/implicit.rb +4 -1
  15. data/lib/factory_bot/declaration.rb +1 -1
  16. data/lib/factory_bot/declaration_list.rb +2 -2
  17. data/lib/factory_bot/decorator/invocation_tracker.rb +2 -1
  18. data/lib/factory_bot/decorator.rb +18 -6
  19. data/lib/factory_bot/definition.rb +66 -19
  20. data/lib/factory_bot/definition_hierarchy.rb +1 -11
  21. data/lib/factory_bot/definition_proxy.rb +77 -12
  22. data/lib/factory_bot/enum.rb +27 -0
  23. data/lib/factory_bot/errors.rb +3 -0
  24. data/lib/factory_bot/evaluator.rb +8 -9
  25. data/lib/factory_bot/evaluator_class_definer.rb +1 -1
  26. data/lib/factory_bot/factory.rb +13 -13
  27. data/lib/factory_bot/factory_runner.rb +4 -4
  28. data/lib/factory_bot/find_definitions.rb +1 -1
  29. data/lib/factory_bot/internal.rb +68 -1
  30. data/lib/factory_bot/linter.rb +9 -13
  31. data/lib/factory_bot/null_factory.rb +10 -4
  32. data/lib/factory_bot/null_object.rb +2 -6
  33. data/lib/factory_bot/registry.rb +4 -4
  34. data/lib/factory_bot/reload.rb +1 -2
  35. data/lib/factory_bot/sequence.rb +5 -5
  36. data/lib/factory_bot/strategy/attributes_for.rb +4 -0
  37. data/lib/factory_bot/strategy/build.rb +4 -0
  38. data/lib/factory_bot/strategy/create.rb +4 -0
  39. data/lib/factory_bot/strategy/null.rb +8 -2
  40. data/lib/factory_bot/strategy/stub.rb +20 -5
  41. data/lib/factory_bot/strategy_calculator.rb +1 -1
  42. data/lib/factory_bot/strategy_syntax_method_registrar.rb +12 -1
  43. data/lib/factory_bot/syntax/default.rb +12 -24
  44. data/lib/factory_bot/syntax/methods.rb +3 -3
  45. data/lib/factory_bot/trait.rb +5 -3
  46. data/lib/factory_bot/version.rb +1 -1
  47. data/lib/factory_bot.rb +21 -93
  48. metadata +12 -39
data/GETTING_STARTED.md CHANGED
@@ -1,8 +1,91 @@
1
1
  Getting Started
2
2
  ===============
3
3
 
4
- Update Your Gemfile
5
- -------------------
4
+ * [Setup](#setup)
5
+ + [Update Your Gemfile](#update-your-gemfile)
6
+ + [Configure your test suite](#configure-your-test-suite)
7
+ - [RSpec](#rspec)
8
+ - [Test::Unit](#testunit)
9
+ - [Cucumber](#cucumber)
10
+ - [Spinach](#spinach)
11
+ - [Minitest](#minitest)
12
+ - [Minitest::Spec](#minitestspec)
13
+ - [minitest-rails](#minitest-rails)
14
+ * [Defining factories](#defining-factories)
15
+ + [Factory name and attributes](#factory-name-and-attributes)
16
+ + [Specifying the class explicitly](#specifying-the-class-explicitly)
17
+ + [Hash attributes](#hash-attributes)
18
+ + [Best practices](#best-practices)
19
+ + [Definition file paths](#definition-file-paths)
20
+ + [Static Attributes](#static-attributes)
21
+ * [Using factories](#using-factories)
22
+ + [Build strategies](#build-strategies)
23
+ + [Attribute overrides](#attribute-overrides)
24
+ + [`build_stubbed` and `Marshal.dump`](#build_stubbed-and-marshaldump)
25
+ * [Aliases](#aliases)
26
+ * [Dependent Attributes](#dependent-attributes)
27
+ * [Transient Attributes](#transient-attributes)
28
+ + [With other attributes](#with-other-attributes)
29
+ + [With `attributes_for`](#with-attributes_for)
30
+ + [With callbacks](#with-callbacks)
31
+ + [With associations](#with-associations)
32
+ * [Method Name / Reserved Word Attributes](#method-name--reserved-word-attributes)
33
+ * [Inheritance](#inheritance)
34
+ + [Nested factories](#nested-factories)
35
+ + [Assigning parent explicitly](#assigning-parent-explicitly)
36
+ + [Best practices](#best-practices-1)
37
+ * [Associations](#associations)
38
+ + [Implicit definition](#implicit-definition)
39
+ + [Explicit definition](#explicit-definition)
40
+ + [Inline definition](#inline-definition)
41
+ + [Specifying the factory](#specifying-the-factory)
42
+ + [Overriding attributes](#overriding-attributes)
43
+ + [Association overrides](#association-overrides)
44
+ + [Build strategies](#build-strategies-1)
45
+ + [`has_many` associations](#has_many-associations)
46
+ + [`has_and_belongs_to_many` associations](#has_and_belongs_to_many-associations)
47
+ + [Polymorphic associations](#polymorphic-associations)
48
+ + [Interconnected associations](#interconnected-associations)
49
+ * [Sequences](#sequences)
50
+ + [Global sequences](#global-sequences)
51
+ + [With dynamic attributes](#with-dynamic-attributes)
52
+ + [As implicit attributes](#as-implicit-attributes)
53
+ + [Inline sequences](#inline-sequences)
54
+ + [Initial value](#initial-value)
55
+ + [Without a block](#without-a-block)
56
+ + [Aliases](#aliases-1)
57
+ + [Rewinding](#rewinding)
58
+ + [Uniqueness](#uniqueness)
59
+ * [Traits](#traits)
60
+ + [Defining traits](#defining-traits)
61
+ + [As implicit attributes](#as-implicit-attributes-1)
62
+ + [Attribute precedence](#attribute-precedence)
63
+ + [In child factories](#in-child-factories)
64
+ + [Using traits](#using-traits)
65
+ + [With associations](#with-associations-1)
66
+ + [Traits within traits](#traits-within-traits)
67
+ + [With transient attributes](#with-transient-attributes)
68
+ + [Enum traits](#enum-traits)
69
+ * [Callbacks](#callbacks)
70
+ + [Default callbacks](#default-callbacks)
71
+ + [Multiple callbacks](#multiple-callbacks)
72
+ + [Global callbacks](#global-callbacks)
73
+ + [Symbol#to_proc](#symbolto_proc)
74
+ * [Modifying factories](#modifying-factories)
75
+ * [Building or Creating Multiple Records](#building-or-creating-multiple-records)
76
+ * [Linting Factories](#linting-factories)
77
+ * [Custom Construction](#custom-construction)
78
+ * [Custom Strategies](#custom-strategies)
79
+ * [Custom Callbacks](#custom-callbacks)
80
+ * [Custom Methods to Persist Objects](#custom-methods-to-persist-objects)
81
+ * [ActiveSupport Instrumentation](#activesupport-instrumentation)
82
+ * [Rails Preloaders and RSpec](#rails-preloaders-and-rspec)
83
+ * [Using Without Bundler](#using-without-bundler)
84
+
85
+ Setup
86
+ -----
87
+
88
+ ### Update Your Gemfile
6
89
 
7
90
  If you're using Rails:
8
91
 
@@ -16,21 +99,13 @@ If you're *not* using Rails:
16
99
  gem "factory_bot"
17
100
  ```
18
101
 
19
- JRuby users: factory_bot works with JRuby starting with 1.6.7.2 (latest stable, as per July 2012).
20
- JRuby has to be used in 1.9 mode, for that, use JRUBY_OPTS environment variable:
21
-
22
- ```bash
23
- export JRUBY_OPTS=--1.9
24
- ```
25
-
26
- Once your Gemfile is updated, you'll want to update your bundle.
27
-
28
- Configure your test suite
29
- -------------------------
102
+ ### Configure your test suite
30
103
 
31
- ### RSpec
104
+ #### RSpec
32
105
 
33
- If you're using Rails:
106
+ If you're using Rails, add the following configuration to
107
+ `spec/support/factory_bot.rb` and be sure to require that file in
108
+ `rails_helper.rb`:
34
109
 
35
110
  ```ruby
36
111
  RSpec.configure do |config|
@@ -50,7 +125,7 @@ RSpec.configure do |config|
50
125
  end
51
126
  ```
52
127
 
53
- ### Test::Unit
128
+ #### Test::Unit
54
129
 
55
130
  ```ruby
56
131
  class Test::Unit::TestCase
@@ -58,14 +133,14 @@ class Test::Unit::TestCase
58
133
  end
59
134
  ```
60
135
 
61
- ### Cucumber
136
+ #### Cucumber
62
137
 
63
138
  ```ruby
64
139
  # env.rb (Rails example location - RAILS_ROOT/features/support/env.rb)
65
140
  World(FactoryBot::Syntax::Methods)
66
141
  ```
67
142
 
68
- ### Spinach
143
+ #### Spinach
69
144
 
70
145
  ```ruby
71
146
  class Spinach::FeatureSteps
@@ -73,7 +148,7 @@ class Spinach::FeatureSteps
73
148
  end
74
149
  ```
75
150
 
76
- ### Minitest
151
+ #### Minitest
77
152
 
78
153
  ```ruby
79
154
  class Minitest::Unit::TestCase
@@ -81,7 +156,7 @@ class Minitest::Unit::TestCase
81
156
  end
82
157
  ```
83
158
 
84
- ### Minitest::Spec
159
+ #### Minitest::Spec
85
160
 
86
161
  ```ruby
87
162
  class Minitest::Spec
@@ -89,7 +164,7 @@ class Minitest::Spec
89
164
  end
90
165
  ```
91
166
 
92
- ### minitest-rails
167
+ #### minitest-rails
93
168
 
94
169
  ```ruby
95
170
  class ActiveSupport::TestCase
@@ -97,12 +172,16 @@ class ActiveSupport::TestCase
97
172
  end
98
173
  ```
99
174
 
100
- If you do not include `FactoryBot::Syntax::Methods` in your test suite, then all factory_bot methods will need to be prefaced with `FactoryBot`.
175
+ If you do not include `FactoryBot::Syntax::Methods` in your test suite, then all
176
+ factory\_bot methods will need to be prefaced with `FactoryBot`.
101
177
 
102
178
  Defining factories
103
179
  ------------------
104
180
 
105
- Each factory has a name and a set of attributes. The name is used to guess the class of the object by default:
181
+ ### Factory name and attributes
182
+
183
+ Each factory has a name and a set of attributes. The name is used to guess the
184
+ class of the object by default:
106
185
 
107
186
  ```ruby
108
187
  # This will guess the User class
@@ -115,23 +194,25 @@ FactoryBot.define do
115
194
  end
116
195
  ```
117
196
 
197
+ ### Specifying the class explicitly
198
+
118
199
  It is also possible to explicitly specify the class:
119
200
 
120
201
  ```ruby
121
202
  # This will use the User class (otherwise Admin would have been guessed)
122
- factory :admin, class: User
203
+ factory :admin, class: "User"
123
204
  ```
124
205
 
125
- If the constant is not available
126
- (if you are using a Rails engine that waits to load models, for example),
127
- you can also pass a symbol or string,
128
- which factory_bot will constantize later, once you start building objects:
206
+ You can pass a constant as well, if the constant is available (note that this
207
+ can cause test performance problems in large Rails applications, since
208
+ referring to the constant will cause it to be eagerly loaded).
129
209
 
130
210
  ```ruby
131
- # It's OK if Doorkeeper::AccessToken isn't loaded yet
132
- factory :access_token, class: "Doorkeeper::AccessToken"
211
+ factory :access_token, class: User
133
212
  ```
134
213
 
214
+ ### Hash attributes
215
+
135
216
  Because of the block syntax in Ruby, defining attributes as `Hash`es (for
136
217
  serialized/JSON columns, for example) requires two sets of curly brackets:
137
218
 
@@ -141,10 +222,19 @@ factory :program do
141
222
  end
142
223
  ```
143
224
 
144
- It is highly recommended that you have one factory for each class that provides the simplest set of attributes necessary to create an instance of that class. If you're creating ActiveRecord objects, that means that you should only provide attributes that are required through validations and that do not have defaults. Other factories can be created through inheritance to cover common scenarios for each class.
225
+ ### Best practices
226
+
227
+ It is recommended that you have one factory for each class that provides
228
+ the simplest set of attributes necessary to create an instance of that class. If
229
+ you're creating ActiveRecord objects, that means that you should only provide
230
+ attributes that are required through validations and that do not have defaults.
231
+ Other factories can be created through inheritance to cover common scenarios for
232
+ each class.
145
233
 
146
234
  Attempting to define multiple factories with the same name will raise an error.
147
235
 
236
+ ### Definition file paths
237
+
148
238
  Factories can be defined anywhere, but will be automatically loaded after
149
239
  calling `FactoryBot.find_definitions` if factories are defined in files at the
150
240
  following locations:
@@ -154,10 +244,20 @@ following locations:
154
244
  test/factories/*.rb
155
245
  spec/factories/*.rb
156
246
 
247
+ ### Static Attributes
248
+
249
+ Static attributes (without a block) are no longer available in factory\_bot 5.
250
+ You can read more about the decision to remove them in
251
+ [this blog post](https://robots.thoughtbot.com/deprecating-static-attributes-in-factory_bot-4-11).
252
+
253
+
157
254
  Using factories
158
255
  ---------------
159
256
 
160
- factory\_bot supports several different build strategies: build, create, attributes\_for and build\_stubbed:
257
+ ### Build strategies
258
+
259
+ factory\_bot supports several different build strategies: build, create,
260
+ attributes\_for and build\_stubbed:
161
261
 
162
262
  ```ruby
163
263
  # Returns a User instance that's not saved
@@ -178,7 +278,10 @@ create(:user) do |user|
178
278
  end
179
279
  ```
180
280
 
181
- No matter which strategy is used, it's possible to override the defined attributes by passing a hash:
281
+ ### Attribute overrides
282
+
283
+ No matter which strategy is used, it's possible to override the defined
284
+ attributes by passing a hash:
182
285
 
183
286
  ```ruby
184
287
  # Build a User instance and override the first_name property
@@ -187,19 +290,20 @@ user.first_name
187
290
  # => "Joe"
188
291
  ```
189
292
 
190
- Note that objects created with `build_stubbed` cannot be serialized with
191
- `Marshal.dump`, since factory_bot defines singleton methods on these objects.
192
-
193
- Static Attributes
194
- ------------------
293
+ ### `build_stubbed` and `Marshal.dump`
195
294
 
196
- Static attributes (without a block) are no longer available in factory\_bot 5.
197
- You can read more about the decision to remove them in
198
- [this blog post](https://robots.thoughtbot.com/deprecating-static-attributes-in-factory_bot-4-11).
295
+ Note that objects created with `build_stubbed` cannot be serialized with
296
+ `Marshal.dump`, since factory\_bot defines singleton methods on these objects.
199
297
 
200
298
  Aliases
201
299
  -------
202
- factory_bot allows you to define aliases to existing factories to make them easier to re-use. This could come in handy when, for example, your Post object has an author attribute that actually refers to an instance of a User class. While normally factory_bot can infer the factory name from the association name, in this case it will look for an author factory in vain. So, alias your user factory so it can be used under alias names.
300
+
301
+ factory\_bot allows you to define aliases to existing factories to make them
302
+ easier to re-use. This could come in handy when, for example, your Post object
303
+ has an author attribute that actually refers to an instance of a User class.
304
+ While normally factory\_bot can infer the factory name from the association name,
305
+ in this case it will look for an author factory in vain. So, alias your user
306
+ factory so it can be used under alias names.
203
307
 
204
308
  ```ruby
205
309
  factory :user, aliases: [:author, :commenter] do
@@ -209,17 +313,17 @@ factory :user, aliases: [:author, :commenter] do
209
313
  end
210
314
 
211
315
  factory :post do
212
- author
213
- # instead of
316
+ # The alias allows us to write author instead of
214
317
  # association :author, factory: :user
318
+ author
215
319
  title { "How to read a book effectively" }
216
320
  body { "There are five steps involved." }
217
321
  end
218
322
 
219
323
  factory :comment do
220
- commenter
221
- # instead of
324
+ # The alias allows us to write commenter instead of
222
325
  # association :commenter, factory: :user
326
+ commenter
223
327
  body { "Great article!" }
224
328
  end
225
329
  ```
@@ -243,36 +347,79 @@ create(:user, last_name: "Doe").email
243
347
 
244
348
  Transient Attributes
245
349
  --------------------
350
+ Transient attributes are attributes only available within the factory definition, and not set on the object being built. This allows for more complex logic inside factories.
246
351
 
247
- There may be times where your code can be DRYed up by passing in transient attributes to factories.
352
+ ### With other attributes
353
+
354
+ There may be times where your code can be DRYed up by passing in transient
355
+ attributes to factories. You can access transient attributes within other
356
+ attributes (see [Dependent Attributes](#dependent-attributes)):
248
357
 
249
358
  ```ruby
250
359
  factory :user do
251
360
  transient do
252
361
  rockstar { true }
253
- upcased { false }
254
362
  end
255
363
 
256
364
  name { "John Doe#{" - Rockstar" if rockstar}" }
257
- email { "#{name.downcase}@example.com" }
365
+ end
366
+
367
+ create(:user).name
368
+ #=> "John Doe - ROCKSTAR"
369
+
370
+ create(:user, rockstar: false).name
371
+ #=> "John Doe"
372
+ ```
373
+
374
+ ### With `attributes_for`
375
+
376
+ Transient attributes will be ignored within attributes\_for and won't be set on
377
+ the model, even if the attribute exists or you attempt to override it.
378
+
379
+ ### With callbacks
380
+
381
+ If you need to access the evaluator in a factory\_bot callback,
382
+ you'll need to declare a second block argument (for the evaluator) and access
383
+ transient attributes from there.
384
+
385
+ ```ruby
386
+ factory :user do
387
+ transient do
388
+ upcased { false }
389
+ end
390
+
391
+ name { "John Doe" }
258
392
 
259
393
  after(:create) do |user, evaluator|
260
394
  user.name.upcase! if evaluator.upcased
261
395
  end
262
396
  end
263
397
 
398
+ create(:user).name
399
+ #=> "John Doe"
400
+
264
401
  create(:user, upcased: true).name
265
- #=> "JOHN DOE - ROCKSTAR"
402
+ #=> "JOHN DOE"
266
403
  ```
267
404
 
268
- Transient attributes will be ignored within attributes\_for and won't be
269
- set on the model,
270
- even if the attribute exists or you attempt to override it.
405
+ ### With associations
271
406
 
272
- Within factory_bot's dynamic attributes, you can access transient attributes as
273
- you would expect. If you need to access the evaluator in a factory_bot callback,
274
- you'll need to declare a second block argument (for the evaluator) and access
275
- transient attributes from there.
407
+ Transient [associations](#associations) are not supported in factory\_bot.
408
+ Associations within the transient block will be treated as regular,
409
+ non-transient associations.
410
+
411
+ If needed, you can generally work around this by building a factory within a
412
+ transient attribute:
413
+
414
+ ```ruby
415
+ factory :post
416
+
417
+ factory :user do
418
+ transient do
419
+ post { build(:post) }
420
+ end
421
+ end
422
+ ```
276
423
 
277
424
  Method Name / Reserved Word Attributes
278
425
  -------------------------------
@@ -293,7 +440,10 @@ end
293
440
  Inheritance
294
441
  -----------
295
442
 
296
- You can easily create multiple factories for the same class without repeating common attributes by nesting factories:
443
+ ### Nested factories
444
+
445
+ You can easily create multiple factories for the same class without repeating
446
+ common attributes by nesting factories:
297
447
 
298
448
  ```ruby
299
449
  factory :post do
@@ -309,6 +459,8 @@ approved_post.title # => "A title"
309
459
  approved_post.approved # => true
310
460
  ```
311
461
 
462
+ ### Assigning parent explicitly
463
+
312
464
  You can also assign the parent explicitly:
313
465
 
314
466
  ```ruby
@@ -321,6 +473,8 @@ factory :approved_post, parent: :post do
321
473
  end
322
474
  ```
323
475
 
476
+ ### Best practices
477
+
324
478
  As mentioned above, it's good practice to define a basic factory for each class
325
479
  with only the attributes required to create it. Then, create more specific
326
480
  factories that inherit from this basic parent. Factory definitions are still
@@ -329,7 +483,10 @@ code, so keep them DRY.
329
483
  Associations
330
484
  ------------
331
485
 
332
- It's possible to set up associations within factories. If the factory name is the same as the association name, the factory name can be left out.
486
+ ### Implicit definition
487
+
488
+ It's possible to set up associations within factories. If the factory name is
489
+ the same as the association name, the factory name can be left out.
333
490
 
334
491
  ```ruby
335
492
  factory :post do
@@ -338,15 +495,117 @@ factory :post do
338
495
  end
339
496
  ```
340
497
 
341
- You can also specify a different factory or override attributes:
498
+ ### Explicit definition
499
+
500
+ You can define associations explicitly. This can be handy especially when
501
+ [Overriding attributes](#overriding-attributes)
502
+
503
+ ```ruby
504
+ factory :post do
505
+ # ...
506
+ association :author
507
+ end
508
+ ```
509
+
510
+ ### Inline definition
511
+
512
+ You can also define associations inline within regular attributes,
513
+ but note that the value will be `nil`
514
+ when using the `attributes_for` strategy.
515
+
516
+ ```ruby
517
+ factory :post do
518
+ # ...
519
+ author { association :author }
520
+ end
521
+ ```
522
+
523
+ ### Specifying the factory
524
+
525
+ You can specify a different factory (although [Aliases](#aliases) might also
526
+ help you out here).
527
+
528
+ Implicitly:
529
+
530
+ ```ruby
531
+ factory :post do
532
+ # ...
533
+ author factory: :user
534
+ end
535
+ ```
536
+
537
+ Explicitly:
538
+
539
+ ```ruby
540
+ factory :post do
541
+ # ...
542
+ association :author, factory: :user
543
+ end
544
+ ```
545
+
546
+ Inline:
547
+
548
+ ```ruby
549
+ factory :post do
550
+ # ...
551
+ author { association :user }
552
+ end
553
+ ```
554
+
555
+ ### Overriding attributes
556
+
557
+ You can also override attributes.
558
+
559
+ Implicitly:
560
+
561
+ ```ruby
562
+ factory :post do
563
+ # ...
564
+ author factory: :author, last_name: "Writely"
565
+ end
566
+ ```
567
+
568
+ Explicitly:
569
+
342
570
 
343
571
  ```ruby
344
572
  factory :post do
345
573
  # ...
346
- association :author, factory: :user, last_name: "Writely"
574
+ association :author, last_name: "Writely"
575
+ end
576
+ ```
577
+
578
+ Or inline using attributes from the factory:
579
+
580
+ ```rb
581
+ factory :post do
582
+ # ...
583
+ author_last_name { "Writely" }
584
+ author { association :author, last_name: author_last_name }
585
+ end
586
+ ```
587
+
588
+ ### Association overrides
589
+
590
+ Attribute overrides can be used to link associated objects:
591
+
592
+ ```ruby
593
+ FactoryBot.define do
594
+ factory :author do
595
+ name { 'Taylor' }
596
+ end
597
+
598
+ factory :post do
599
+ author
600
+ end
347
601
  end
602
+
603
+ eunji = build(:author, name: 'Eunji')
604
+ post = build(:post, author: eunji)
348
605
  ```
349
606
 
607
+ ### Build strategies
608
+
350
609
  In factory\_bot 5, associations default to using the same build strategy as
351
610
  their parent object:
352
611
 
@@ -387,7 +646,7 @@ post.new_record? # => true
387
646
  post.author.new_record? # => false
388
647
  ```
389
648
 
390
- To not save the associated object, specify strategy: :build in the factory:
649
+ To not save the associated object, specify `strategy: :build` in the factory:
391
650
 
392
651
  ```ruby
393
652
  FactoryBot.use_parent_strategy = false
@@ -412,27 +671,53 @@ factory :post do
412
671
  author strategy: :build # <<< this does *not* work; causes author_id to be nil
413
672
  ```
414
673
 
415
- Generating data for a `has_many` relationship is a bit more involved,
416
- depending on the amount of flexibility desired, but here's a surefire example
417
- of generating associated data.
674
+ ### `has_many` associations
675
+
676
+ There are a few ways to generate data for a `has_many` relationship. The
677
+ simplest approach is to write a helper method in plain Ruby to tie together the
678
+ different records:
418
679
 
419
680
  ```ruby
420
681
  FactoryBot.define do
682
+ factory :post do
683
+ title { "Through the Looking Glass" }
684
+ user
685
+ end
686
+
687
+ factory :user do
688
+ name { "Rachel Sanchez" }
689
+ end
690
+ end
691
+
692
+ def user_with_posts(posts_count: 5)
693
+ FactoryBot.create(:user) do |user|
694
+ FactoryBot.create_list(:post, posts_count, user: user)
695
+ end
696
+ end
421
697
 
422
- # post factory with a `belongs_to` association for the user
698
+ create(:user).posts.length # 0
699
+ user_with_posts.posts.length # 5
700
+ user_with_posts(posts_count: 15).posts.length # 15
701
+ ```
702
+
703
+ If you prefer to keep the object creation fully within factory\_bot, you can
704
+ build the posts in an `after(:create)` callback.
705
+
706
+
707
+ ```ruby
708
+ FactoryBot.define do
423
709
  factory :post do
424
710
  title { "Through the Looking Glass" }
425
711
  user
426
712
  end
427
713
 
428
- # user factory without associated posts
429
714
  factory :user do
430
715
  name { "John Doe" }
431
716
 
432
717
  # user_with_posts will create post data after the user has been created
433
718
  factory :user_with_posts do
434
- # posts_count is declared as a transient attribute and available in
435
- # attributes on the factory, as well as the callback via the evaluator
719
+ # posts_count is declared as a transient attribute available in the
720
+ # callback via the evaluator
436
721
  transient do
437
722
  posts_count { 5 }
438
723
  end
@@ -443,87 +728,142 @@ FactoryBot.define do
443
728
  # to create and we make sure the user is associated properly to the post
444
729
  after(:create) do |user, evaluator|
445
730
  create_list(:post, evaluator.posts_count, user: user)
731
+
732
+ # You may need to reload the record here, depending on your application
733
+ user.reload
446
734
  end
447
735
  end
448
736
  end
449
737
  end
450
- ```
451
738
 
452
- This allows us to do:
453
-
454
- ```ruby
455
739
  create(:user).posts.length # 0
456
740
  create(:user_with_posts).posts.length # 5
457
741
  create(:user_with_posts, posts_count: 15).posts.length # 15
458
742
  ```
459
743
 
460
- Generating data for a `has_and_belongs_to_many` relationship is very similar
461
- to the above `has_many` relationship, with a small change, you need to pass an
462
- array of objects to the model's pluralized attribute name rather than a single
463
- object to the singular version of the attribute name.
464
-
465
- Here's an example with two models that are related via
466
- `has_and_belongs_to_many`:
744
+ Or, for a solution that works with `build`, `build_stubbed`, and `create`
745
+ (although it doesn't work well with `attributes_for`), you can use inline
746
+ associations:
467
747
 
468
748
  ```ruby
469
749
  FactoryBot.define do
750
+ factory :post do
751
+ title { "Through the Looking Glass" }
752
+ user
753
+ end
754
+
755
+ factory :user do
756
+ name { "Taylor Kim" }
757
+
758
+ factory :user_with_posts do
759
+ posts { [association(:post)] }
760
+ end
761
+ end
762
+ end
763
+
764
+ create(:user).posts.length # 0
765
+ create(:user_with_posts).posts.length # 1
766
+ build(:user_with_posts).posts.length # 1
767
+ build_stubbed(:user_with_posts).posts.length # 1
768
+ ```
769
+
770
+ For more flexibility you can combine this with the `posts_count` transient
771
+ attribute from the callback example:
470
772
 
471
- # language factory with a `belongs_to` association for the profile
472
- factory :language do
773
+ ```ruby
774
+ FactoryBot.define do
775
+ factory :post do
473
776
  title { "Through the Looking Glass" }
474
- profile
777
+ user
475
778
  end
476
779
 
477
- # profile factory without associated languages
478
- factory :profile do
479
- name { "John Doe" }
780
+ factory :user do
781
+ name { "Adiza Kumato" }
480
782
 
481
- # profile_with_languages will create language data after the profile has
482
- # been created
483
- factory :profile_with_languages do
484
- # languages_count is declared as an ignored attribute and available in
485
- # attributes on the factory, as well as the callback via the evaluator
783
+ factory :user_with_posts do
486
784
  transient do
487
- languages_count { 5 }
785
+ posts_count { 5 }
488
786
  end
489
787
 
490
- # the after(:create) yields two values; the profile instance itself and
491
- # the evaluator, which stores all values from the factory, including
492
- # ignored attributes; `create_list`'s second argument is the number of
493
- # records to create and we make sure the profile is associated properly
494
- # to the language
495
- after(:create) do |profile, evaluator|
496
- create_list(:language, evaluator.languages_count, profiles: [profile])
788
+ posts do
789
+ Array.new(posts_count) { association(:post) }
497
790
  end
498
791
  end
499
792
  end
500
793
  end
794
+
795
+ create(:user_with_posts).posts.length # 5
796
+ create(:user_with_posts, posts_count: 15).posts.length # 15
797
+ build(:user_with_posts, posts_count: 15).posts.length # 15
798
+ build_stubbed(:user_with_posts, posts_count: 15).posts.length # 15
501
799
  ```
502
800
 
503
- This allows us to do:
801
+ ### `has_and_belongs_to_many` associations
802
+
803
+ Generating data for a `has_and_belongs_to_many` relationship is very similar
804
+ to the above `has_many` relationship, with a small change: you need to pass an
805
+ array of objects to the model's pluralized attribute name rather than a single
806
+ object to the singular version of the attribute name.
807
+
808
+
809
+ ```ruby
810
+ def profile_with_languages(languages_count: 2)
811
+ FactoryBot.create(:profile) do |profile|
812
+ FactoryBot.create_list(:language, languages_count, profiles: [profile])
813
+ end
814
+ end
815
+ ```
816
+
817
+ Or with the callback approach:
504
818
 
505
819
  ```ruby
506
- create(:profile).languages.length # 0
507
- create(:profile_with_languages).languages.length # 5
508
- create(:profile_with_languages, languages_count: 15).languages.length # 15
820
+ factory :profile_with_languages do
821
+ transient do
822
+ languages_count { 2 }
823
+ end
824
+
825
+ after(:create) do |profile, evaluator|
826
+ create_list(:language, evaluator.languages_count, profiles: [profile])
827
+ profile.reload
828
+ end
829
+ end
509
830
  ```
510
831
 
511
- Polymorphic associations can be handled with traits:
832
+ Or the inline association approach (note the use of the `instance` method here
833
+ to refer to the profile being built):
512
834
 
835
+ ```ruby
836
+ factory :profile_with_languages do
837
+ transient do
838
+ languages_count { 2 }
839
+ end
840
+
841
+ languages do
842
+ Array.new(languages_count) do
843
+ association(:language, profiles: [instance])
844
+ end
845
+ end
846
+ end
513
847
  ```
848
+
849
+ ### Polymorphic associations
850
+
851
+ Polymorphic associations can be handled with traits:
852
+
853
+ ```ruby
514
854
  FactoryBot.define do
515
855
  factory :video
516
856
  factory :photo
517
857
 
518
858
  factory :comment do
519
- for_photo
859
+ for_photo # default to the :for_photo trait if none is specified
520
860
 
521
861
  trait :for_video do
522
- association(:commentable, factory: :video)
862
+ association :commentable, factory: :video
523
863
  end
524
864
 
525
865
  trait :for_photo do
526
- association(:commentable, factory: :photo)
866
+ association :commentable, factory: :photo
527
867
  end
528
868
  end
529
869
  end
@@ -531,16 +871,73 @@ end
531
871
 
532
872
  This allows us to do:
533
873
 
534
- ```
874
+ ```ruby
535
875
  create(:comment)
536
876
  create(:comment, :for_video)
537
877
  create(:comment, :for_photo)
538
878
  ```
539
879
 
880
+ ### Interconnected associations
881
+
882
+ There are limitless ways objects might be interconnected, and
883
+ factory\_bot may not always be suited to handle those relationships. In some
884
+ cases it makes sense to use factory\_bot to build each individual object, and
885
+ then to write helper methods in plain Ruby to tie those objects together.
886
+
887
+ That said, some more complex, interconnected relationships can be built in factory\_bot
888
+ using inline associations with reference to the `instance` being built.
889
+
890
+ Let's say your models look like this, where an associated `Student` and
891
+ `Profile` should both belong to the same `School`:
892
+
893
+ ```ruby
894
+ class Student < ApplicationRecord
895
+ belongs_to :school
896
+ has_one :profile
897
+ end
898
+
899
+ class Profile < ApplicationRecord
900
+ belongs_to :school
901
+ belongs_to :student
902
+ end
903
+
904
+ class School < ApplicationRecord
905
+ has_many :students
906
+ has_many :profiles
907
+ end
908
+ ```
909
+
910
+ We can ensure the student and profile are connected to each other and to the
911
+ same school with a factory like this:
912
+
913
+ ```ruby
914
+ FactoryBot.define do
915
+ factory :student do
916
+ school
917
+ profile { association :profile, student: instance, school: school }
918
+ end
919
+
920
+ factory :profile do
921
+ school
922
+ student { association :student, profile: instance, school: school }
923
+ end
924
+
925
+ factory :school
926
+ end
927
+ ```
928
+
929
+ Note that this approach works with `build`, `build_stubbed`, and `create`, but
930
+ the associations will return `nil` when using `attributes_for`.
931
+
932
+ Also, note that if you assign any attributes inside a custom `initialize_with`
933
+ (e.g. `initialize_with { new(**attributes) }`), those attributes should not refer to `instance`,
934
+ since it will be `nil`.
540
935
 
541
936
  Sequences
542
937
  ---------
543
938
 
939
+ ### Global sequences
940
+
544
941
  Unique values in a specific format (for example, e-mail addresses) can be
545
942
  generated using sequences. Sequences are defined by calling `sequence` in a
546
943
  definition block, and values in a sequence are generated by calling
@@ -561,6 +958,8 @@ generate :email
561
958
  # => "person2@example.com"
562
959
  ```
563
960
 
961
+ ### With dynamic attributes
962
+
564
963
  Sequences can be used in dynamic attributes:
565
964
 
566
965
  ```ruby
@@ -569,6 +968,8 @@ factory :invite do
569
968
  end
570
969
  ```
571
970
 
971
+ ### As implicit attributes
972
+
572
973
  Or as implicit attributes:
573
974
 
574
975
  ```ruby
@@ -580,6 +981,8 @@ end
580
981
  Note that defining sequences as implicit attributes will not work if you have a
581
982
  factory with the same name as the sequence.
582
983
 
984
+ ### Inline sequences
985
+
583
986
  And it's also possible to define an in-line sequence that is only used in
584
987
  a particular factory:
585
988
 
@@ -589,7 +992,10 @@ factory :user do
589
992
  end
590
993
  ```
591
994
 
592
- You can also override the initial value:
995
+ ### Initial value
996
+
997
+ You can override the initial value. Any value that responds to the `#next`
998
+ method will work (e.g. 1, 2, 3, 'a', 'b', 'c')
593
999
 
594
1000
  ```ruby
595
1001
  factory :user do
@@ -597,6 +1003,8 @@ factory :user do
597
1003
  end
598
1004
  ```
599
1005
 
1006
+ ### Without a block
1007
+
600
1008
  Without a block, the value will increment itself, starting at its initial value:
601
1009
 
602
1010
  ```ruby
@@ -605,6 +1013,17 @@ factory :post do
605
1013
  end
606
1014
  ```
607
1015
 
1016
+ Please note, that the value for the sequence could be any Enumerable instance,
1017
+ as long as it responds to `#next`:
1018
+
1019
+ ```ruby
1020
+ factory :task do
1021
+ sequence :priority, %i[low medium high urgent].cycle
1022
+ end
1023
+ ```
1024
+
1025
+ ### Aliases
1026
+
608
1027
  Sequences can also have aliases. The sequence aliases share the same counter:
609
1028
 
610
1029
  ```ruby
@@ -634,6 +1053,8 @@ end
634
1053
 
635
1054
  The value just needs to support the `#next` method. Here the next value will be 'a', then 'b', etc.
636
1055
 
1056
+ ### Rewinding
1057
+
637
1058
  Sequences can also be rewound with `FactoryBot.rewind_sequences`:
638
1059
 
639
1060
  ```ruby
@@ -650,9 +1071,27 @@ generate(:email) # "person1@example.com"
650
1071
 
651
1072
  This rewinds all registered sequences.
652
1073
 
1074
+ ### Uniqueness
1075
+
1076
+ When working with uniqueness constraints, be careful not to pass in override values that will conflict with the generated sequence values.
1077
+
1078
+ In this example the email will be the same for both users. If email must be unique, this code will error:
1079
+
1080
+ ```rb
1081
+ factory :user do
1082
+ sequence(:email) { |n| "person#{n}@example.com" }
1083
+ end
1084
+
1085
+ FactoryBot.create(:user, email: "person1@example.com")
1086
+ FactoryBot.create(:user)
1087
+ ```
1088
+
1089
+
653
1090
  Traits
654
1091
  ------
655
1092
 
1093
+ ### Defining traits
1094
+
656
1095
  Traits allow you to group attributes together and then apply them
657
1096
  to any factory.
658
1097
 
@@ -688,6 +1127,8 @@ factory :story do
688
1127
  end
689
1128
  ```
690
1129
 
1130
+ ### As implicit attributes
1131
+
691
1132
  Traits can be used as implicit attributes:
692
1133
 
693
1134
  ```ruby
@@ -701,6 +1142,8 @@ end
701
1142
  Note that defining traits as implicit attributes will not work if you have a
702
1143
  factory or sequence with the same name as the trait.
703
1144
 
1145
+ ### Attribute precedence
1146
+
704
1147
  Traits that define the same attributes won't raise AttributeDefinitionErrors;
705
1148
  the trait that defines the attribute latest gets precedence.
706
1149
 
@@ -709,16 +1152,16 @@ factory :user do
709
1152
  name { "Friendly User" }
710
1153
  login { name }
711
1154
 
712
- trait :male do
1155
+ trait :active do
713
1156
  name { "John Doe" }
714
- gender { "Male" }
715
- login { "#{name} (M)" }
1157
+ status { :active }
1158
+ login { "#{name} (active)" }
716
1159
  end
717
1160
 
718
- trait :female do
1161
+ trait :inactive do
719
1162
  name { "Jane Doe" }
720
- gender { "Female" }
721
- login { "#{name} (F)" }
1163
+ status { :inactive }
1164
+ login { "#{name} (inactive)" }
722
1165
  end
723
1166
 
724
1167
  trait :admin do
@@ -726,40 +1169,67 @@ factory :user do
726
1169
  login { "admin-#{name}" }
727
1170
  end
728
1171
 
729
- factory :male_admin, traits: [:male, :admin] # login will be "admin-John Doe"
730
- factory :female_admin, traits: [:admin, :female] # login will be "Jane Doe (F)"
1172
+ factory :active_admin, traits: [:active, :admin] # login will be "admin-John Doe"
1173
+ factory :inactive_admin, traits: [:admin, :inactive] # login will be "Jane Doe (inactive)"
731
1174
  end
732
1175
  ```
733
1176
 
734
- You can also override individual attributes granted by a trait in subclasses.
1177
+ ### In child factories
1178
+
1179
+ You can override individual attributes granted by a trait in a child factory:
735
1180
 
736
1181
  ```ruby
737
1182
  factory :user do
738
1183
  name { "Friendly User" }
739
1184
  login { name }
740
1185
 
741
- trait :male do
1186
+ trait :active do
742
1187
  name { "John Doe" }
743
- gender { "Male" }
1188
+ status { :active }
744
1189
  login { "#{name} (M)" }
745
1190
  end
746
1191
 
747
1192
  factory :brandon do
748
- male
1193
+ active
749
1194
  name { "Brandon" }
750
1195
  end
751
1196
  end
752
1197
  ```
753
1198
 
754
- Traits can also be passed in as a list of symbols when you construct an instance from factory_bot.
1199
+ ### As mixins
1200
+
1201
+ Traits can be defined outside of factories and used as mixins to compose shared attributes
1202
+
1203
+ ```ruby
1204
+ FactoryBot.define do
1205
+ trait :timestamps do
1206
+ created_at { 8.days.ago }
1207
+ updated_at { 4.days.ago }
1208
+ end
1209
+
1210
+ factory :user, traits: [:timestamps] do
1211
+ username { "john_doe" }
1212
+ end
1213
+
1214
+ factory :post do
1215
+ timestamps
1216
+ title { "Traits rock" }
1217
+ end
1218
+ end
1219
+ ```
1220
+
1221
+ ### Using traits
1222
+
1223
+ Traits can also be passed in as a list of symbols when you construct an instance
1224
+ from factory\_bot.
755
1225
 
756
1226
  ```ruby
757
1227
  factory :user do
758
1228
  name { "Friendly User" }
759
1229
 
760
- trait :male do
1230
+ trait :active do
761
1231
  name { "John Doe" }
762
- gender { "Male" }
1232
+ status { :active }
763
1233
  end
764
1234
 
765
1235
  trait :admin do
@@ -767,8 +1237,8 @@ factory :user do
767
1237
  end
768
1238
  end
769
1239
 
770
- # creates an admin user with gender "Male" and name "Jon Snow"
771
- create(:user, :admin, :male, name: "Jon Snow")
1240
+ # creates an admin user with :active status and name "Jon Snow"
1241
+ create(:user, :admin, :active, name: "Jon Snow")
772
1242
  ```
773
1243
 
774
1244
  This ability works with `build`, `build_stubbed`, `attributes_for`, and `create`.
@@ -786,10 +1256,12 @@ factory :user do
786
1256
  end
787
1257
  end
788
1258
 
789
- # creates 3 admin users with gender "Male" and name "Jon Snow"
790
- create_list(:user, 3, :admin, :male, name: "Jon Snow")
1259
+ # creates 3 admin users with :active status and name "Jon Snow"
1260
+ create_list(:user, 3, :admin, :active, name: "Jon Snow")
791
1261
  ```
792
1262
 
1263
+ ### With associations
1264
+
793
1265
  Traits can be used with associations easily too:
794
1266
 
795
1267
  ```ruby
@@ -830,6 +1302,8 @@ end
830
1302
  create(:post).author
831
1303
  ```
832
1304
 
1305
+ ### Traits within traits
1306
+
833
1307
  Traits can be used within other traits to mix in their attributes.
834
1308
 
835
1309
  ```ruby
@@ -845,6 +1319,8 @@ factory :order do
845
1319
  end
846
1320
  ```
847
1321
 
1322
+ ### With transient attributes
1323
+
848
1324
  Finally, traits can accept transient attributes.
849
1325
 
850
1326
  ```ruby
@@ -863,9 +1339,103 @@ end
863
1339
  create :invoice, :with_amount, amount: 2
864
1340
  ```
865
1341
 
1342
+ ### Enum traits
1343
+
1344
+ Given an Active Record model with an enum attribute:
1345
+
1346
+ ```rb
1347
+ class Task < ActiveRecord::Base
1348
+ enum status: {queued: 0, started: 1, finished: 2}
1349
+ end
1350
+
1351
+ ```
1352
+
1353
+ factory\_bot will automatically define traits for each possible value of the
1354
+ enum:
1355
+
1356
+ ```rb
1357
+ FactoryBot.define do
1358
+ factory :task
1359
+ end
1360
+
1361
+ FactoryBot.build(:task, :queued)
1362
+ FactoryBot.build(:task, :started)
1363
+ FactoryBot.build(:task, :finished)
1364
+ ```
1365
+
1366
+ Writing the traits out manually would be cumbersome, and is not necessary:
1367
+
1368
+ ```rb
1369
+ FactoryBot.define do
1370
+ factory :task do
1371
+ trait :queued do
1372
+ status { :queued }
1373
+ end
1374
+
1375
+ trait :started do
1376
+ status { :started }
1377
+ end
1378
+
1379
+ trait :finished do
1380
+ status { :finished }
1381
+ end
1382
+ end
1383
+ end
1384
+ ```
1385
+
1386
+ If automatically defining traits for enum attributes on every factory is not
1387
+ desired, it is possible to disable the feature by setting
1388
+ `FactoryBot.automatically_define_enum_traits = false`
1389
+
1390
+ In that case, it is still possible to explicitly define traits for an enum
1391
+ attribute in a particular factory:
1392
+
1393
+ ```rb
1394
+ FactoryBot.automatically_define_enum_traits = false
1395
+
1396
+ FactoryBot.define do
1397
+ factory :task do
1398
+ traits_for_enum(:status)
1399
+ end
1400
+ end
1401
+ ```
1402
+
1403
+ It is also possible to use this feature for other enumerable values, not
1404
+ specifically tied to Active Record enum attributes.
1405
+
1406
+ With an array:
1407
+
1408
+ ```rb
1409
+ class Task
1410
+ attr_accessor :status
1411
+ end
1412
+
1413
+ FactoryBot.define do
1414
+ factory :task do
1415
+ traits_for_enum(:status, ["queued", "started", "finished"])
1416
+ end
1417
+ end
1418
+ ```
1419
+
1420
+ Or with a hash:
1421
+
1422
+ ```rb
1423
+ class Task
1424
+ attr_accessor :status
1425
+ end
1426
+
1427
+ FactoryBot.define do
1428
+ factory :task do
1429
+ traits_for_enum(:status, { queued: 0, started: 1, finished: 2 })
1430
+ end
1431
+ end
1432
+ ```
1433
+
866
1434
  Callbacks
867
1435
  ---------
868
1436
 
1437
+ ### Default callbacks
1438
+
869
1439
  factory\_bot makes available four callbacks for injecting some code:
870
1440
 
871
1441
  * after(:build) - called after a factory is built (via `FactoryBot.build`, `FactoryBot.create`)
@@ -884,6 +1454,8 @@ end
884
1454
 
885
1455
  Note that you'll have an instance of the user in the block. This can be useful.
886
1456
 
1457
+ ### Multiple callbacks
1458
+
887
1459
  You can also define multiple types of callbacks on the same factory:
888
1460
 
889
1461
  ```ruby
@@ -893,7 +1465,8 @@ factory :user do
893
1465
  end
894
1466
  ```
895
1467
 
896
- Factories can also define any number of the same kind of callback. These callbacks will be executed in the order they are specified:
1468
+ Factories can also define any number of the same kind of callback. These
1469
+ callbacks will be executed in the order they are specified:
897
1470
 
898
1471
  ```ruby
899
1472
  factory :user do
@@ -904,9 +1477,12 @@ end
904
1477
 
905
1478
  Calling `create` will invoke both `after_build` and `after_create` callbacks.
906
1479
 
907
- Also, like standard attributes, child factories will inherit (and can also define) callbacks from their parent factory.
1480
+ Also, like standard attributes, child factories will inherit (and can also
1481
+ define) callbacks from their parent factory.
908
1482
 
909
- Multiple callbacks can be assigned to run a block; this is useful when building various strategies that run the same code (since there are no callbacks that are shared across all strategies).
1483
+ Multiple callbacks can be assigned to run a block; this is useful when building
1484
+ various strategies that run the same code (since there are no callbacks that are
1485
+ shared across all strategies).
910
1486
 
911
1487
  ```ruby
912
1488
  factory :user do
@@ -916,6 +1492,8 @@ factory :user do
916
1492
  end
917
1493
  ```
918
1494
 
1495
+ ### Global callbacks
1496
+
919
1497
  To override callbacks for all factories, define them within the
920
1498
  `FactoryBot.define` block:
921
1499
 
@@ -930,7 +1508,9 @@ FactoryBot.define do
930
1508
  end
931
1509
  ```
932
1510
 
933
- You can also call callbacks that rely on `Symbol#to_proc`:
1511
+ ### Symbol#to_proc
1512
+
1513
+ You can call callbacks that rely on `Symbol#to_proc`:
934
1514
 
935
1515
  ```ruby
936
1516
  # app/models/user.rb
@@ -953,15 +1533,16 @@ create(:user) # creates the user and confirms it
953
1533
  Modifying factories
954
1534
  -------------------
955
1535
 
956
- If you're given a set of factories (say, from a gem developer) but want to change them to fit into your application better, you can
957
- modify that factory instead of creating a child factory and adding attributes there.
1536
+ If you're given a set of factories (say, from a gem developer) but want to
1537
+ change them to fit into your application better, you can modify that factory
1538
+ instead of creating a child factory and adding attributes there.
958
1539
 
959
1540
  If a gem were to give you a User factory:
960
1541
 
961
1542
  ```ruby
962
1543
  FactoryBot.define do
963
1544
  factory :user do
964
- full_name "John Doe"
1545
+ full_name { "John Doe" }
965
1546
  sequence(:username) { |n| "user#{n}" }
966
1547
  password { "password" }
967
1548
  end
@@ -975,7 +1556,6 @@ FactoryBot.define do
975
1556
  factory :application_user, parent: :user do
976
1557
  full_name { "Jane Doe" }
977
1558
  date_of_birth { 21.years.ago }
978
- gender { "Female" }
979
1559
  health { 90 }
980
1560
  end
981
1561
  end
@@ -988,7 +1568,6 @@ FactoryBot.modify do
988
1568
  factory :user do
989
1569
  full_name { "Jane Doe" }
990
1570
  date_of_birth { 21.years.ago }
991
- gender { "Female" }
992
1571
  health { 90 }
993
1572
  end
994
1573
  end
@@ -1018,6 +1597,23 @@ To set the attributes for each of the factories, you can pass in a hash as you n
1018
1597
  twenty_year_olds = build_list(:user, 25, date_of_birth: 20.years.ago)
1019
1598
  ```
1020
1599
 
1600
+ In order to set different attributes for each factory, these methods may be passed a block, with the factory and the index as parameters:
1601
+
1602
+ ```ruby
1603
+ twenty_somethings = build_list(:user, 10) do |user, i|
1604
+ user.date_of_birth = (20 + i).years.ago
1605
+ end
1606
+ ```
1607
+
1608
+ `create_list` passes saved instances into the block. If you modify the instance, you must save it again:
1609
+
1610
+ ```ruby
1611
+ twenty_somethings = create_list(:user, 10) do |user, i|
1612
+ user.date_of_birth = (20 + i).years.ago
1613
+ user.save!
1614
+ end
1615
+ ```
1616
+
1021
1617
  `build_stubbed_list` will give you fully stubbed out instances:
1022
1618
 
1023
1619
  ```ruby
@@ -1040,7 +1636,7 @@ users_attrs = attributes_for_list(:user, 25) # array of attribute hashes
1040
1636
  Linting Factories
1041
1637
  -----------------
1042
1638
 
1043
- factory_bot allows for linting known factories:
1639
+ factory\_bot allows for linting known factories:
1044
1640
 
1045
1641
  ```ruby
1046
1642
  FactoryBot.lint
@@ -1067,9 +1663,10 @@ namespace :factory_bot do
1067
1663
  desc "Verify that all FactoryBot factories are valid"
1068
1664
  task lint: :environment do
1069
1665
  if Rails.env.test?
1070
- DatabaseCleaner.clean_with(:deletion)
1071
- DatabaseCleaner.cleaning do
1666
+ conn = ActiveRecord::Base.connection
1667
+ conn.transaction do
1072
1668
  FactoryBot.lint
1669
+ raise ActiveRecord::Rollback
1073
1670
  end
1074
1671
  else
1075
1672
  system("bundle exec rake factory_bot:lint RAILS_ENV='test'")
@@ -1081,8 +1678,7 @@ end
1081
1678
 
1082
1679
  After calling `FactoryBot.lint`, you'll likely want to clear out the
1083
1680
  database, as records will most likely be created. The provided example above
1084
- uses the database_cleaner gem to clear out the database; be sure to add the
1085
- gem to your Gemfile under the appropriate groups.
1681
+ uses an sql transaction and rollback to leave the database clean.
1086
1682
 
1087
1683
  You can lint factories selectively by passing only factories you want linted:
1088
1684
 
@@ -1126,7 +1722,7 @@ FactoryBot.lint verbose: true
1126
1722
  Custom Construction
1127
1723
  -------------------
1128
1724
 
1129
- If you want to use factory_bot to construct an object where some attributes
1725
+ If you want to use factory\_bot to construct an object where some attributes
1130
1726
  are passed to `initialize` or if you want to do something other than simply
1131
1727
  calling `new` on your build class, you can override the default behavior by
1132
1728
  defining `initialize_with` on your factory. Example:
@@ -1154,7 +1750,7 @@ end
1154
1750
  build(:user).name # Jane Doe
1155
1751
  ```
1156
1752
 
1157
- Although factory_bot is written to work with ActiveRecord out of the box, it
1753
+ Although factory\_bot is written to work with ActiveRecord out of the box, it
1158
1754
  can also work with any Ruby class. For maximum compatibility with ActiveRecord,
1159
1755
  the default initializer builds all instances by calling `new` on your build class
1160
1756
  without any arguments. It then calls attribute writer methods to assign all the
@@ -1165,7 +1761,7 @@ You can override the initializer in order to:
1165
1761
 
1166
1762
  * Build non-ActiveRecord objects that require arguments to `initialize`
1167
1763
  * Use a method other than `new` to instantiate the instance
1168
- * Do crazy things like decorate the instance after it's built
1764
+ * Do wild things like decorate the instance after it's built
1169
1765
 
1170
1766
  When using `initialize_with`, you don't have to declare the class itself when
1171
1767
  calling `new`; however, any other class methods you want to call will have to
@@ -1192,7 +1788,7 @@ factory :user do
1192
1788
 
1193
1789
  name "John Doe"
1194
1790
 
1195
- initialize_with { new(attributes) }
1791
+ initialize_with { new(**attributes) }
1196
1792
  end
1197
1793
  ```
1198
1794
 
@@ -1227,7 +1823,7 @@ build(:user)
1227
1823
  User.new('value')
1228
1824
  ```
1229
1825
 
1230
- This prevents duplicate assignment; in versions of factory_bot before 4.0, it
1826
+ This prevents duplicate assignment; in versions of factory\_bot before 4.0, it
1231
1827
  would run this:
1232
1828
 
1233
1829
  ```ruby
@@ -1413,12 +2009,12 @@ with associations, as below:
1413
2009
 
1414
2010
  ```ruby
1415
2011
  FactoryBot.define do
1416
- factory :united_states, class: Location do
2012
+ factory :united_states, class: "Location" do
1417
2013
  name { 'United States' }
1418
2014
  association :location_group, factory: :north_america
1419
2015
  end
1420
2016
 
1421
- factory :north_america, class: LocationGroup do
2017
+ factory :north_america, class: "LocationGroup" do
1422
2018
  name { 'North America' }
1423
2019
  end
1424
2020
  end