factory_bot 4.10.0 → 6.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -0
  3. data/CONTRIBUTING.md +52 -13
  4. data/GETTING_STARTED.md +630 -182
  5. data/LICENSE +1 -1
  6. data/NEWS.md +372 -0
  7. data/README.md +29 -31
  8. data/lib/factory_bot.rb +71 -140
  9. data/lib/factory_bot/aliases.rb +2 -2
  10. data/lib/factory_bot/attribute.rb +4 -39
  11. data/lib/factory_bot/attribute/association.rb +2 -2
  12. data/lib/factory_bot/attribute/dynamic.rb +2 -1
  13. data/lib/factory_bot/attribute_assigner.rb +24 -10
  14. data/lib/factory_bot/attribute_list.rb +3 -2
  15. data/lib/factory_bot/callback.rb +3 -10
  16. data/lib/factory_bot/configuration.rb +15 -19
  17. data/lib/factory_bot/declaration.rb +5 -5
  18. data/lib/factory_bot/declaration/association.rb +33 -3
  19. data/lib/factory_bot/declaration/dynamic.rb +3 -1
  20. data/lib/factory_bot/declaration/implicit.rb +7 -2
  21. data/lib/factory_bot/declaration_list.rb +3 -3
  22. data/lib/factory_bot/decorator.rb +20 -4
  23. data/lib/factory_bot/decorator/attribute_hash.rb +1 -1
  24. data/lib/factory_bot/decorator/invocation_tracker.rb +10 -3
  25. data/lib/factory_bot/definition.rb +54 -20
  26. data/lib/factory_bot/definition_hierarchy.rb +1 -11
  27. data/lib/factory_bot/definition_proxy.rb +125 -43
  28. data/lib/factory_bot/enum.rb +27 -0
  29. data/lib/factory_bot/errors.rb +7 -4
  30. data/lib/factory_bot/evaluation.rb +1 -1
  31. data/lib/factory_bot/evaluator.rb +23 -15
  32. data/lib/factory_bot/evaluator_class_definer.rb +1 -1
  33. data/lib/factory_bot/factory.rb +12 -12
  34. data/lib/factory_bot/factory_runner.rb +4 -4
  35. data/lib/factory_bot/find_definitions.rb +2 -2
  36. data/lib/factory_bot/internal.rb +91 -0
  37. data/lib/factory_bot/linter.rb +41 -28
  38. data/lib/factory_bot/null_factory.rb +13 -4
  39. data/lib/factory_bot/null_object.rb +2 -6
  40. data/lib/factory_bot/registry.rb +17 -8
  41. data/lib/factory_bot/reload.rb +2 -3
  42. data/lib/factory_bot/sequence.rb +5 -6
  43. data/lib/factory_bot/strategy/stub.rb +37 -37
  44. data/lib/factory_bot/strategy_calculator.rb +1 -1
  45. data/lib/factory_bot/strategy_syntax_method_registrar.rb +13 -2
  46. data/lib/factory_bot/syntax.rb +2 -2
  47. data/lib/factory_bot/syntax/default.rb +12 -24
  48. data/lib/factory_bot/syntax/methods.rb +32 -9
  49. data/lib/factory_bot/trait.rb +7 -4
  50. data/lib/factory_bot/version.rb +1 -1
  51. metadata +50 -65
  52. data/.autotest +0 -9
  53. data/.gitignore +0 -10
  54. data/.rspec +0 -3
  55. data/.simplecov +0 -4
  56. data/.travis.yml +0 -58
  57. data/Appraisals +0 -23
  58. data/Gemfile +0 -8
  59. data/Gemfile.lock +0 -103
  60. data/NEWS +0 -298
  61. data/Rakefile +0 -36
  62. data/cucumber.yml +0 -1
  63. data/factory_bot.gemspec +0 -36
  64. data/factory_girl.gemspec +0 -40
  65. data/gemfiles/3.2.gemfile +0 -10
  66. data/gemfiles/3.2.gemfile.lock +0 -107
  67. data/gemfiles/4.0.gemfile +0 -10
  68. data/gemfiles/4.0.gemfile.lock +0 -107
  69. data/gemfiles/4.1.gemfile +0 -10
  70. data/gemfiles/4.1.gemfile.lock +0 -106
  71. data/gemfiles/4.2.gemfile +0 -10
  72. data/gemfiles/4.2.gemfile.lock +0 -106
  73. data/gemfiles/5.0.gemfile +0 -10
  74. data/gemfiles/5.0.gemfile.lock +0 -104
  75. data/gemfiles/5.1.gemfile +0 -10
  76. data/gemfiles/5.1.gemfile.lock +0 -104
  77. data/lib/factory_bot/attribute/static.rb +0 -16
  78. data/lib/factory_bot/declaration/static.rb +0 -26
  79. data/lib/factory_bot/decorator/class_key_hash.rb +0 -28
  80. data/lib/factory_girl.rb +0 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3f6cddf8a7633587c40928e1b9bd981a644d0f2f99259eaafdd0ac986fa19775
4
- data.tar.gz: 4300e1bc0e6204159ca66ef4ec2a3a9eb1cc131693b7907591e1a94f1f1e93f7
3
+ metadata.gz: fe33ad3bb5d907e38ceac543f969484fb0ec67a4708a701cdfea0696d4a292c4
4
+ data.tar.gz: 54cdb44f4ac7782360c8e9efd02ac46f40336d00c34a5767d5d7fc0f86f8d7a5
5
5
  SHA512:
6
- metadata.gz: 9583c5fb81fd3be6241566123cc1ffa590f54cc58c441868aff8efb679405b2c52bf38fd8ca9c3a4bf89079d12505d64565161ff300fca3d186cfcafc3573dd6
7
- data.tar.gz: 10723a4fdc450038aa2d515e3df7ff26d59d634439e6632daa44ba91f6ca87491f52edfb9c9595da8fd3621dda4a2b707dd8523c4eb42c156fda04411d75c332
6
+ metadata.gz: cdc3ec9def71e797058fb13cff95b911eceb61d1488f193ef1bfb6bdf12c6c7835d1f67dc1885d5539e6da7135f04e4a417a16fbc60cbc0c4d60056a1948c89d
7
+ data.tar.gz: 2f04ab1a184266a86cf8510be688b8a01b0dd570615d25e314176b4492f9635053596636aa4ec9ab8133e86e4c9f630acdb52468c01ea1bfd2fb8777fc27b2ab
data/.yardopts CHANGED
@@ -2,4 +2,5 @@ lib/**/*.rb
2
2
  -
3
3
  GETTING_STARTED.md
4
4
  CONTRIBUTING.md
5
+ NAME.md
5
6
  LICENSE
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,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
data/GETTING_STARTED.md CHANGED
@@ -1,42 +1,118 @@
1
1
  Getting Started
2
2
  ===============
3
3
 
4
- Update Your Gemfile
5
- -------------------
6
-
7
- If you're using Rails, you'll need to change the required version of `factory_bot_rails`:
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
86
+
87
+ If you're using Rails:
88
+
89
+ ```ruby
90
+ gem "factory_bot_rails"
91
+ ```
92
+
93
+ If you're *not* using Rails:
94
+
95
+ ```ruby
96
+ gem "factory_bot"
97
+ ```
98
+
99
+ ### Configure your test suite
100
+
101
+ #### RSpec
102
+
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`:
8
106
 
9
107
  ```ruby
10
- gem "factory_bot_rails", "~> 4.0"
11
- ```
12
-
13
- If you're *not* using Rails, you'll just have to change the required version of `factory_bot`:
14
-
15
- ```ruby
16
- gem "factory_bot", "~> 4.0"
17
- ```
18
-
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
- -------------------------
30
-
31
- ### RSpec
32
-
33
- ```ruby
34
- # spec/support/factory_bot.rb
35
108
  RSpec.configure do |config|
36
109
  config.include FactoryBot::Syntax::Methods
37
110
  end
111
+ ```
112
+
113
+ If you're *not* using Rails:
38
114
 
39
- # RSpec without Rails
115
+ ```ruby
40
116
  RSpec.configure do |config|
41
117
  config.include FactoryBot::Syntax::Methods
42
118
 
@@ -46,13 +122,7 @@ RSpec.configure do |config|
46
122
  end
47
123
  ```
48
124
 
49
- Remember to require the above file in your rails_helper since the support folder isn't eagerly loaded
50
-
51
- ```ruby
52
- require 'support/factory_bot'
53
- ```
54
-
55
- ### Test::Unit
125
+ #### Test::Unit
56
126
 
57
127
  ```ruby
58
128
  class Test::Unit::TestCase
@@ -60,14 +130,14 @@ class Test::Unit::TestCase
60
130
  end
61
131
  ```
62
132
 
63
- ### Cucumber
133
+ #### Cucumber
64
134
 
65
135
  ```ruby
66
136
  # env.rb (Rails example location - RAILS_ROOT/features/support/env.rb)
67
137
  World(FactoryBot::Syntax::Methods)
68
138
  ```
69
139
 
70
- ### Spinach
140
+ #### Spinach
71
141
 
72
142
  ```ruby
73
143
  class Spinach::FeatureSteps
@@ -75,7 +145,7 @@ class Spinach::FeatureSteps
75
145
  end
76
146
  ```
77
147
 
78
- ### Minitest
148
+ #### Minitest
79
149
 
80
150
  ```ruby
81
151
  class Minitest::Unit::TestCase
@@ -83,7 +153,7 @@ class Minitest::Unit::TestCase
83
153
  end
84
154
  ```
85
155
 
86
- ### Minitest::Spec
156
+ #### Minitest::Spec
87
157
 
88
158
  ```ruby
89
159
  class Minitest::Spec
@@ -91,7 +161,7 @@ class Minitest::Spec
91
161
  end
92
162
  ```
93
163
 
94
- ### minitest-rails
164
+ #### minitest-rails
95
165
 
96
166
  ```ruby
97
167
  class ActiveSupport::TestCase
@@ -99,35 +169,71 @@ class ActiveSupport::TestCase
99
169
  end
100
170
  ```
101
171
 
102
- 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`.
103
174
 
104
175
  Defining factories
105
176
  ------------------
106
177
 
107
- Each factory has a name and a set of attributes. The name is used to guess the class of the object by default, but it's possible to explicitly specify it:
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:
108
182
 
109
183
  ```ruby
110
184
  # This will guess the User class
111
185
  FactoryBot.define do
112
186
  factory :user do
113
- first_name "John"
114
- last_name "Doe"
115
- admin false
187
+ first_name { "John" }
188
+ last_name { "Doe" }
189
+ admin { false }
116
190
  end
191
+ end
192
+ ```
117
193
 
118
- # This will use the User class (Admin would have been guessed)
119
- factory :admin, class: User do
120
- first_name "Admin"
121
- last_name "User"
122
- admin true
123
- end
194
+ ### Specifying the class explicitly
195
+
196
+ It is also possible to explicitly specify the class:
197
+
198
+ ```ruby
199
+ # This will use the User class (otherwise Admin would have been guessed)
200
+ factory :admin, class: User
201
+ ```
202
+
203
+ If the constant is not available
204
+ (if you are using a Rails engine that waits to load models, for example),
205
+ you can also pass a symbol or string,
206
+ which factory\_bot will constantize later, once you start building objects:
207
+
208
+ ```ruby
209
+ # It's OK if Doorkeeper::AccessToken isn't loaded yet
210
+ factory :access_token, class: "Doorkeeper::AccessToken"
211
+ ```
212
+
213
+ ### Hash attributes
214
+
215
+ Because of the block syntax in Ruby, defining attributes as `Hash`es (for
216
+ serialized/JSON columns, for example) requires two sets of curly brackets:
217
+
218
+ ```ruby
219
+ factory :program do
220
+ configuration { { auto_resolve: false, auto_define: true } }
124
221
  end
125
222
  ```
126
223
 
127
- 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.
128
232
 
129
233
  Attempting to define multiple factories with the same name will raise an error.
130
234
 
235
+ ### Definition file paths
236
+
131
237
  Factories can be defined anywhere, but will be automatically loaded after
132
238
  calling `FactoryBot.find_definitions` if factories are defined in files at the
133
239
  following locations:
@@ -137,10 +243,20 @@ following locations:
137
243
  test/factories/*.rb
138
244
  spec/factories/*.rb
139
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
+
140
253
  Using factories
141
254
  ---------------
142
255
 
143
- 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:
144
260
 
145
261
  ```ruby
146
262
  # Returns a User instance that's not saved
@@ -161,7 +277,10 @@ create(:user) do |user|
161
277
  end
162
278
  ```
163
279
 
164
- 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:
165
284
 
166
285
  ```ruby
167
286
  # Build a User instance and override the first_name property
@@ -170,40 +289,25 @@ user.first_name
170
289
  # => "Joe"
171
290
  ```
172
291
 
173
- Dynamic Attributes
174
- ------------------
292
+ ### `build_stubbed` and `Marshal.dump`
175
293
 
176
- Most factory attributes can be added using static values that are evaluated when
177
- the factory is defined, but some attributes (such as associations and other
178
- attributes that must be dynamically generated) will need values assigned each
179
- time an instance is generated. These "dynamic" attributes can be added by passing a
180
- block instead of a parameter:
181
-
182
- ```ruby
183
- factory :user do
184
- # ...
185
- activation_code { User.generate_activation_code }
186
- date_of_birth { 21.years.ago }
187
- end
188
- ```
189
-
190
- Because of the block syntax in Ruby, defining attributes as `Hash`es (for
191
- serialized/JSON columns, for example) requires two sets of curly brackets:
192
-
193
- ```ruby
194
- factory :program do
195
- configuration { { auto_resolve: false, auto_define: true } }
196
- end
197
- ```
294
+ Note that objects created with `build_stubbed` cannot be serialized with
295
+ `Marshal.dump`, since factory\_bot defines singleton methods on these objects.
198
296
 
199
297
  Aliases
200
298
  -------
201
- 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 a 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.
202
306
 
203
307
  ```ruby
204
308
  factory :user, aliases: [:author, :commenter] do
205
- first_name "John"
206
- last_name "Doe"
309
+ first_name { "John" }
310
+ last_name { "Doe" }
207
311
  date_of_birth { 18.years.ago }
208
312
  end
209
313
 
@@ -211,15 +315,15 @@ factory :post do
211
315
  author
212
316
  # instead of
213
317
  # association :author, factory: :user
214
- title "How to read a book effectively"
215
- body "There are five steps involved."
318
+ title { "How to read a book effectively" }
319
+ body { "There are five steps involved." }
216
320
  end
217
321
 
218
322
  factory :comment do
219
323
  commenter
220
324
  # instead of
221
325
  # association :commenter, factory: :user
222
- body "Great article!"
326
+ body { "Great article!" }
223
327
  end
224
328
  ```
225
329
 
@@ -231,8 +335,8 @@ that is yielded to dynamic attribute blocks:
231
335
 
232
336
  ```ruby
233
337
  factory :user do
234
- first_name "Joe"
235
- last_name "Blow"
338
+ first_name { "Joe" }
339
+ last_name { "Blow" }
236
340
  email { "#{first_name}.#{last_name}@example.com".downcase }
237
341
  end
238
342
 
@@ -243,40 +347,82 @@ create(:user, last_name: "Doe").email
243
347
  Transient Attributes
244
348
  --------------------
245
349
 
246
- 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)):
355
+
356
+ ```ruby
357
+ factory :user do
358
+ transient do
359
+ rockstar { true }
360
+ end
361
+
362
+ name { "John Doe#{" - Rockstar" if rockstar}" }
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.
247
382
 
248
383
  ```ruby
249
384
  factory :user do
250
385
  transient do
251
- rockstar true
252
- upcased false
386
+ upcased { false }
253
387
  end
254
388
 
255
- name { "John Doe#{" - Rockstar" if rockstar}" }
256
- email { "#{name.downcase}@example.com" }
389
+ name { "John Doe" }
257
390
 
258
391
  after(:create) do |user, evaluator|
259
392
  user.name.upcase! if evaluator.upcased
260
393
  end
261
394
  end
262
395
 
396
+ create(:user).name
397
+ #=> "John Doe"
398
+
263
399
  create(:user, upcased: true).name
264
- #=> "JOHN DOE - ROCKSTAR"
400
+ #=> "JOHN DOE"
265
401
  ```
266
402
 
267
- Static and dynamic attributes can be created as transient attributes. Transient
268
- attributes will be ignored within attributes\_for and won't be set on the model,
269
- even if the attribute exists or you attempt to override it.
403
+ ### With associations
270
404
 
271
- Within factory_bot's dynamic attributes, you can access transient attributes as
272
- you would expect. If you need to access the evaluator in a factory_bot callback,
273
- you'll need to declare a second block argument (for the evaluator) and access
274
- 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
+ ```
275
421
 
276
422
  Method Name / Reserved Word Attributes
277
423
  -------------------------------
278
424
 
279
- If your attributes conflict with existing methods or reserved words you can define them with `add_attribute`.
425
+ If your attributes conflict with existing methods or reserved words (all methods in the [DefinitionProxy](https://github.com/thoughtbot/factory_bot/blob/master/lib/factory_bot/definition_proxy.rb) class) you can define them with `add_attribute`.
280
426
 
281
427
  ```ruby
282
428
  factory :dna do
@@ -292,14 +438,17 @@ end
292
438
  Inheritance
293
439
  -----------
294
440
 
295
- 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:
296
445
 
297
446
  ```ruby
298
447
  factory :post do
299
- title "A title"
448
+ title { "A title" }
300
449
 
301
450
  factory :approved_post do
302
- approved true
451
+ approved { true }
303
452
  end
304
453
  end
305
454
 
@@ -308,18 +457,22 @@ approved_post.title # => "A title"
308
457
  approved_post.approved # => true
309
458
  ```
310
459
 
460
+ ### Assigning parent explicitly
461
+
311
462
  You can also assign the parent explicitly:
312
463
 
313
464
  ```ruby
314
465
  factory :post do
315
- title "A title"
466
+ title { "A title" }
316
467
  end
317
468
 
318
469
  factory :approved_post, parent: :post do
319
- approved true
470
+ approved { true }
320
471
  end
321
472
  ```
322
473
 
474
+ ### Best practices
475
+
323
476
  As mentioned above, it's good practice to define a basic factory for each class
324
477
  with only the attributes required to create it. Then, create more specific
325
478
  factories that inherit from this basic parent. Factory definitions are still
@@ -328,7 +481,10 @@ code, so keep them DRY.
328
481
  Associations
329
482
  ------------
330
483
 
331
- 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.
332
488
 
333
489
  ```ruby
334
490
  factory :post do
@@ -337,18 +493,95 @@ factory :post do
337
493
  end
338
494
  ```
339
495
 
340
- 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
+
341
546
 
342
547
  ```ruby
343
548
  factory :post do
344
549
  # ...
345
- association :author, factory: :user, last_name: "Writely"
550
+ association :author, last_name: "Writely"
346
551
  end
347
552
  ```
348
553
 
349
- The behavior of the association method varies depending on the build strategy used for the parent object.
554
+ ### Build strategies
555
+
556
+ In factory\_bot 5, associations default to using the same build strategy as
557
+ their parent object:
350
558
 
351
559
  ```ruby
560
+ FactoryBot.define do
561
+ factory :author
562
+
563
+ factory :post do
564
+ author
565
+ end
566
+ end
567
+
568
+ post = build(:post)
569
+ post.new_record? # => true
570
+ post.author.new_record? # => true
571
+
572
+ post = create(:post)
573
+ post.new_record? # => false
574
+ post.author.new_record? # => false
575
+ ```
576
+
577
+ This is different than the default behavior for previous versions of
578
+ factory\_bot, where the association strategy would not always match the strategy
579
+ of the parent object. If you want to continue using the old behavior, you can
580
+ set the `use_parent_strategy` configuration option to `false`.
581
+
582
+ ```ruby
583
+ FactoryBot.use_parent_strategy = false
584
+
352
585
  # Builds and saves a User and a Post
353
586
  post = create(:post)
354
587
  post.new_record? # => false
@@ -360,9 +593,11 @@ post.new_record? # => true
360
593
  post.author.new_record? # => false
361
594
  ```
362
595
 
363
- 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:
364
597
 
365
598
  ```ruby
599
+ FactoryBot.use_parent_strategy = false
600
+
366
601
  factory :post do
367
602
  # ...
368
603
  association :author, factory: :user, strategy: :build
@@ -383,6 +618,8 @@ factory :post do
383
618
  author strategy: :build # <<< this does *not* work; causes author_id to be nil
384
619
  ```
385
620
 
621
+ ### `has_many` associations
622
+
386
623
  Generating data for a `has_many` relationship is a bit more involved,
387
624
  depending on the amount of flexibility desired, but here's a surefire example
388
625
  of generating associated data.
@@ -392,20 +629,20 @@ FactoryBot.define do
392
629
 
393
630
  # post factory with a `belongs_to` association for the user
394
631
  factory :post do
395
- title "Through the Looking Glass"
632
+ title { "Through the Looking Glass" }
396
633
  user
397
634
  end
398
635
 
399
636
  # user factory without associated posts
400
637
  factory :user do
401
- name "John Doe"
638
+ name { "John Doe" }
402
639
 
403
640
  # user_with_posts will create post data after the user has been created
404
641
  factory :user_with_posts do
405
642
  # posts_count is declared as a transient attribute and available in
406
643
  # attributes on the factory, as well as the callback via the evaluator
407
644
  transient do
408
- posts_count 5
645
+ posts_count { 5 }
409
646
  end
410
647
 
411
648
  # the after(:create) yields two values; the user instance itself and the
@@ -428,6 +665,8 @@ create(:user_with_posts).posts.length # 5
428
665
  create(:user_with_posts, posts_count: 15).posts.length # 15
429
666
  ```
430
667
 
668
+ ### `has_and_belongs_to_many` associations
669
+
431
670
  Generating data for a `has_and_belongs_to_many` relationship is very similar
432
671
  to the above `has_many` relationship, with a small change, you need to pass an
433
672
  array of objects to the model's pluralized attribute name rather than a single
@@ -441,13 +680,13 @@ FactoryBot.define do
441
680
 
442
681
  # language factory with a `belongs_to` association for the profile
443
682
  factory :language do
444
- title "Through the Looking Glass"
683
+ title { "Through the Looking Glass" }
445
684
  profile
446
685
  end
447
686
 
448
687
  # profile factory without associated languages
449
688
  factory :profile do
450
- name "John Doe"
689
+ name { "John Doe" }
451
690
 
452
691
  # profile_with_languages will create language data after the profile has
453
692
  # been created
@@ -455,7 +694,7 @@ FactoryBot.define do
455
694
  # languages_count is declared as an ignored attribute and available in
456
695
  # attributes on the factory, as well as the callback via the evaluator
457
696
  transient do
458
- languages_count 5
697
+ languages_count { 5 }
459
698
  end
460
699
 
461
700
  # the after(:create) yields two values; the profile instance itself and
@@ -479,9 +718,43 @@ create(:profile_with_languages).languages.length # 5
479
718
  create(:profile_with_languages, languages_count: 15).languages.length # 15
480
719
  ```
481
720
 
721
+ ### Polymorphic associations
722
+
723
+ Polymorphic associations can be handled with traits:
724
+
725
+ ```ruby
726
+ FactoryBot.define do
727
+ factory :video
728
+ factory :photo
729
+
730
+ factory :comment do
731
+ for_photo # default to the :for_photo trait if none is specified
732
+
733
+ trait :for_video do
734
+ association :commentable, factory: :video
735
+ end
736
+
737
+ trait :for_photo do
738
+ association :commentable, factory: :photo
739
+ end
740
+ end
741
+ end
742
+ ```
743
+
744
+ This allows us to do:
745
+
746
+ ```ruby
747
+ create(:comment)
748
+ create(:comment, :for_video)
749
+ create(:comment, :for_photo)
750
+ ```
751
+
752
+
482
753
  Sequences
483
754
  ---------
484
755
 
756
+ ### Global sequences
757
+
485
758
  Unique values in a specific format (for example, e-mail addresses) can be
486
759
  generated using sequences. Sequences are defined by calling `sequence` in a
487
760
  definition block, and values in a sequence are generated by calling
@@ -502,6 +775,8 @@ generate :email
502
775
  # => "person2@example.com"
503
776
  ```
504
777
 
778
+ ### With dynamic attributes
779
+
505
780
  Sequences can be used in dynamic attributes:
506
781
 
507
782
  ```ruby
@@ -510,6 +785,8 @@ factory :invite do
510
785
  end
511
786
  ```
512
787
 
788
+ ### As implicit attributes
789
+
513
790
  Or as implicit attributes:
514
791
 
515
792
  ```ruby
@@ -518,6 +795,11 @@ factory :user do
518
795
  end
519
796
  ```
520
797
 
798
+ Note that defining sequences as implicit attributes will not work if you have a
799
+ factory with the same name as the sequence.
800
+
801
+ ### Inline sequences
802
+
521
803
  And it's also possible to define an in-line sequence that is only used in
522
804
  a particular factory:
523
805
 
@@ -527,7 +809,10 @@ factory :user do
527
809
  end
528
810
  ```
529
811
 
530
- 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')
531
816
 
532
817
  ```ruby
533
818
  factory :user do
@@ -535,6 +820,8 @@ factory :user do
535
820
  end
536
821
  ```
537
822
 
823
+ ### Without a block
824
+
538
825
  Without a block, the value will increment itself, starting at its initial value:
539
826
 
540
827
  ```ruby
@@ -543,6 +830,8 @@ factory :post do
543
830
  end
544
831
  ```
545
832
 
833
+ ### Aliases
834
+
546
835
  Sequences can also have aliases. The sequence aliases share the same counter:
547
836
 
548
837
  ```ruby
@@ -572,6 +861,8 @@ end
572
861
 
573
862
  The value just needs to support the `#next` method. Here the next value will be 'a', then 'b', etc.
574
863
 
864
+ ### Rewinding
865
+
575
866
  Sequences can also be rewound with `FactoryBot.rewind_sequences`:
576
867
 
577
868
  ```ruby
@@ -588,9 +879,27 @@ generate(:email) # "person1@example.com"
588
879
 
589
880
  This rewinds all registered sequences.
590
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
+
591
898
  Traits
592
899
  ------
593
900
 
901
+ ### Defining traits
902
+
594
903
  Traits allow you to group attributes together and then apply them
595
904
  to any factory.
596
905
 
@@ -598,25 +907,25 @@ to any factory.
598
907
  factory :user, aliases: [:author]
599
908
 
600
909
  factory :story do
601
- title "My awesome story"
910
+ title { "My awesome story" }
602
911
  author
603
912
 
604
913
  trait :published do
605
- published true
914
+ published { true }
606
915
  end
607
916
 
608
917
  trait :unpublished do
609
- published false
918
+ published { false }
610
919
  end
611
920
 
612
921
  trait :week_long_publishing do
613
922
  start_at { 1.week.ago }
614
- end_at { Time.now }
923
+ end_at { Time.now }
615
924
  end
616
925
 
617
926
  trait :month_long_publishing do
618
927
  start_at { 1.month.ago }
619
- end_at { Time.now }
928
+ end_at { Time.now }
620
929
  end
621
930
 
622
931
  factory :week_long_published_story, traits: [:published, :week_long_publishing]
@@ -626,7 +935,9 @@ factory :story do
626
935
  end
627
936
  ```
628
937
 
629
- Traits can be used as attributes:
938
+ ### As implicit attributes
939
+
940
+ Traits can be used as implicit attributes:
630
941
 
631
942
  ```ruby
632
943
  factory :week_long_published_story_with_title, parent: :story do
@@ -636,28 +947,33 @@ factory :week_long_published_story_with_title, parent: :story do
636
947
  end
637
948
  ```
638
949
 
950
+ Note that defining traits as implicit attributes will not work if you have a
951
+ factory or sequence with the same name as the trait.
952
+
953
+ ### Attribute precedence
954
+
639
955
  Traits that define the same attributes won't raise AttributeDefinitionErrors;
640
956
  the trait that defines the attribute latest gets precedence.
641
957
 
642
958
  ```ruby
643
959
  factory :user do
644
- name "Friendly User"
960
+ name { "Friendly User" }
645
961
  login { name }
646
962
 
647
963
  trait :male do
648
- name "John Doe"
649
- gender "Male"
964
+ name { "John Doe" }
965
+ gender { "Male" }
650
966
  login { "#{name} (M)" }
651
967
  end
652
968
 
653
969
  trait :female do
654
- name "Jane Doe"
655
- gender "Female"
970
+ name { "Jane Doe" }
971
+ gender { "Female" }
656
972
  login { "#{name} (F)" }
657
973
  end
658
974
 
659
975
  trait :admin do
660
- admin true
976
+ admin { true }
661
977
  login { "admin-#{name}" }
662
978
  end
663
979
 
@@ -666,39 +982,44 @@ factory :user do
666
982
  end
667
983
  ```
668
984
 
669
- 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:
670
988
 
671
989
  ```ruby
672
990
  factory :user do
673
- name "Friendly User"
991
+ name { "Friendly User" }
674
992
  login { name }
675
993
 
676
994
  trait :male do
677
- name "John Doe"
678
- gender "Male"
995
+ name { "John Doe" }
996
+ gender { "Male" }
679
997
  login { "#{name} (M)" }
680
998
  end
681
999
 
682
1000
  factory :brandon do
683
1001
  male
684
- name "Brandon"
1002
+ name { "Brandon" }
685
1003
  end
686
1004
  end
687
1005
  ```
688
1006
 
689
- 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.
690
1011
 
691
1012
  ```ruby
692
1013
  factory :user do
693
- name "Friendly User"
1014
+ name { "Friendly User" }
694
1015
 
695
1016
  trait :male do
696
- name "John Doe"
697
- gender "Male"
1017
+ name { "John Doe" }
1018
+ gender { "Male" }
698
1019
  end
699
1020
 
700
1021
  trait :admin do
701
- admin true
1022
+ admin { true }
702
1023
  end
703
1024
  end
704
1025
 
@@ -714,10 +1035,10 @@ the number of instances to create/build as second parameter, as documented in th
714
1035
 
715
1036
  ```ruby
716
1037
  factory :user do
717
- name "Friendly User"
1038
+ name { "Friendly User" }
718
1039
 
719
1040
  trait :admin do
720
- admin true
1041
+ admin { true }
721
1042
  end
722
1043
  end
723
1044
 
@@ -725,14 +1046,16 @@ end
725
1046
  create_list(:user, 3, :admin, :male, name: "Jon Snow")
726
1047
  ```
727
1048
 
1049
+ ### With associations
1050
+
728
1051
  Traits can be used with associations easily too:
729
1052
 
730
1053
  ```ruby
731
1054
  factory :user do
732
- name "Friendly User"
1055
+ name { "Friendly User" }
733
1056
 
734
1057
  trait :admin do
735
- admin true
1058
+ admin { true }
736
1059
  end
737
1060
  end
738
1061
 
@@ -748,10 +1071,10 @@ When you're using association names that're different than the factory:
748
1071
 
749
1072
  ```ruby
750
1073
  factory :user do
751
- name "Friendly User"
1074
+ name { "Friendly User" }
752
1075
 
753
1076
  trait :admin do
754
- admin true
1077
+ admin { true }
755
1078
  end
756
1079
  end
757
1080
 
@@ -765,6 +1088,8 @@ end
765
1088
  create(:post).author
766
1089
  ```
767
1090
 
1091
+ ### Traits within traits
1092
+
768
1093
  Traits can be used within other traits to mix in their attributes.
769
1094
 
770
1095
  ```ruby
@@ -780,13 +1105,15 @@ factory :order do
780
1105
  end
781
1106
  ```
782
1107
 
1108
+ ### With transient attributes
1109
+
783
1110
  Finally, traits can accept transient attributes.
784
1111
 
785
1112
  ```ruby
786
1113
  factory :invoice do
787
1114
  trait :with_amount do
788
1115
  transient do
789
- amount 1
1116
+ amount { 1 }
790
1117
  end
791
1118
 
792
1119
  after(:create) do |invoice, evaluator|
@@ -798,9 +1125,103 @@ end
798
1125
  create :invoice, :with_amount, amount: 2
799
1126
  ```
800
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
+
801
1220
  Callbacks
802
1221
  ---------
803
1222
 
1223
+ ### Default callbacks
1224
+
804
1225
  factory\_bot makes available four callbacks for injecting some code:
805
1226
 
806
1227
  * after(:build) - called after a factory is built (via `FactoryBot.build`, `FactoryBot.create`)
@@ -819,6 +1240,8 @@ end
819
1240
 
820
1241
  Note that you'll have an instance of the user in the block. This can be useful.
821
1242
 
1243
+ ### Multiple callbacks
1244
+
822
1245
  You can also define multiple types of callbacks on the same factory:
823
1246
 
824
1247
  ```ruby
@@ -828,7 +1251,8 @@ factory :user do
828
1251
  end
829
1252
  ```
830
1253
 
831
- 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:
832
1256
 
833
1257
  ```ruby
834
1258
  factory :user do
@@ -839,9 +1263,12 @@ end
839
1263
 
840
1264
  Calling `create` will invoke both `after_build` and `after_create` callbacks.
841
1265
 
842
- 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.
843
1268
 
844
- 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).
845
1272
 
846
1273
  ```ruby
847
1274
  factory :user do
@@ -851,6 +1278,8 @@ factory :user do
851
1278
  end
852
1279
  ```
853
1280
 
1281
+ ### Global callbacks
1282
+
854
1283
  To override callbacks for all factories, define them within the
855
1284
  `FactoryBot.define` block:
856
1285
 
@@ -860,12 +1289,14 @@ FactoryBot.define do
860
1289
  after(:create) { |object| AuditLog.create(attrs: object.attributes) }
861
1290
 
862
1291
  factory :user do
863
- name "John Doe"
1292
+ name { "John Doe" }
864
1293
  end
865
1294
  end
866
1295
  ```
867
1296
 
868
- 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`:
869
1300
 
870
1301
  ```ruby
871
1302
  # app/models/user.rb
@@ -888,17 +1319,18 @@ create(:user) # creates the user and confirms it
888
1319
  Modifying factories
889
1320
  -------------------
890
1321
 
891
- 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
892
- 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.
893
1325
 
894
1326
  If a gem were to give you a User factory:
895
1327
 
896
1328
  ```ruby
897
1329
  FactoryBot.define do
898
1330
  factory :user do
899
- full_name "John Doe"
1331
+ full_name { "John Doe" }
900
1332
  sequence(:username) { |n| "user#{n}" }
901
- password "password"
1333
+ password { "password" }
902
1334
  end
903
1335
  end
904
1336
  ```
@@ -908,10 +1340,10 @@ Instead of creating a child factory that added additional attributes:
908
1340
  ```ruby
909
1341
  FactoryBot.define do
910
1342
  factory :application_user, parent: :user do
911
- full_name "Jane Doe"
1343
+ full_name { "Jane Doe" }
912
1344
  date_of_birth { 21.years.ago }
913
- gender "Female"
914
- health 90
1345
+ gender { "Female" }
1346
+ health { 90 }
915
1347
  end
916
1348
  end
917
1349
  ```
@@ -921,10 +1353,10 @@ You could modify that factory instead.
921
1353
  ```ruby
922
1354
  FactoryBot.modify do
923
1355
  factory :user do
924
- full_name "Jane Doe"
1356
+ full_name { "Jane Doe" }
925
1357
  date_of_birth { 21.years.ago }
926
- gender "Female"
927
- health 90
1358
+ gender { "Female" }
1359
+ health { 90 }
928
1360
  end
929
1361
  end
930
1362
  ```
@@ -953,6 +1385,14 @@ To set the attributes for each of the factories, you can pass in a hash as you n
953
1385
  twenty_year_olds = build_list(:user, 25, date_of_birth: 20.years.ago)
954
1386
  ```
955
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
+
956
1396
  `build_stubbed_list` will give you fully stubbed out instances:
957
1397
 
958
1398
  ```ruby
@@ -975,7 +1415,7 @@ users_attrs = attributes_for_list(:user, 25) # array of attribute hashes
975
1415
  Linting Factories
976
1416
  -----------------
977
1417
 
978
- factory_bot allows for linting known factories:
1418
+ factory\_bot allows for linting known factories:
979
1419
 
980
1420
  ```ruby
981
1421
  FactoryBot.lint
@@ -1002,8 +1442,10 @@ namespace :factory_bot do
1002
1442
  desc "Verify that all FactoryBot factories are valid"
1003
1443
  task lint: :environment do
1004
1444
  if Rails.env.test?
1005
- DatabaseCleaner.cleaning do
1445
+ conn = ActiveRecord::Base.connection
1446
+ conn.transaction do
1006
1447
  FactoryBot.lint
1448
+ raise ActiveRecord::Rollback
1007
1449
  end
1008
1450
  else
1009
1451
  system("bundle exec rake factory_bot:lint RAILS_ENV='test'")
@@ -1015,8 +1457,7 @@ end
1015
1457
 
1016
1458
  After calling `FactoryBot.lint`, you'll likely want to clear out the
1017
1459
  database, as records will most likely be created. The provided example above
1018
- uses the database_cleaner gem to clear out the database; be sure to add the
1019
- gem to your Gemfile under the appropriate groups.
1460
+ uses an sql transaction and rollback to leave the database clean.
1020
1461
 
1021
1462
  You can lint factories selectively by passing only factories you want linted:
1022
1463
 
@@ -1050,10 +1491,17 @@ You can also specify the strategy used for linting:
1050
1491
  FactoryBot.lint strategy: :build
1051
1492
  ```
1052
1493
 
1494
+ Verbose linting will include full backtraces for each error, which can be
1495
+ helpful for debugging:
1496
+
1497
+ ```ruby
1498
+ FactoryBot.lint verbose: true
1499
+ ```
1500
+
1053
1501
  Custom Construction
1054
1502
  -------------------
1055
1503
 
1056
- 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
1057
1505
  are passed to `initialize` or if you want to do something other than simply
1058
1506
  calling `new` on your build class, you can override the default behavior by
1059
1507
  defining `initialize_with` on your factory. Example:
@@ -1072,7 +1520,7 @@ end
1072
1520
  sequence(:email) { |n| "person#{n}@example.com" }
1073
1521
 
1074
1522
  factory :user do
1075
- name "Jane Doe"
1523
+ name { "Jane Doe" }
1076
1524
  email
1077
1525
 
1078
1526
  initialize_with { new(name) }
@@ -1081,7 +1529,7 @@ end
1081
1529
  build(:user).name # Jane Doe
1082
1530
  ```
1083
1531
 
1084
- 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
1085
1533
  can also work with any Ruby class. For maximum compatibility with ActiveRecord,
1086
1534
  the default initializer builds all instances by calling `new` on your build class
1087
1535
  without any arguments. It then calls attribute writer methods to assign all the
@@ -1092,7 +1540,7 @@ You can override the initializer in order to:
1092
1540
 
1093
1541
  * Build non-ActiveRecord objects that require arguments to `initialize`
1094
1542
  * Use a method other than `new` to instantiate the instance
1095
- * Do crazy things like decorate the instance after it's built
1543
+ * Do wild things like decorate the instance after it's built
1096
1544
 
1097
1545
  When using `initialize_with`, you don't have to declare the class itself when
1098
1546
  calling `new`; however, any other class methods you want to call will have to
@@ -1102,7 +1550,7 @@ For example:
1102
1550
 
1103
1551
  ```ruby
1104
1552
  factory :user do
1105
- name "John Doe"
1553
+ name { "John Doe" }
1106
1554
 
1107
1555
  initialize_with { User.build_with_name(name) }
1108
1556
  end
@@ -1114,7 +1562,7 @@ by calling `attributes`:
1114
1562
  ```ruby
1115
1563
  factory :user do
1116
1564
  transient do
1117
- comments_count 5
1565
+ comments_count { 5 }
1118
1566
  end
1119
1567
 
1120
1568
  name "John Doe"
@@ -1125,7 +1573,7 @@ end
1125
1573
 
1126
1574
  This will build a hash of all attributes to be passed to `new`. It won't
1127
1575
  include transient attributes, but everything else defined in the factory will be
1128
- passed (associations, evalued sequences, etc.)
1576
+ passed (associations, evaluated sequences, etc.)
1129
1577
 
1130
1578
  You can define `initialize_with` for all factories by including it in the
1131
1579
  `FactoryBot.define` block:
@@ -1154,7 +1602,7 @@ build(:user)
1154
1602
  User.new('value')
1155
1603
  ```
1156
1604
 
1157
- 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
1158
1606
  would run this:
1159
1607
 
1160
1608
  ```ruby
@@ -1287,7 +1735,7 @@ FactoryBot.define do
1287
1735
 
1288
1736
 
1289
1737
  factory :user do
1290
- name "John Doe"
1738
+ name { "John Doe" }
1291
1739
  end
1292
1740
  end
1293
1741
  ```
@@ -1340,13 +1788,13 @@ with associations, as below:
1340
1788
 
1341
1789
  ```ruby
1342
1790
  FactoryBot.define do
1343
- factory :united_states, class: Location do
1344
- name 'United States'
1791
+ factory :united_states, class: "Location" do
1792
+ name { 'United States' }
1345
1793
  association :location_group, factory: :north_america
1346
1794
  end
1347
1795
 
1348
- factory :north_america, class: LocationGroup do
1349
- name 'North America'
1796
+ factory :north_america, class: "LocationGroup" do
1797
+ name { 'North America' }
1350
1798
  end
1351
1799
  end
1352
1800
  ```
@@ -1378,7 +1826,7 @@ require 'factory_bot'
1378
1826
  ```
1379
1827
 
1380
1828
  Once required, assuming you have a directory structure of `spec/factories` or
1381
- `test/factories`, all you'll need to do is run
1829
+ `test/factories`, all you'll need to do is run:
1382
1830
 
1383
1831
  ```ruby
1384
1832
  FactoryBot.find_definitions
@@ -1400,7 +1848,7 @@ require 'factory_bot'
1400
1848
 
1401
1849
  FactoryBot.define do
1402
1850
  factory :user do
1403
- name 'John Doe'
1851
+ name { 'John Doe' }
1404
1852
  date_of_birth { 21.years.ago }
1405
1853
  end
1406
1854
  end