factory_bot 5.2.0 → 6.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +58 -13
  3. data/GETTING_STARTED.md +684 -136
  4. data/NEWS.md +30 -2
  5. data/README.md +4 -10
  6. data/lib/factory_bot.rb +19 -53
  7. data/lib/factory_bot/aliases.rb +3 -3
  8. data/lib/factory_bot/attribute/association.rb +2 -2
  9. data/lib/factory_bot/attribute/dynamic.rb +2 -2
  10. data/lib/factory_bot/attribute_assigner.rb +9 -10
  11. data/lib/factory_bot/attribute_list.rb +1 -1
  12. data/lib/factory_bot/callback.rb +3 -11
  13. data/lib/factory_bot/configuration.rb +7 -7
  14. data/lib/factory_bot/declaration.rb +1 -1
  15. data/lib/factory_bot/declaration/association.rb +23 -6
  16. data/lib/factory_bot/declaration_list.rb +2 -2
  17. data/lib/factory_bot/decorator.rb +18 -6
  18. data/lib/factory_bot/decorator/invocation_tracker.rb +1 -0
  19. data/lib/factory_bot/definition.rb +61 -16
  20. data/lib/factory_bot/definition_proxy.rb +63 -5
  21. data/lib/factory_bot/enum.rb +27 -0
  22. data/lib/factory_bot/evaluator.rb +6 -7
  23. data/lib/factory_bot/evaluator_class_definer.rb +1 -1
  24. data/lib/factory_bot/factory.rb +12 -12
  25. data/lib/factory_bot/factory_runner.rb +3 -3
  26. data/lib/factory_bot/find_definitions.rb +1 -1
  27. data/lib/factory_bot/internal.rb +12 -25
  28. data/lib/factory_bot/linter.rb +8 -12
  29. data/lib/factory_bot/null_factory.rb +11 -5
  30. data/lib/factory_bot/null_object.rb +2 -6
  31. data/lib/factory_bot/registry.rb +2 -2
  32. data/lib/factory_bot/reload.rb +0 -1
  33. data/lib/factory_bot/sequence.rb +5 -5
  34. data/lib/factory_bot/strategy/null.rb +4 -2
  35. data/lib/factory_bot/strategy/stub.rb +6 -2
  36. data/lib/factory_bot/syntax/default.rb +7 -7
  37. data/lib/factory_bot/trait.rb +2 -2
  38. data/lib/factory_bot/version.rb +1 -1
  39. metadata +12 -40
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 802da48aa95dce3321f20d0173c5dcf041c5393fb0c270fb8ae2029ce12b6ed9
4
- data.tar.gz: 0aa227896ef66ccf100f88b1aa4e9aa26c5bc657fee76739a73e15072bc80572
3
+ metadata.gz: a928c94babd835a0756175aa3d7a1f03d4dae15b0782818a8c9688489f6e18d3
4
+ data.tar.gz: e2875eca60137531b83267dcdfd87ba1329ed8a52e460a0e609fa5fb04f39244
5
5
  SHA512:
6
- metadata.gz: 63554d6765398f0c524cb8cd45b1a0da83da1d8aba9f359d0e4c44e42cdbd0d93edb8e38c668e0310ad709905c5cd6a3c35e640ad8c45a06a8b7d4090b4e6161
7
- data.tar.gz: fe3be69bdd601384da0a7f2ec7e1fcf00ae7d4984c65423e31e94c1b7f3d7bb04345371daaea19d794365972b59f69f9f3403b0ef8b8ef7d7349d89404284ac2
6
+ metadata.gz: bf8f7006ff4e0f34533259c6e747bb61cd8ebcd6d68b7a9076b811bf4b152662997f18ad467953c07f3a0c7c10585b48b4f0489ce6aa1a16b42ad02641e7169b
7
+ data.tar.gz: a80c3ed49517c2cee0dc7bdafc9dd3459d7fcd83443873e2a8c72db8a3c96b6d902975c8a586ecbfb1cd6b8dab9513a4bdfaa22f84c297f81b2736a8f4317e8d
data/CONTRIBUTING.md CHANGED
@@ -12,7 +12,7 @@ Here are some ways *you* can contribute:
12
12
  * by suggesting new features
13
13
  * by writing or editing documentation
14
14
  * by writing specifications
15
- * by writing code ( **no patch is too small** : fix typos, add comments, clean up inconsistent whitespace )
15
+ * by writing code ( **no patch is too small** : fix typos, add comments, etc. )
16
16
  * by refactoring code
17
17
  * by closing [issues][]
18
18
  * by reviewing patches
@@ -23,13 +23,10 @@ Here are some ways *you* can contribute:
23
23
 
24
24
  * We use the [GitHub issue tracker][issues] to track bugs and features.
25
25
  * Before submitting a bug report or feature request, check to make sure it hasn't
26
- already been submitted.
27
- * When submitting a bug report, please include a [Gist][] that includes a stack
28
- trace and any details that may be necessary to reproduce the bug, including
29
- your gem version, Ruby version, and operating system. Ideally, a bug report
30
- should include a pull request with failing specs.
31
-
32
- [gist]: https://gist.github.com/
26
+ already been submitted.
27
+ * When submitting a bug report, please include a [reproduction script] and any
28
+ other details that may be necessary to reproduce the bug, including your gem
29
+ version, Ruby version, and operating system.
33
30
 
34
31
  ## Cleaning up issues
35
32
 
@@ -40,21 +37,69 @@ already been submitted.
40
37
  We will happily reopen the issue.
41
38
 
42
39
  ## Submitting a Pull Request
40
+
43
41
  1. [Fork][fork] the [official repository][repo].
44
- 2. [Create a topic branch.][branch]
45
- 3. Implement your feature or bug fix.
46
- 4. Add, commit, and push your changes.
47
- 5. [Submit a pull request.][pr]
42
+ 1. [Create a topic branch.][branch]
43
+ 1. Implement your feature or bug fix.
44
+ 1. Add, commit, and push your changes.
45
+ 1. [Submit a pull request.][pr]
46
+
47
+ ### Notes
48
48
 
49
- ## Notes
50
49
  * Please add tests if you changed code. Contributions without tests won't be accepted.
51
50
  * If you don't know how to add tests, please put in a PR and leave a comment
52
51
  asking for help. We love helping!
53
52
  * Please don't update the Gem version.
54
53
 
54
+ ## Setting up
55
+
56
+ ```sh
57
+ bundle install
58
+ ```
59
+
60
+ ## Running the test suite
61
+
62
+ The default rake task will run the full test suite and [standard]:
63
+
64
+ ```sh
65
+ bundle exec rake
66
+ ```
67
+
68
+ You can also run a single group of tests (unit, spec, or feature)
69
+
70
+ ```sh
71
+ bundle exec rake spec:unit
72
+ bundle exec rake spec:acceptance
73
+ bundle exec rake features
74
+ ```
75
+
76
+ To run an individual rspec test, you can provide a path and line number:
77
+
78
+ ```sh
79
+ bundle exec rspec spec/path/to/spec.rb:123
80
+ ```
81
+
82
+ You can run tests with a specific version of rails via [appraisal]. To run
83
+ the default rake task against Rails 6, for example:
84
+
85
+ ```sh
86
+ bundle exec appraisal 6.0 rake
87
+ ```
88
+
89
+ ## Formatting
90
+
91
+ Use [standard] to automatically format your code:
92
+
93
+ ```sh
94
+ bundle exec rake standard:fix
95
+ ```
96
+
55
97
  [repo]: https://github.com/thoughtbot/factory_bot/tree/master
56
98
  [fork]: https://help.github.com/articles/fork-a-repo/
57
99
  [branch]: https://help.github.com/articles/creating-and-deleting-branches-within-your-repository/
58
100
  [pr]: https://help.github.com/articles/using-pull-requests/
101
+ [standard]: https://github.com/testdouble/standard
102
+ [appraisal]: https://github.com/thoughtbot/appraisal
103
+ [reproduction script]: https://github.com/thoughtbot/factory_bot/blob/master/.github/REPRODUCTION_SCRIPT.rb
59
104
 
60
105
  Inspired by https://github.com/middleman/middleman-heroku/blob/master/CONTRIBUTING.md
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, add the following configuration to `spec/support/factory_bot.rb` and be sure to require that file in `rails_helper.rb`:
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.
351
+
352
+ ### With other attributes
246
353
 
247
- There may be times where your code can be DRYed up by passing in transient attributes to factories.
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.
342
515
 
343
516
  ```ruby
344
517
  factory :post do
345
518
  # ...
346
- association :author, factory: :user, last_name: "Writely"
519
+ author { association :author }
347
520
  end
348
521
  ```
349
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
+
570
+
571
+ ```ruby
572
+ factory :post do
573
+ # ...
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
+ author_last_name { 'Taylor' }
596
+ end
597
+
598
+ factory :post do
599
+ author
600
+ end
601
+ end
602
+
603
+ eunji = build(:author, name: 'Eunji')
604
+ post = build(:post, author: eunji)
605
+ ```
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
 
@@ -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
697
+
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.
421
705
 
422
- # post factory with a `belongs_to` association for the user
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,71 +728,126 @@ 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:
818
+
819
+ ```ruby
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
830
+ ```
831
+
832
+ Or the inline association approach (note the use of the `instance` method here
833
+ to refer to the profile being built):
504
834
 
505
835
  ```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
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
509
847
  ```
510
848
 
849
+ ### Polymorphic associations
850
+
511
851
  Polymorphic associations can be handled with traits:
512
852
 
513
853
  ```ruby
@@ -537,10 +877,67 @@ 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,8 @@ factory :post do
605
1013
  end
606
1014
  ```
607
1015
 
1016
+ ### Aliases
1017
+
608
1018
  Sequences can also have aliases. The sequence aliases share the same counter:
609
1019
 
610
1020
  ```ruby
@@ -634,6 +1044,8 @@ end
634
1044
 
635
1045
  The value just needs to support the `#next` method. Here the next value will be 'a', then 'b', etc.
636
1046
 
1047
+ ### Rewinding
1048
+
637
1049
  Sequences can also be rewound with `FactoryBot.rewind_sequences`:
638
1050
 
639
1051
  ```ruby
@@ -650,9 +1062,27 @@ generate(:email) # "person1@example.com"
650
1062
 
651
1063
  This rewinds all registered sequences.
652
1064
 
1065
+ ### Uniqueness
1066
+
1067
+ When working with uniqueness constraints, be careful not to pass in override values that will conflict with the generated sequence values.
1068
+
1069
+ In this example the email will be the same for both users. If email must be unique, this code will error:
1070
+
1071
+ ```rb
1072
+ factory :user do
1073
+ sequence(:email) { |n| "person#{n}@example.com" }
1074
+ end
1075
+
1076
+ FactoryBot.create(:user, email: "person1@example.com")
1077
+ FactoryBot.create(:user)
1078
+ ```
1079
+
1080
+
653
1081
  Traits
654
1082
  ------
655
1083
 
1084
+ ### Defining traits
1085
+
656
1086
  Traits allow you to group attributes together and then apply them
657
1087
  to any factory.
658
1088
 
@@ -688,6 +1118,8 @@ factory :story do
688
1118
  end
689
1119
  ```
690
1120
 
1121
+ ### As implicit attributes
1122
+
691
1123
  Traits can be used as implicit attributes:
692
1124
 
693
1125
  ```ruby
@@ -701,6 +1133,8 @@ end
701
1133
  Note that defining traits as implicit attributes will not work if you have a
702
1134
  factory or sequence with the same name as the trait.
703
1135
 
1136
+ ### Attribute precedence
1137
+
704
1138
  Traits that define the same attributes won't raise AttributeDefinitionErrors;
705
1139
  the trait that defines the attribute latest gets precedence.
706
1140
 
@@ -709,16 +1143,16 @@ factory :user do
709
1143
  name { "Friendly User" }
710
1144
  login { name }
711
1145
 
712
- trait :male do
1146
+ trait :active do
713
1147
  name { "John Doe" }
714
- gender { "Male" }
715
- login { "#{name} (M)" }
1148
+ status { :active }
1149
+ login { "#{name} (active)" }
716
1150
  end
717
1151
 
718
- trait :female do
1152
+ trait :inactive do
719
1153
  name { "Jane Doe" }
720
- gender { "Female" }
721
- login { "#{name} (F)" }
1154
+ status { :inactive }
1155
+ login { "#{name} (inactive)" }
722
1156
  end
723
1157
 
724
1158
  trait :admin do
@@ -726,40 +1160,45 @@ factory :user do
726
1160
  login { "admin-#{name}" }
727
1161
  end
728
1162
 
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)"
1163
+ factory :active_admin, traits: [:active, :admin] # login will be "admin-John Doe"
1164
+ factory :inactive_admin, traits: [:admin, :inactive] # login will be "Jane Doe (inactive)"
731
1165
  end
732
1166
  ```
733
1167
 
734
- You can also override individual attributes granted by a trait in subclasses.
1168
+ ### In child factories
1169
+
1170
+ You can override individual attributes granted by a trait in a child factory:
735
1171
 
736
1172
  ```ruby
737
1173
  factory :user do
738
1174
  name { "Friendly User" }
739
1175
  login { name }
740
1176
 
741
- trait :male do
1177
+ trait :active do
742
1178
  name { "John Doe" }
743
- gender { "Male" }
1179
+ status { :active }
744
1180
  login { "#{name} (M)" }
745
1181
  end
746
1182
 
747
1183
  factory :brandon do
748
- male
1184
+ active
749
1185
  name { "Brandon" }
750
1186
  end
751
1187
  end
752
1188
  ```
753
1189
 
754
- Traits can also be passed in as a list of symbols when you construct an instance from factory_bot.
1190
+ ### Using traits
1191
+
1192
+ Traits can also be passed in as a list of symbols when you construct an instance
1193
+ from factory\_bot.
755
1194
 
756
1195
  ```ruby
757
1196
  factory :user do
758
1197
  name { "Friendly User" }
759
1198
 
760
- trait :male do
1199
+ trait :active do
761
1200
  name { "John Doe" }
762
- gender { "Male" }
1201
+ status { :active }
763
1202
  end
764
1203
 
765
1204
  trait :admin do
@@ -767,8 +1206,8 @@ factory :user do
767
1206
  end
768
1207
  end
769
1208
 
770
- # creates an admin user with gender "Male" and name "Jon Snow"
771
- create(:user, :admin, :male, name: "Jon Snow")
1209
+ # creates an admin user with :active status and name "Jon Snow"
1210
+ create(:user, :admin, :active, name: "Jon Snow")
772
1211
  ```
773
1212
 
774
1213
  This ability works with `build`, `build_stubbed`, `attributes_for`, and `create`.
@@ -786,10 +1225,12 @@ factory :user do
786
1225
  end
787
1226
  end
788
1227
 
789
- # creates 3 admin users with gender "Male" and name "Jon Snow"
790
- create_list(:user, 3, :admin, :male, name: "Jon Snow")
1228
+ # creates 3 admin users with :active status and name "Jon Snow"
1229
+ create_list(:user, 3, :admin, :active, name: "Jon Snow")
791
1230
  ```
792
1231
 
1232
+ ### With associations
1233
+
793
1234
  Traits can be used with associations easily too:
794
1235
 
795
1236
  ```ruby
@@ -830,6 +1271,8 @@ end
830
1271
  create(:post).author
831
1272
  ```
832
1273
 
1274
+ ### Traits within traits
1275
+
833
1276
  Traits can be used within other traits to mix in their attributes.
834
1277
 
835
1278
  ```ruby
@@ -845,6 +1288,8 @@ factory :order do
845
1288
  end
846
1289
  ```
847
1290
 
1291
+ ### With transient attributes
1292
+
848
1293
  Finally, traits can accept transient attributes.
849
1294
 
850
1295
  ```ruby
@@ -863,9 +1308,103 @@ end
863
1308
  create :invoice, :with_amount, amount: 2
864
1309
  ```
865
1310
 
1311
+ ### Enum traits
1312
+
1313
+ Given an Active Record model with an enum attribute:
1314
+
1315
+ ```rb
1316
+ class Task < ActiveRecord::Base
1317
+ enum status: {queued: 0, started: 1, finished: 2}
1318
+ end
1319
+
1320
+ ```
1321
+
1322
+ factory\_bot will automatically define traits for each possible value of the
1323
+ enum:
1324
+
1325
+ ```rb
1326
+ FactoryBot.define do
1327
+ factory :task
1328
+ end
1329
+
1330
+ FactoryBot.build(:task, :queued)
1331
+ FactoryBot.build(:task, :started)
1332
+ FactoryBot.build(:task, :finished)
1333
+ ```
1334
+
1335
+ Writing the traits out manually would be cumbersome, and is not necessary:
1336
+
1337
+ ```rb
1338
+ FactoryBot.define do
1339
+ factory :task do
1340
+ trait :queued do
1341
+ status { :queued }
1342
+ end
1343
+
1344
+ trait :started do
1345
+ status { :started }
1346
+ end
1347
+
1348
+ trait :finished do
1349
+ status { :finished }
1350
+ end
1351
+ end
1352
+ end
1353
+ ```
1354
+
1355
+ If automatically defining traits for enum attributes on every factory is not
1356
+ desired, it is possible to disable the feature by setting
1357
+ `FactoryBot.automatically_define_enum_traits = false`
1358
+
1359
+ In that case, it is still possible to explicitly define traits for an enum
1360
+ attribute in a particular factory:
1361
+
1362
+ ```rb
1363
+ FactoryBot.automatically_define_enum_traits = false
1364
+
1365
+ FactoryBot.define do
1366
+ factory :task do
1367
+ traits_for_enum(:status)
1368
+ end
1369
+ end
1370
+ ```
1371
+
1372
+ It is also possible to use this feature for other enumerable values, not
1373
+ specifically tied to Active Record enum attributes.
1374
+
1375
+ With an array:
1376
+
1377
+ ```rb
1378
+ class Task
1379
+ attr_accessor :status
1380
+ end
1381
+
1382
+ FactoryBot.define do
1383
+ factory :task do
1384
+ traits_for_enum(:status, ["queued", "started", "finished"])
1385
+ end
1386
+ end
1387
+ ```
1388
+
1389
+ Or with a hash:
1390
+
1391
+ ```rb
1392
+ class Task
1393
+ attr_accessor :status
1394
+ end
1395
+
1396
+ FactoryBot.define do
1397
+ factory :task do
1398
+ traits_for_enum(:status, { queued: 0, started: 1, finished: 2 })
1399
+ end
1400
+ end
1401
+ ```
1402
+
866
1403
  Callbacks
867
1404
  ---------
868
1405
 
1406
+ ### Default callbacks
1407
+
869
1408
  factory\_bot makes available four callbacks for injecting some code:
870
1409
 
871
1410
  * after(:build) - called after a factory is built (via `FactoryBot.build`, `FactoryBot.create`)
@@ -884,6 +1423,8 @@ end
884
1423
 
885
1424
  Note that you'll have an instance of the user in the block. This can be useful.
886
1425
 
1426
+ ### Multiple callbacks
1427
+
887
1428
  You can also define multiple types of callbacks on the same factory:
888
1429
 
889
1430
  ```ruby
@@ -893,7 +1434,8 @@ factory :user do
893
1434
  end
894
1435
  ```
895
1436
 
896
- Factories can also define any number of the same kind of callback. These callbacks will be executed in the order they are specified:
1437
+ Factories can also define any number of the same kind of callback. These
1438
+ callbacks will be executed in the order they are specified:
897
1439
 
898
1440
  ```ruby
899
1441
  factory :user do
@@ -904,9 +1446,12 @@ end
904
1446
 
905
1447
  Calling `create` will invoke both `after_build` and `after_create` callbacks.
906
1448
 
907
- Also, like standard attributes, child factories will inherit (and can also define) callbacks from their parent factory.
1449
+ Also, like standard attributes, child factories will inherit (and can also
1450
+ define) callbacks from their parent factory.
908
1451
 
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).
1452
+ Multiple callbacks can be assigned to run a block; this is useful when building
1453
+ various strategies that run the same code (since there are no callbacks that are
1454
+ shared across all strategies).
910
1455
 
911
1456
  ```ruby
912
1457
  factory :user do
@@ -916,6 +1461,8 @@ factory :user do
916
1461
  end
917
1462
  ```
918
1463
 
1464
+ ### Global callbacks
1465
+
919
1466
  To override callbacks for all factories, define them within the
920
1467
  `FactoryBot.define` block:
921
1468
 
@@ -930,7 +1477,9 @@ FactoryBot.define do
930
1477
  end
931
1478
  ```
932
1479
 
933
- You can also call callbacks that rely on `Symbol#to_proc`:
1480
+ ### Symbol#to_proc
1481
+
1482
+ You can call callbacks that rely on `Symbol#to_proc`:
934
1483
 
935
1484
  ```ruby
936
1485
  # app/models/user.rb
@@ -953,8 +1502,9 @@ create(:user) # creates the user and confirms it
953
1502
  Modifying factories
954
1503
  -------------------
955
1504
 
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.
1505
+ If you're given a set of factories (say, from a gem developer) but want to
1506
+ change them to fit into your application better, you can modify that factory
1507
+ instead of creating a child factory and adding attributes there.
958
1508
 
959
1509
  If a gem were to give you a User factory:
960
1510
 
@@ -975,7 +1525,6 @@ FactoryBot.define do
975
1525
  factory :application_user, parent: :user do
976
1526
  full_name { "Jane Doe" }
977
1527
  date_of_birth { 21.years.ago }
978
- gender { "Female" }
979
1528
  health { 90 }
980
1529
  end
981
1530
  end
@@ -988,7 +1537,6 @@ FactoryBot.modify do
988
1537
  factory :user do
989
1538
  full_name { "Jane Doe" }
990
1539
  date_of_birth { 21.years.ago }
991
- gender { "Female" }
992
1540
  health { 90 }
993
1541
  end
994
1542
  end
@@ -1048,7 +1596,7 @@ users_attrs = attributes_for_list(:user, 25) # array of attribute hashes
1048
1596
  Linting Factories
1049
1597
  -----------------
1050
1598
 
1051
- factory_bot allows for linting known factories:
1599
+ factory\_bot allows for linting known factories:
1052
1600
 
1053
1601
  ```ruby
1054
1602
  FactoryBot.lint
@@ -1134,7 +1682,7 @@ FactoryBot.lint verbose: true
1134
1682
  Custom Construction
1135
1683
  -------------------
1136
1684
 
1137
- If you want to use factory_bot to construct an object where some attributes
1685
+ If you want to use factory\_bot to construct an object where some attributes
1138
1686
  are passed to `initialize` or if you want to do something other than simply
1139
1687
  calling `new` on your build class, you can override the default behavior by
1140
1688
  defining `initialize_with` on your factory. Example:
@@ -1162,7 +1710,7 @@ end
1162
1710
  build(:user).name # Jane Doe
1163
1711
  ```
1164
1712
 
1165
- Although factory_bot is written to work with ActiveRecord out of the box, it
1713
+ Although factory\_bot is written to work with ActiveRecord out of the box, it
1166
1714
  can also work with any Ruby class. For maximum compatibility with ActiveRecord,
1167
1715
  the default initializer builds all instances by calling `new` on your build class
1168
1716
  without any arguments. It then calls attribute writer methods to assign all the
@@ -1173,7 +1721,7 @@ You can override the initializer in order to:
1173
1721
 
1174
1722
  * Build non-ActiveRecord objects that require arguments to `initialize`
1175
1723
  * Use a method other than `new` to instantiate the instance
1176
- * Do crazy things like decorate the instance after it's built
1724
+ * Do wild things like decorate the instance after it's built
1177
1725
 
1178
1726
  When using `initialize_with`, you don't have to declare the class itself when
1179
1727
  calling `new`; however, any other class methods you want to call will have to
@@ -1200,7 +1748,7 @@ factory :user do
1200
1748
 
1201
1749
  name "John Doe"
1202
1750
 
1203
- initialize_with { new(attributes) }
1751
+ initialize_with { new(**attributes) }
1204
1752
  end
1205
1753
  ```
1206
1754
 
@@ -1235,7 +1783,7 @@ build(:user)
1235
1783
  User.new('value')
1236
1784
  ```
1237
1785
 
1238
- This prevents duplicate assignment; in versions of factory_bot before 4.0, it
1786
+ This prevents duplicate assignment; in versions of factory\_bot before 4.0, it
1239
1787
  would run this:
1240
1788
 
1241
1789
  ```ruby