factory_bot 5.0.2 → 6.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +52 -13
  3. data/GETTING_STARTED.md +453 -78
  4. data/NEWS.md +40 -0
  5. data/README.md +17 -16
  6. data/lib/factory_bot.rb +21 -93
  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 -1
  10. data/lib/factory_bot/attribute_assigner.rb +8 -9
  11. data/lib/factory_bot/attribute_list.rb +1 -1
  12. data/lib/factory_bot/callback.rb +2 -10
  13. data/lib/factory_bot/configuration.rb +6 -6
  14. data/lib/factory_bot/declaration.rb +1 -1
  15. data/lib/factory_bot/declaration/association.rb +30 -2
  16. data/lib/factory_bot/declaration/implicit.rb +4 -1
  17. data/lib/factory_bot/declaration_list.rb +2 -2
  18. data/lib/factory_bot/decorator.rb +18 -6
  19. data/lib/factory_bot/decorator/invocation_tracker.rb +10 -3
  20. data/lib/factory_bot/definition.rb +51 -18
  21. data/lib/factory_bot/definition_hierarchy.rb +1 -11
  22. data/lib/factory_bot/definition_proxy.rb +77 -12
  23. data/lib/factory_bot/enum.rb +27 -0
  24. data/lib/factory_bot/errors.rb +3 -0
  25. data/lib/factory_bot/evaluator.rb +20 -12
  26. data/lib/factory_bot/evaluator_class_definer.rb +1 -1
  27. data/lib/factory_bot/factory.rb +13 -13
  28. data/lib/factory_bot/factory_runner.rb +4 -4
  29. data/lib/factory_bot/find_definitions.rb +1 -1
  30. data/lib/factory_bot/internal.rb +68 -1
  31. data/lib/factory_bot/linter.rb +9 -13
  32. data/lib/factory_bot/null_factory.rb +10 -4
  33. data/lib/factory_bot/null_object.rb +2 -6
  34. data/lib/factory_bot/registry.rb +4 -4
  35. data/lib/factory_bot/reload.rb +1 -2
  36. data/lib/factory_bot/sequence.rb +5 -5
  37. data/lib/factory_bot/strategy/null.rb +4 -2
  38. data/lib/factory_bot/strategy/stub.rb +16 -5
  39. data/lib/factory_bot/strategy_calculator.rb +1 -1
  40. data/lib/factory_bot/strategy_syntax_method_registrar.rb +12 -1
  41. data/lib/factory_bot/syntax/default.rb +11 -23
  42. data/lib/factory_bot/syntax/methods.rb +3 -3
  43. data/lib/factory_bot/trait.rb +5 -3
  44. data/lib/factory_bot/version.rb +1 -1
  45. metadata +9 -36
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c8a85e57f19a64402fd04363e3860ece58e6d1b5196cde075cf47973a15cda8a
4
- data.tar.gz: 4fb7243c9259094b83de12be38b27bd58d5cdaaec3d13796d07593c0f3846084
3
+ metadata.gz: fe33ad3bb5d907e38ceac543f969484fb0ec67a4708a701cdfea0696d4a292c4
4
+ data.tar.gz: 54cdb44f4ac7782360c8e9efd02ac46f40336d00c34a5767d5d7fc0f86f8d7a5
5
5
  SHA512:
6
- metadata.gz: 2e2fe25c47b767790269c438cf426c55dfc648e4f120eab1bc006fd5c38106deae1db27ae8107ae1aff5c310edf6f8f27116a4c36dd0e296b92feaf30cc8f291
7
- data.tar.gz: f7e369608d2a547c2a1fcf57b2f69645b8ea94ff6fb06c5fa71002a0024c2e3ca3e28738379324796f04648e969576ca42b49e181f8c7495b39444079acbaaea
6
+ metadata.gz: cdc3ec9def71e797058fb13cff95b911eceb61d1488f193ef1bfb6bdf12c6c7835d1f67dc1885d5539e6da7135f04e4a417a16fbc60cbc0c4d60056a1948c89d
7
+ data.tar.gz: 2f04ab1a184266a86cf8510be688b8a01b0dd570615d25e314176b4492f9635053596636aa4ec9ab8133e86e4c9f630acdb52468c01ea1bfd2fb8777fc27b2ab
@@ -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,63 @@ 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
+ ## Running the test suite
55
+
56
+ The default rake task will run the full test suite and [standard]:
57
+
58
+ ```sh
59
+ bundle exec rake
60
+ ```
61
+
62
+ You can also run a single group of tests (unit, spec, or feature)
63
+
64
+ ```sh
65
+ bundle exec rake spec:unit
66
+ bundle exec rake spec:acceptance
67
+ bundle exec rake features
68
+ ```
69
+
70
+ To run an individual rspec test, you can provide a path and line number:
71
+
72
+ ```sh
73
+ bundle exec rspec spec/path/to/spec.rb:123
74
+ ```
75
+
76
+ You can run tests with a specific version of rails via [appraisal]. To run
77
+ the default rake task against Rails 6, for example:
78
+
79
+ ```sh
80
+ bundle exec appraisal 6.0 rake
81
+ ```
82
+
83
+ ## Formatting
84
+
85
+ Use [standard] to automatically format your code:
86
+
87
+ ```sh
88
+ bundle exec rake standard:fix
89
+ ```
90
+
55
91
  [repo]: https://github.com/thoughtbot/factory_bot/tree/master
56
92
  [fork]: https://help.github.com/articles/fork-a-repo/
57
93
  [branch]: https://help.github.com/articles/creating-and-deleting-branches-within-your-repository/
58
94
  [pr]: https://help.github.com/articles/using-pull-requests/
95
+ [standard]: https://github.com/testdouble/standard
96
+ [appraisal]: https://github.com/thoughtbot/appraisal
97
+ [reproduction script]: https://github.com/thoughtbot/factory_bot/blob/master/.github/REPRODUCTION_SCRIPT.rb
59
98
 
60
99
  Inspired by https://github.com/middleman/middleman-heroku/blob/master/CONTRIBUTING.md
@@ -1,8 +1,88 @@
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
+ + [Specifying the factory](#specifying-the-factory)
41
+ + [Overriding attributes](#overriding-attributes)
42
+ + [Build strategies](#build-strategies-1)
43
+ + [`has_many` associations](#has_many-associations)
44
+ + [`has_and_belongs_to_many` associations](#has_and_belongs_to_many-associations)
45
+ + [Polymorphic associations](#polymorphic-associations)
46
+ * [Sequences](#sequences)
47
+ + [Global sequences](#global-sequences)
48
+ + [With dynamic attributes](#with-dynamic-attributes)
49
+ + [As implicit attributes](#as-implicit-attributes)
50
+ + [Inline sequences](#inline-sequences)
51
+ + [Initial value](#initial-value)
52
+ + [Without a block](#without-a-block)
53
+ + [Aliases](#aliases-1)
54
+ + [Rewinding](#rewinding)
55
+ + [Uniqueness](#uniqueness)
56
+ * [Traits](#traits)
57
+ + [Defining traits](#defining-traits)
58
+ + [As implicit attributes](#as-implicit-attributes-1)
59
+ + [Attribute precedence](#attribute-precedence)
60
+ + [In child factories](#in-child-factories)
61
+ + [Using traits](#using-traits)
62
+ + [With associations](#with-associations-1)
63
+ + [Traits within traits](#traits-within-traits)
64
+ + [With transient attributes](#with-transient-attributes)
65
+ + [Enum traits](#enum-traits)
66
+ * [Callbacks](#callbacks)
67
+ + [Default callbacks](#default-callbacks)
68
+ + [Multiple callbacks](#multiple-callbacks)
69
+ + [Global callbacks](#global-callbacks)
70
+ + [Symbol#to_proc](#symbolto_proc)
71
+ * [Modifying factories](#modifying-factories)
72
+ * [Building or Creating Multiple Records](#building-or-creating-multiple-records)
73
+ * [Linting Factories](#linting-factories)
74
+ * [Custom Construction](#custom-construction)
75
+ * [Custom Strategies](#custom-strategies)
76
+ * [Custom Callbacks](#custom-callbacks)
77
+ * [Custom Methods to Persist Objects](#custom-methods-to-persist-objects)
78
+ * [ActiveSupport Instrumentation](#activesupport-instrumentation)
79
+ * [Rails Preloaders and RSpec](#rails-preloaders-and-rspec)
80
+ * [Using Without Bundler](#using-without-bundler)
81
+
82
+ Setup
83
+ -----
84
+
85
+ ### Update Your Gemfile
6
86
 
7
87
  If you're using Rails:
8
88
 
@@ -16,21 +96,13 @@ If you're *not* using Rails:
16
96
  gem "factory_bot"
17
97
  ```
18
98
 
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
- -------------------------
99
+ ### Configure your test suite
30
100
 
31
- ### RSpec
101
+ #### RSpec
32
102
 
33
- If you're using Rails:
103
+ If you're using Rails, add the following configuration to
104
+ `spec/support/factory_bot.rb` and be sure to require that file in
105
+ `rails_helper.rb`:
34
106
 
35
107
  ```ruby
36
108
  RSpec.configure do |config|
@@ -50,7 +122,7 @@ RSpec.configure do |config|
50
122
  end
51
123
  ```
52
124
 
53
- ### Test::Unit
125
+ #### Test::Unit
54
126
 
55
127
  ```ruby
56
128
  class Test::Unit::TestCase
@@ -58,14 +130,14 @@ class Test::Unit::TestCase
58
130
  end
59
131
  ```
60
132
 
61
- ### Cucumber
133
+ #### Cucumber
62
134
 
63
135
  ```ruby
64
136
  # env.rb (Rails example location - RAILS_ROOT/features/support/env.rb)
65
137
  World(FactoryBot::Syntax::Methods)
66
138
  ```
67
139
 
68
- ### Spinach
140
+ #### Spinach
69
141
 
70
142
  ```ruby
71
143
  class Spinach::FeatureSteps
@@ -73,7 +145,7 @@ class Spinach::FeatureSteps
73
145
  end
74
146
  ```
75
147
 
76
- ### Minitest
148
+ #### Minitest
77
149
 
78
150
  ```ruby
79
151
  class Minitest::Unit::TestCase
@@ -81,7 +153,7 @@ class Minitest::Unit::TestCase
81
153
  end
82
154
  ```
83
155
 
84
- ### Minitest::Spec
156
+ #### Minitest::Spec
85
157
 
86
158
  ```ruby
87
159
  class Minitest::Spec
@@ -89,7 +161,7 @@ class Minitest::Spec
89
161
  end
90
162
  ```
91
163
 
92
- ### minitest-rails
164
+ #### minitest-rails
93
165
 
94
166
  ```ruby
95
167
  class ActiveSupport::TestCase
@@ -97,12 +169,16 @@ class ActiveSupport::TestCase
97
169
  end
98
170
  ```
99
171
 
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`.
172
+ If you do not include `FactoryBot::Syntax::Methods` in your test suite, then all
173
+ factory\_bot methods will need to be prefaced with `FactoryBot`.
101
174
 
102
175
  Defining factories
103
176
  ------------------
104
177
 
105
- Each factory has a name and a set of attributes. The name is used to guess the class of the object by default:
178
+ ### Factory name and attributes
179
+
180
+ Each factory has a name and a set of attributes. The name is used to guess the
181
+ class of the object by default:
106
182
 
107
183
  ```ruby
108
184
  # This will guess the User class
@@ -115,6 +191,8 @@ FactoryBot.define do
115
191
  end
116
192
  ```
117
193
 
194
+ ### Specifying the class explicitly
195
+
118
196
  It is also possible to explicitly specify the class:
119
197
 
120
198
  ```ruby
@@ -125,13 +203,15 @@ factory :admin, class: User
125
203
  If the constant is not available
126
204
  (if you are using a Rails engine that waits to load models, for example),
127
205
  you can also pass a symbol or string,
128
- which factory_bot will constantize later, once you start building objects:
206
+ which factory\_bot will constantize later, once you start building objects:
129
207
 
130
208
  ```ruby
131
209
  # It's OK if Doorkeeper::AccessToken isn't loaded yet
132
210
  factory :access_token, class: "Doorkeeper::AccessToken"
133
211
  ```
134
212
 
213
+ ### Hash attributes
214
+
135
215
  Because of the block syntax in Ruby, defining attributes as `Hash`es (for
136
216
  serialized/JSON columns, for example) requires two sets of curly brackets:
137
217
 
@@ -141,10 +221,19 @@ factory :program do
141
221
  end
142
222
  ```
143
223
 
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.
224
+ ### Best practices
225
+
226
+ It is recommended that you have one factory for each class that provides
227
+ the simplest set of attributes necessary to create an instance of that class. If
228
+ you're creating ActiveRecord objects, that means that you should only provide
229
+ attributes that are required through validations and that do not have defaults.
230
+ Other factories can be created through inheritance to cover common scenarios for
231
+ each class.
145
232
 
146
233
  Attempting to define multiple factories with the same name will raise an error.
147
234
 
235
+ ### Definition file paths
236
+
148
237
  Factories can be defined anywhere, but will be automatically loaded after
149
238
  calling `FactoryBot.find_definitions` if factories are defined in files at the
150
239
  following locations:
@@ -154,10 +243,20 @@ following locations:
154
243
  test/factories/*.rb
155
244
  spec/factories/*.rb
156
245
 
246
+ ### Static Attributes
247
+
248
+ Static attributes (without a block) are no longer available in factory\_bot 5.
249
+ You can read more about the decision to remove them in
250
+ [this blog post](https://robots.thoughtbot.com/deprecating-static-attributes-in-factory_bot-4-11).
251
+
252
+
157
253
  Using factories
158
254
  ---------------
159
255
 
160
- factory\_bot supports several different build strategies: build, create, attributes\_for and build\_stubbed:
256
+ ### Build strategies
257
+
258
+ factory\_bot supports several different build strategies: build, create,
259
+ attributes\_for and build\_stubbed:
161
260
 
162
261
  ```ruby
163
262
  # Returns a User instance that's not saved
@@ -178,7 +277,10 @@ create(:user) do |user|
178
277
  end
179
278
  ```
180
279
 
181
- No matter which strategy is used, it's possible to override the defined attributes by passing a hash:
280
+ ### Attribute overrides
281
+
282
+ No matter which strategy is used, it's possible to override the defined
283
+ attributes by passing a hash:
182
284
 
183
285
  ```ruby
184
286
  # Build a User instance and override the first_name property
@@ -187,19 +289,20 @@ user.first_name
187
289
  # => "Joe"
188
290
  ```
189
291
 
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
- ------------------
292
+ ### `build_stubbed` and `Marshal.dump`
195
293
 
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).
294
+ Note that objects created with `build_stubbed` cannot be serialized with
295
+ `Marshal.dump`, since factory\_bot defines singleton methods on these objects.
199
296
 
200
297
  Aliases
201
298
  -------
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.
299
+
300
+ factory\_bot allows you to define aliases to existing factories to make them
301
+ easier to re-use. This could come in handy when, for example, your Post object
302
+ has an author attribute that actually refers to an instance of a User class.
303
+ While normally factory\_bot can infer the factory name from the association name,
304
+ in this case it will look for an author factory in vain. So, alias your user
305
+ factory so it can be used under alias names.
203
306
 
204
307
  ```ruby
205
308
  factory :user, aliases: [:author, :commenter] do
@@ -244,35 +347,77 @@ create(:user, last_name: "Doe").email
244
347
  Transient Attributes
245
348
  --------------------
246
349
 
247
- There may be times where your code can be DRYed up by passing in transient attributes to factories.
350
+ ### With other attributes
351
+
352
+ There may be times where your code can be DRYed up by passing in transient
353
+ attributes to factories. You can access transient attributes within other
354
+ attributes (see [Dependent Attributes](#dependent-attributes)):
248
355
 
249
356
  ```ruby
250
357
  factory :user do
251
358
  transient do
252
359
  rockstar { true }
253
- upcased { false }
254
360
  end
255
361
 
256
362
  name { "John Doe#{" - Rockstar" if rockstar}" }
257
- email { "#{name.downcase}@example.com" }
363
+ end
364
+
365
+ create(:user).name
366
+ #=> "John Doe - ROCKSTAR"
367
+
368
+ create(:user, rockstar: false).name
369
+ #=> "John Doe"
370
+ ```
371
+
372
+ ### With `attributes_for`
373
+
374
+ Transient attributes will be ignored within attributes\_for and won't be set on
375
+ the model, even if the attribute exists or you attempt to override it.
376
+
377
+ ### With callbacks
378
+
379
+ If you need to access the evaluator in a factory\_bot callback,
380
+ you'll need to declare a second block argument (for the evaluator) and access
381
+ transient attributes from there.
382
+
383
+ ```ruby
384
+ factory :user do
385
+ transient do
386
+ upcased { false }
387
+ end
388
+
389
+ name { "John Doe" }
258
390
 
259
391
  after(:create) do |user, evaluator|
260
392
  user.name.upcase! if evaluator.upcased
261
393
  end
262
394
  end
263
395
 
396
+ create(:user).name
397
+ #=> "John Doe"
398
+
264
399
  create(:user, upcased: true).name
265
- #=> "JOHN DOE - ROCKSTAR"
400
+ #=> "JOHN DOE"
266
401
  ```
267
402
 
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.
403
+ ### With associations
271
404
 
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.
405
+ Transient [associations](#associations) are not supported in factory\_bot.
406
+ Associations within the transient block will be treated as regular,
407
+ non-transient associations.
408
+
409
+ If needed, you can generally work around this by building a factory within a
410
+ transient attribute:
411
+
412
+ ```ruby
413
+ factory :post
414
+
415
+ factory :user do
416
+ transient do
417
+ post { build(:post) }
418
+ end
419
+ end
420
+ ```
276
421
 
277
422
  Method Name / Reserved Word Attributes
278
423
  -------------------------------
@@ -293,7 +438,10 @@ end
293
438
  Inheritance
294
439
  -----------
295
440
 
296
- You can easily create multiple factories for the same class without repeating common attributes by nesting factories:
441
+ ### Nested factories
442
+
443
+ You can easily create multiple factories for the same class without repeating
444
+ common attributes by nesting factories:
297
445
 
298
446
  ```ruby
299
447
  factory :post do
@@ -309,6 +457,8 @@ approved_post.title # => "A title"
309
457
  approved_post.approved # => true
310
458
  ```
311
459
 
460
+ ### Assigning parent explicitly
461
+
312
462
  You can also assign the parent explicitly:
313
463
 
314
464
  ```ruby
@@ -321,6 +471,8 @@ factory :approved_post, parent: :post do
321
471
  end
322
472
  ```
323
473
 
474
+ ### Best practices
475
+
324
476
  As mentioned above, it's good practice to define a basic factory for each class
325
477
  with only the attributes required to create it. Then, create more specific
326
478
  factories that inherit from this basic parent. Factory definitions are still
@@ -329,7 +481,10 @@ code, so keep them DRY.
329
481
  Associations
330
482
  ------------
331
483
 
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.
484
+ ### Implicit definition
485
+
486
+ It's possible to set up associations within factories. If the factory name is
487
+ the same as the association name, the factory name can be left out.
333
488
 
334
489
  ```ruby
335
490
  factory :post do
@@ -338,15 +493,66 @@ factory :post do
338
493
  end
339
494
  ```
340
495
 
341
- You can also specify a different factory or override attributes:
496
+ ### Explicit definition
497
+
498
+ You can define associations explicitly. This can be handy especially when
499
+ [Overriding attributes](#overriding-attributes)
500
+
501
+ ```ruby
502
+ factory :post do
503
+ # ...
504
+ association :author
505
+ end
506
+ ```
507
+
508
+ ### Specifying the factory
509
+
510
+ You can specify a different factory (although [Aliases](#aliases) might also
511
+ help you out here).
512
+
513
+ Implicitly:
514
+
515
+ ```ruby
516
+ factory :post do
517
+ # ...
518
+ author factory: :user
519
+ end
520
+ ```
521
+
522
+ Explicitly:
523
+
524
+ ```ruby
525
+ factory :post do
526
+ # ...
527
+ association :author, factory: :user
528
+ end
529
+ ```
530
+
531
+ ### Overriding attributes
532
+
533
+ You can also override attributes.
534
+
535
+ Implicitly:
536
+
537
+ ```ruby
538
+ factory :post do
539
+ # ...
540
+ author factory: :author, last_name: "Writely"
541
+ end
542
+ ```
543
+
544
+ Explicitly:
545
+
342
546
 
343
547
  ```ruby
344
548
  factory :post do
345
549
  # ...
346
- association :author, factory: :user, last_name: "Writely"
550
+ association :author, last_name: "Writely"
347
551
  end
348
552
  ```
349
553
 
554
+ ### Build strategies
555
+
350
556
  In factory\_bot 5, associations default to using the same build strategy as
351
557
  their parent object:
352
558
 
@@ -387,7 +593,7 @@ post.new_record? # => true
387
593
  post.author.new_record? # => false
388
594
  ```
389
595
 
390
- To not save the associated object, specify strategy: :build in the factory:
596
+ To not save the associated object, specify `strategy: :build` in the factory:
391
597
 
392
598
  ```ruby
393
599
  FactoryBot.use_parent_strategy = false
@@ -412,6 +618,8 @@ factory :post do
412
618
  author strategy: :build # <<< this does *not* work; causes author_id to be nil
413
619
  ```
414
620
 
621
+ ### `has_many` associations
622
+
415
623
  Generating data for a `has_many` relationship is a bit more involved,
416
624
  depending on the amount of flexibility desired, but here's a surefire example
417
625
  of generating associated data.
@@ -457,6 +665,8 @@ create(:user_with_posts).posts.length # 5
457
665
  create(:user_with_posts, posts_count: 15).posts.length # 15
458
666
  ```
459
667
 
668
+ ### `has_and_belongs_to_many` associations
669
+
460
670
  Generating data for a `has_and_belongs_to_many` relationship is very similar
461
671
  to the above `has_many` relationship, with a small change, you need to pass an
462
672
  array of objects to the model's pluralized attribute name rather than a single
@@ -508,22 +718,24 @@ create(:profile_with_languages).languages.length # 5
508
718
  create(:profile_with_languages, languages_count: 15).languages.length # 15
509
719
  ```
510
720
 
721
+ ### Polymorphic associations
722
+
511
723
  Polymorphic associations can be handled with traits:
512
724
 
513
- ```
725
+ ```ruby
514
726
  FactoryBot.define do
515
727
  factory :video
516
728
  factory :photo
517
729
 
518
730
  factory :comment do
519
- for_photo
731
+ for_photo # default to the :for_photo trait if none is specified
520
732
 
521
733
  trait :for_video do
522
- association(:commentable, factory: :video)
734
+ association :commentable, factory: :video
523
735
  end
524
736
 
525
737
  trait :for_photo do
526
- association(:commentable, factory: :photo)
738
+ association :commentable, factory: :photo
527
739
  end
528
740
  end
529
741
  end
@@ -531,7 +743,7 @@ end
531
743
 
532
744
  This allows us to do:
533
745
 
534
- ```
746
+ ```ruby
535
747
  create(:comment)
536
748
  create(:comment, :for_video)
537
749
  create(:comment, :for_photo)
@@ -541,6 +753,8 @@ create(:comment, :for_photo)
541
753
  Sequences
542
754
  ---------
543
755
 
756
+ ### Global sequences
757
+
544
758
  Unique values in a specific format (for example, e-mail addresses) can be
545
759
  generated using sequences. Sequences are defined by calling `sequence` in a
546
760
  definition block, and values in a sequence are generated by calling
@@ -561,6 +775,8 @@ generate :email
561
775
  # => "person2@example.com"
562
776
  ```
563
777
 
778
+ ### With dynamic attributes
779
+
564
780
  Sequences can be used in dynamic attributes:
565
781
 
566
782
  ```ruby
@@ -569,6 +785,8 @@ factory :invite do
569
785
  end
570
786
  ```
571
787
 
788
+ ### As implicit attributes
789
+
572
790
  Or as implicit attributes:
573
791
 
574
792
  ```ruby
@@ -580,6 +798,8 @@ end
580
798
  Note that defining sequences as implicit attributes will not work if you have a
581
799
  factory with the same name as the sequence.
582
800
 
801
+ ### Inline sequences
802
+
583
803
  And it's also possible to define an in-line sequence that is only used in
584
804
  a particular factory:
585
805
 
@@ -589,7 +809,10 @@ factory :user do
589
809
  end
590
810
  ```
591
811
 
592
- You can also override the initial value:
812
+ ### Initial value
813
+
814
+ You can override the initial value. Any value that response to the `#next`
815
+ method will work (e.g. 1, 2, 3, 'a', 'b', 'c')
593
816
 
594
817
  ```ruby
595
818
  factory :user do
@@ -597,6 +820,8 @@ factory :user do
597
820
  end
598
821
  ```
599
822
 
823
+ ### Without a block
824
+
600
825
  Without a block, the value will increment itself, starting at its initial value:
601
826
 
602
827
  ```ruby
@@ -605,6 +830,8 @@ factory :post do
605
830
  end
606
831
  ```
607
832
 
833
+ ### Aliases
834
+
608
835
  Sequences can also have aliases. The sequence aliases share the same counter:
609
836
 
610
837
  ```ruby
@@ -634,6 +861,8 @@ end
634
861
 
635
862
  The value just needs to support the `#next` method. Here the next value will be 'a', then 'b', etc.
636
863
 
864
+ ### Rewinding
865
+
637
866
  Sequences can also be rewound with `FactoryBot.rewind_sequences`:
638
867
 
639
868
  ```ruby
@@ -650,9 +879,27 @@ generate(:email) # "person1@example.com"
650
879
 
651
880
  This rewinds all registered sequences.
652
881
 
882
+ ### Uniqueness
883
+
884
+ When working with uniqueness constraints, be careful not to pass in override values that will conflict with the generated sequence values.
885
+
886
+ In this example the email will be the same for both users. If email must be unique, this code will error:
887
+
888
+ ```rb
889
+ factory :user do
890
+ sequence(:email) { |n| "person#{n}@example.com" }
891
+ end
892
+
893
+ FactoryBot.create(:user, email: "person1@example.com")
894
+ FactoryBot.create(:user)
895
+ ```
896
+
897
+
653
898
  Traits
654
899
  ------
655
900
 
901
+ ### Defining traits
902
+
656
903
  Traits allow you to group attributes together and then apply them
657
904
  to any factory.
658
905
 
@@ -688,6 +935,8 @@ factory :story do
688
935
  end
689
936
  ```
690
937
 
938
+ ### As implicit attributes
939
+
691
940
  Traits can be used as implicit attributes:
692
941
 
693
942
  ```ruby
@@ -701,6 +950,8 @@ end
701
950
  Note that defining traits as implicit attributes will not work if you have a
702
951
  factory or sequence with the same name as the trait.
703
952
 
953
+ ### Attribute precedence
954
+
704
955
  Traits that define the same attributes won't raise AttributeDefinitionErrors;
705
956
  the trait that defines the attribute latest gets precedence.
706
957
 
@@ -731,7 +982,9 @@ factory :user do
731
982
  end
732
983
  ```
733
984
 
734
- You can also override individual attributes granted by a trait in subclasses.
985
+ ### In child factories
986
+
987
+ You can override individual attributes granted by a trait in a child factory:
735
988
 
736
989
  ```ruby
737
990
  factory :user do
@@ -751,7 +1004,10 @@ factory :user do
751
1004
  end
752
1005
  ```
753
1006
 
754
- Traits can also be passed in as a list of symbols when you construct an instance from factory_bot.
1007
+ ### Using traits
1008
+
1009
+ Traits can also be passed in as a list of symbols when you construct an instance
1010
+ from factory\_bot.
755
1011
 
756
1012
  ```ruby
757
1013
  factory :user do
@@ -790,6 +1046,8 @@ end
790
1046
  create_list(:user, 3, :admin, :male, name: "Jon Snow")
791
1047
  ```
792
1048
 
1049
+ ### With associations
1050
+
793
1051
  Traits can be used with associations easily too:
794
1052
 
795
1053
  ```ruby
@@ -830,6 +1088,8 @@ end
830
1088
  create(:post).author
831
1089
  ```
832
1090
 
1091
+ ### Traits within traits
1092
+
833
1093
  Traits can be used within other traits to mix in their attributes.
834
1094
 
835
1095
  ```ruby
@@ -845,6 +1105,8 @@ factory :order do
845
1105
  end
846
1106
  ```
847
1107
 
1108
+ ### With transient attributes
1109
+
848
1110
  Finally, traits can accept transient attributes.
849
1111
 
850
1112
  ```ruby
@@ -863,9 +1125,103 @@ end
863
1125
  create :invoice, :with_amount, amount: 2
864
1126
  ```
865
1127
 
1128
+ ### Enum traits
1129
+
1130
+ Given an Active Record model with an enum attribute:
1131
+
1132
+ ```rb
1133
+ class Task < ActiveRecord::Base
1134
+ enum status: {queued: 0, started: 1, finished: 2}
1135
+ end
1136
+
1137
+ ```
1138
+
1139
+ factory\_bot will automatically define traits for each possible value of the
1140
+ enum:
1141
+
1142
+ ```rb
1143
+ FactoryBot.define do
1144
+ factory :task
1145
+ end
1146
+
1147
+ FactoryBot.build(:task, :queued)
1148
+ FactoryBot.build(:task, :started)
1149
+ FactoryBot.build(:task, :finished)
1150
+ ```
1151
+
1152
+ Writing the traits out manually would be cumbersome, and is not necessary:
1153
+
1154
+ ```rb
1155
+ FactoryBot.define do
1156
+ factory :task do
1157
+ trait :queued do
1158
+ status { :queued }
1159
+ end
1160
+
1161
+ trait :started do
1162
+ status { :started }
1163
+ end
1164
+
1165
+ trait :finished do
1166
+ status { :finished }
1167
+ end
1168
+ end
1169
+ end
1170
+ ```
1171
+
1172
+ If automatically defining traits for enum attributes on every factory is not
1173
+ desired, it is possible to disable the feature by setting
1174
+ `FactoryBot.automatically_define_enum_traits = false`
1175
+
1176
+ In that case, it is still possible to explicitly define traits for an enum
1177
+ attribute in a particular factory:
1178
+
1179
+ ```rb
1180
+ FactoryBot.automatically_define_enum_traits = false
1181
+
1182
+ FactoryBot.define do
1183
+ factory :task do
1184
+ traits_for_enum(:status)
1185
+ end
1186
+ end
1187
+ ```
1188
+
1189
+ It is also possible to use this feature for other enumerable values, not
1190
+ specifically tied to Active Record enum attributes.
1191
+
1192
+ With an array:
1193
+
1194
+ ```rb
1195
+ class Task
1196
+ attr_accessor :status
1197
+ end
1198
+
1199
+ FactoryBot.define do
1200
+ factory :task do
1201
+ traits_for_enum(:status, ["queued", "started", "finished"])
1202
+ end
1203
+ end
1204
+ ```
1205
+
1206
+ Or with a hash:
1207
+
1208
+ ```rb
1209
+ class Task
1210
+ attr_accessor :status
1211
+ end
1212
+
1213
+ FactoryBot.define do
1214
+ factory :task do
1215
+ traits_for_enum(:status, { queued: 0, started: 1, finished: 2 })
1216
+ end
1217
+ end
1218
+ ```
1219
+
866
1220
  Callbacks
867
1221
  ---------
868
1222
 
1223
+ ### Default callbacks
1224
+
869
1225
  factory\_bot makes available four callbacks for injecting some code:
870
1226
 
871
1227
  * after(:build) - called after a factory is built (via `FactoryBot.build`, `FactoryBot.create`)
@@ -884,6 +1240,8 @@ end
884
1240
 
885
1241
  Note that you'll have an instance of the user in the block. This can be useful.
886
1242
 
1243
+ ### Multiple callbacks
1244
+
887
1245
  You can also define multiple types of callbacks on the same factory:
888
1246
 
889
1247
  ```ruby
@@ -893,7 +1251,8 @@ factory :user do
893
1251
  end
894
1252
  ```
895
1253
 
896
- Factories can also define any number of the same kind of callback. These callbacks will be executed in the order they are specified:
1254
+ Factories can also define any number of the same kind of callback. These
1255
+ callbacks will be executed in the order they are specified:
897
1256
 
898
1257
  ```ruby
899
1258
  factory :user do
@@ -904,9 +1263,12 @@ end
904
1263
 
905
1264
  Calling `create` will invoke both `after_build` and `after_create` callbacks.
906
1265
 
907
- Also, like standard attributes, child factories will inherit (and can also define) callbacks from their parent factory.
1266
+ Also, like standard attributes, child factories will inherit (and can also
1267
+ define) callbacks from their parent factory.
908
1268
 
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).
1269
+ Multiple callbacks can be assigned to run a block; this is useful when building
1270
+ various strategies that run the same code (since there are no callbacks that are
1271
+ shared across all strategies).
910
1272
 
911
1273
  ```ruby
912
1274
  factory :user do
@@ -916,6 +1278,8 @@ factory :user do
916
1278
  end
917
1279
  ```
918
1280
 
1281
+ ### Global callbacks
1282
+
919
1283
  To override callbacks for all factories, define them within the
920
1284
  `FactoryBot.define` block:
921
1285
 
@@ -930,7 +1294,9 @@ FactoryBot.define do
930
1294
  end
931
1295
  ```
932
1296
 
933
- You can also call callbacks that rely on `Symbol#to_proc`:
1297
+ ### Symbol#to_proc
1298
+
1299
+ You can call callbacks that rely on `Symbol#to_proc`:
934
1300
 
935
1301
  ```ruby
936
1302
  # app/models/user.rb
@@ -953,15 +1319,16 @@ create(:user) # creates the user and confirms it
953
1319
  Modifying factories
954
1320
  -------------------
955
1321
 
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.
1322
+ If you're given a set of factories (say, from a gem developer) but want to
1323
+ change them to fit into your application better, you can modify that factory
1324
+ instead of creating a child factory and adding attributes there.
958
1325
 
959
1326
  If a gem were to give you a User factory:
960
1327
 
961
1328
  ```ruby
962
1329
  FactoryBot.define do
963
1330
  factory :user do
964
- full_name "John Doe"
1331
+ full_name { "John Doe" }
965
1332
  sequence(:username) { |n| "user#{n}" }
966
1333
  password { "password" }
967
1334
  end
@@ -1018,6 +1385,14 @@ To set the attributes for each of the factories, you can pass in a hash as you n
1018
1385
  twenty_year_olds = build_list(:user, 25, date_of_birth: 20.years.ago)
1019
1386
  ```
1020
1387
 
1388
+ In order to set different attributes for each factory, these methods may be passed a block, with the factory and the index as parameters:
1389
+
1390
+ ```ruby
1391
+ twenty_somethings = build_list(:user, 10) do |user, i|
1392
+ user.date_of_birth = (20 + i).years.ago
1393
+ end
1394
+ ```
1395
+
1021
1396
  `build_stubbed_list` will give you fully stubbed out instances:
1022
1397
 
1023
1398
  ```ruby
@@ -1040,7 +1415,7 @@ users_attrs = attributes_for_list(:user, 25) # array of attribute hashes
1040
1415
  Linting Factories
1041
1416
  -----------------
1042
1417
 
1043
- factory_bot allows for linting known factories:
1418
+ factory\_bot allows for linting known factories:
1044
1419
 
1045
1420
  ```ruby
1046
1421
  FactoryBot.lint
@@ -1067,9 +1442,10 @@ namespace :factory_bot do
1067
1442
  desc "Verify that all FactoryBot factories are valid"
1068
1443
  task lint: :environment do
1069
1444
  if Rails.env.test?
1070
- DatabaseCleaner.clean_with(:deletion)
1071
- DatabaseCleaner.cleaning do
1445
+ conn = ActiveRecord::Base.connection
1446
+ conn.transaction do
1072
1447
  FactoryBot.lint
1448
+ raise ActiveRecord::Rollback
1073
1449
  end
1074
1450
  else
1075
1451
  system("bundle exec rake factory_bot:lint RAILS_ENV='test'")
@@ -1081,8 +1457,7 @@ end
1081
1457
 
1082
1458
  After calling `FactoryBot.lint`, you'll likely want to clear out the
1083
1459
  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.
1460
+ uses an sql transaction and rollback to leave the database clean.
1086
1461
 
1087
1462
  You can lint factories selectively by passing only factories you want linted:
1088
1463
 
@@ -1126,7 +1501,7 @@ FactoryBot.lint verbose: true
1126
1501
  Custom Construction
1127
1502
  -------------------
1128
1503
 
1129
- If you want to use factory_bot to construct an object where some attributes
1504
+ If you want to use factory\_bot to construct an object where some attributes
1130
1505
  are passed to `initialize` or if you want to do something other than simply
1131
1506
  calling `new` on your build class, you can override the default behavior by
1132
1507
  defining `initialize_with` on your factory. Example:
@@ -1154,7 +1529,7 @@ end
1154
1529
  build(:user).name # Jane Doe
1155
1530
  ```
1156
1531
 
1157
- Although factory_bot is written to work with ActiveRecord out of the box, it
1532
+ Although factory\_bot is written to work with ActiveRecord out of the box, it
1158
1533
  can also work with any Ruby class. For maximum compatibility with ActiveRecord,
1159
1534
  the default initializer builds all instances by calling `new` on your build class
1160
1535
  without any arguments. It then calls attribute writer methods to assign all the
@@ -1165,7 +1540,7 @@ You can override the initializer in order to:
1165
1540
 
1166
1541
  * Build non-ActiveRecord objects that require arguments to `initialize`
1167
1542
  * Use a method other than `new` to instantiate the instance
1168
- * Do crazy things like decorate the instance after it's built
1543
+ * Do wild things like decorate the instance after it's built
1169
1544
 
1170
1545
  When using `initialize_with`, you don't have to declare the class itself when
1171
1546
  calling `new`; however, any other class methods you want to call will have to
@@ -1227,7 +1602,7 @@ build(:user)
1227
1602
  User.new('value')
1228
1603
  ```
1229
1604
 
1230
- This prevents duplicate assignment; in versions of factory_bot before 4.0, it
1605
+ This prevents duplicate assignment; in versions of factory\_bot before 4.0, it
1231
1606
  would run this:
1232
1607
 
1233
1608
  ```ruby
@@ -1413,12 +1788,12 @@ with associations, as below:
1413
1788
 
1414
1789
  ```ruby
1415
1790
  FactoryBot.define do
1416
- factory :united_states, class: Location do
1791
+ factory :united_states, class: "Location" do
1417
1792
  name { 'United States' }
1418
1793
  association :location_group, factory: :north_america
1419
1794
  end
1420
1795
 
1421
- factory :north_america, class: LocationGroup do
1796
+ factory :north_america, class: "LocationGroup" do
1422
1797
  name { 'North America' }
1423
1798
  end
1424
1799
  end