factory_bot 4.10.0 → 6.0.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 +613 -182
  5. data/LICENSE +1 -1
  6. data/NEWS.md +358 -0
  7. data/README.md +30 -26
  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 +14 -1
  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 +5 -5
  23. data/lib/factory_bot/decorator/attribute_hash.rb +1 -1
  24. data/lib/factory_bot/decorator/invocation_tracker.rb +1 -1
  25. data/lib/factory_bot/definition.rb +49 -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 +9 -11
  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: 2f060c0b183a1d65b69542b917a19ad16d1de52d7f69dd692839eceaa316ad2a
4
+ data.tar.gz: 4f2286b4cabd1b562352fed5d20f00ba29a7ede89c8a855657f0f0075527d0f4
5
5
  SHA512:
6
- metadata.gz: 9583c5fb81fd3be6241566123cc1ffa590f54cc58c441868aff8efb679405b2c52bf38fd8ca9c3a4bf89079d12505d64565161ff300fca3d186cfcafc3573dd6
7
- data.tar.gz: 10723a4fdc450038aa2d515e3df7ff26d59d634439e6632daa44ba91f6ca87491f52edfb9c9595da8fd3621dda4a2b707dd8523c4eb42c156fda04411d75c332
6
+ metadata.gz: 67230581c94a6e476ba8fa8aeb123d2ccfe18cd14af2d9d292cc871d9d1dda63cbd827e455c165f9eac7211fe9770fd41b87ab349db55a000e32ee23a319fda1
7
+ data.tar.gz: 8ce7be2d33e08ddc24c50082a2025c7c59877457558720dfbdc4920e70f881e30a52cfb322fe129ae9690b512bbf42059bb24db973c81b3a585d8693ff484a1c
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
@@ -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,42 +1,117 @@
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`:
8
-
9
- ```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
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
+ * [Traits](#traits)
56
+ + [Defining traits](#defining-traits)
57
+ + [As implicit attributes](#as-implicit-attributes-1)
58
+ + [Attribute precedence](#attribute-precedence)
59
+ + [In child factories](#in-child-factories)
60
+ + [Using traits](#using-traits)
61
+ + [With associations](#with-associations-1)
62
+ + [Traits within traits](#traits-within-traits)
63
+ + [With transient attributes](#with-transient-attributes)
64
+ + [Enum traits](#enum-traits)
65
+ * [Callbacks](#callbacks)
66
+ + [Default callbacks](#default-callbacks)
67
+ + [Multiple callbacks](#multiple-callbacks)
68
+ + [Global callbacks](#global-callbacks)
69
+ + [Symbol#to_proc](#symbolto_proc)
70
+ * [Modifying factories](#modifying-factories)
71
+ * [Building or Creating Multiple Records](#building-or-creating-multiple-records)
72
+ * [Linting Factories](#linting-factories)
73
+ * [Custom Construction](#custom-construction)
74
+ * [Custom Strategies](#custom-strategies)
75
+ * [Custom Callbacks](#custom-callbacks)
76
+ * [Custom Methods to Persist Objects](#custom-methods-to-persist-objects)
77
+ * [ActiveSupport Instrumentation](#activesupport-instrumentation)
78
+ * [Rails Preloaders and RSpec](#rails-preloaders-and-rspec)
79
+ * [Using Without Bundler](#using-without-bundler)
80
+
81
+ Setup
82
+ -----
83
+
84
+ ### Update Your Gemfile
85
+
86
+ If you're using Rails:
87
+
88
+ ```ruby
89
+ gem "factory_bot_rails"
90
+ ```
91
+
92
+ If you're *not* using Rails:
93
+
94
+ ```ruby
95
+ gem "factory_bot"
96
+ ```
97
+
98
+ ### Configure your test suite
99
+
100
+ #### RSpec
101
+
102
+ If you're using Rails, add the following configuration to
103
+ `spec/support/factory_bot.rb` and be sure to require that file in
104
+ `rails_helper.rb`:
32
105
 
33
106
  ```ruby
34
- # spec/support/factory_bot.rb
35
107
  RSpec.configure do |config|
36
108
  config.include FactoryBot::Syntax::Methods
37
109
  end
110
+ ```
38
111
 
39
- # RSpec without Rails
112
+ If you're *not* using Rails:
113
+
114
+ ```ruby
40
115
  RSpec.configure do |config|
41
116
  config.include FactoryBot::Syntax::Methods
42
117
 
@@ -46,13 +121,7 @@ RSpec.configure do |config|
46
121
  end
47
122
  ```
48
123
 
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
124
+ #### Test::Unit
56
125
 
57
126
  ```ruby
58
127
  class Test::Unit::TestCase
@@ -60,14 +129,14 @@ class Test::Unit::TestCase
60
129
  end
61
130
  ```
62
131
 
63
- ### Cucumber
132
+ #### Cucumber
64
133
 
65
134
  ```ruby
66
135
  # env.rb (Rails example location - RAILS_ROOT/features/support/env.rb)
67
136
  World(FactoryBot::Syntax::Methods)
68
137
  ```
69
138
 
70
- ### Spinach
139
+ #### Spinach
71
140
 
72
141
  ```ruby
73
142
  class Spinach::FeatureSteps
@@ -75,7 +144,7 @@ class Spinach::FeatureSteps
75
144
  end
76
145
  ```
77
146
 
78
- ### Minitest
147
+ #### Minitest
79
148
 
80
149
  ```ruby
81
150
  class Minitest::Unit::TestCase
@@ -83,7 +152,7 @@ class Minitest::Unit::TestCase
83
152
  end
84
153
  ```
85
154
 
86
- ### Minitest::Spec
155
+ #### Minitest::Spec
87
156
 
88
157
  ```ruby
89
158
  class Minitest::Spec
@@ -91,7 +160,7 @@ class Minitest::Spec
91
160
  end
92
161
  ```
93
162
 
94
- ### minitest-rails
163
+ #### minitest-rails
95
164
 
96
165
  ```ruby
97
166
  class ActiveSupport::TestCase
@@ -99,35 +168,71 @@ class ActiveSupport::TestCase
99
168
  end
100
169
  ```
101
170
 
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`.
171
+ If you do not include `FactoryBot::Syntax::Methods` in your test suite, then all
172
+ factory\_bot methods will need to be prefaced with `FactoryBot`.
103
173
 
104
174
  Defining factories
105
175
  ------------------
106
176
 
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:
177
+ ### Factory name and attributes
178
+
179
+ Each factory has a name and a set of attributes. The name is used to guess the
180
+ class of the object by default:
108
181
 
109
182
  ```ruby
110
183
  # This will guess the User class
111
184
  FactoryBot.define do
112
185
  factory :user do
113
- first_name "John"
114
- last_name "Doe"
115
- admin false
186
+ first_name { "John" }
187
+ last_name { "Doe" }
188
+ admin { false }
116
189
  end
190
+ end
191
+ ```
117
192
 
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
193
+ ### Specifying the class explicitly
194
+
195
+ It is also possible to explicitly specify the class:
196
+
197
+ ```ruby
198
+ # This will use the User class (otherwise Admin would have been guessed)
199
+ factory :admin, class: User
200
+ ```
201
+
202
+ If the constant is not available
203
+ (if you are using a Rails engine that waits to load models, for example),
204
+ you can also pass a symbol or string,
205
+ which factory\_bot will constantize later, once you start building objects:
206
+
207
+ ```ruby
208
+ # It's OK if Doorkeeper::AccessToken isn't loaded yet
209
+ factory :access_token, class: "Doorkeeper::AccessToken"
210
+ ```
211
+
212
+ ### Hash attributes
213
+
214
+ Because of the block syntax in Ruby, defining attributes as `Hash`es (for
215
+ serialized/JSON columns, for example) requires two sets of curly brackets:
216
+
217
+ ```ruby
218
+ factory :program do
219
+ configuration { { auto_resolve: false, auto_define: true } }
124
220
  end
125
221
  ```
126
222
 
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.
223
+ ### Best practices
224
+
225
+ It is recommended that you have one factory for each class that provides
226
+ the simplest set of attributes necessary to create an instance of that class. If
227
+ you're creating ActiveRecord objects, that means that you should only provide
228
+ attributes that are required through validations and that do not have defaults.
229
+ Other factories can be created through inheritance to cover common scenarios for
230
+ each class.
128
231
 
129
232
  Attempting to define multiple factories with the same name will raise an error.
130
233
 
234
+ ### Definition file paths
235
+
131
236
  Factories can be defined anywhere, but will be automatically loaded after
132
237
  calling `FactoryBot.find_definitions` if factories are defined in files at the
133
238
  following locations:
@@ -137,10 +242,20 @@ following locations:
137
242
  test/factories/*.rb
138
243
  spec/factories/*.rb
139
244
 
245
+ ### Static Attributes
246
+
247
+ Static attributes (without a block) are no longer available in factory\_bot 5.
248
+ You can read more about the decision to remove them in
249
+ [this blog post](https://robots.thoughtbot.com/deprecating-static-attributes-in-factory_bot-4-11).
250
+
251
+
140
252
  Using factories
141
253
  ---------------
142
254
 
143
- factory\_bot supports several different build strategies: build, create, attributes\_for and build\_stubbed:
255
+ ### Build strategies
256
+
257
+ factory\_bot supports several different build strategies: build, create,
258
+ attributes\_for and build\_stubbed:
144
259
 
145
260
  ```ruby
146
261
  # Returns a User instance that's not saved
@@ -161,7 +276,10 @@ create(:user) do |user|
161
276
  end
162
277
  ```
163
278
 
164
- No matter which strategy is used, it's possible to override the defined attributes by passing a hash:
279
+ ### Attribute overrides
280
+
281
+ No matter which strategy is used, it's possible to override the defined
282
+ attributes by passing a hash:
165
283
 
166
284
  ```ruby
167
285
  # Build a User instance and override the first_name property
@@ -170,40 +288,25 @@ user.first_name
170
288
  # => "Joe"
171
289
  ```
172
290
 
173
- Dynamic Attributes
174
- ------------------
175
-
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
- ```
291
+ ### `build_stubbed` and `Marshal.dump`
189
292
 
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
- ```
293
+ Note that objects created with `build_stubbed` cannot be serialized with
294
+ `Marshal.dump`, since factory\_bot defines singleton methods on these objects.
198
295
 
199
296
  Aliases
200
297
  -------
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.
298
+
299
+ factory\_bot allows you to define aliases to existing factories to make them
300
+ easier to re-use. This could come in handy when, for example, your Post object
301
+ has an author attribute that actually refers to an instance of a User class.
302
+ While normally factory\_bot can infer the factory name from the association name,
303
+ in this case it will look for an author factory in vain. So, alias your user
304
+ factory so it can be used under alias names.
202
305
 
203
306
  ```ruby
204
307
  factory :user, aliases: [:author, :commenter] do
205
- first_name "John"
206
- last_name "Doe"
308
+ first_name { "John" }
309
+ last_name { "Doe" }
207
310
  date_of_birth { 18.years.ago }
208
311
  end
209
312
 
@@ -211,15 +314,15 @@ factory :post do
211
314
  author
212
315
  # instead of
213
316
  # association :author, factory: :user
214
- title "How to read a book effectively"
215
- body "There are five steps involved."
317
+ title { "How to read a book effectively" }
318
+ body { "There are five steps involved." }
216
319
  end
217
320
 
218
321
  factory :comment do
219
322
  commenter
220
323
  # instead of
221
324
  # association :commenter, factory: :user
222
- body "Great article!"
325
+ body { "Great article!" }
223
326
  end
224
327
  ```
225
328
 
@@ -231,8 +334,8 @@ that is yielded to dynamic attribute blocks:
231
334
 
232
335
  ```ruby
233
336
  factory :user do
234
- first_name "Joe"
235
- last_name "Blow"
337
+ first_name { "Joe" }
338
+ last_name { "Blow" }
236
339
  email { "#{first_name}.#{last_name}@example.com".downcase }
237
340
  end
238
341
 
@@ -243,40 +346,82 @@ create(:user, last_name: "Doe").email
243
346
  Transient Attributes
244
347
  --------------------
245
348
 
246
- There may be times where your code can be DRYed up by passing in transient attributes to factories.
349
+ ### With other attributes
350
+
351
+ There may be times where your code can be DRYed up by passing in transient
352
+ attributes to factories. You can access transient attributes within other
353
+ attributes (see [Dependent Attributes](#dependent-attributes)):
354
+
355
+ ```ruby
356
+ factory :user do
357
+ transient do
358
+ rockstar { true }
359
+ end
360
+
361
+ name { "John Doe#{" - Rockstar" if rockstar}" }
362
+ end
363
+
364
+ create(:user).name
365
+ #=> "John Doe - ROCKSTAR"
366
+
367
+ create(:user, rockstar: false).name
368
+ #=> "John Doe"
369
+ ```
370
+
371
+ ### With `attributes_for`
372
+
373
+ Transient attributes will be ignored within attributes\_for and won't be set on
374
+ the model, even if the attribute exists or you attempt to override it.
375
+
376
+ ### With callbacks
377
+
378
+ If you need to access the evaluator in a factory\_bot callback,
379
+ you'll need to declare a second block argument (for the evaluator) and access
380
+ transient attributes from there.
247
381
 
248
382
  ```ruby
249
383
  factory :user do
250
384
  transient do
251
- rockstar true
252
- upcased false
385
+ upcased { false }
253
386
  end
254
387
 
255
- name { "John Doe#{" - Rockstar" if rockstar}" }
256
- email { "#{name.downcase}@example.com" }
388
+ name { "John Doe" }
257
389
 
258
390
  after(:create) do |user, evaluator|
259
391
  user.name.upcase! if evaluator.upcased
260
392
  end
261
393
  end
262
394
 
395
+ create(:user).name
396
+ #=> "John Doe"
397
+
263
398
  create(:user, upcased: true).name
264
- #=> "JOHN DOE - ROCKSTAR"
399
+ #=> "JOHN DOE"
265
400
  ```
266
401
 
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.
402
+ ### With associations
270
403
 
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.
404
+ Transient [associations](#associations) are not supported in factory\_bot.
405
+ Associations within the transient block will be treated as regular,
406
+ non-transient associations.
407
+
408
+ If needed, you can generally work around this by building a factory within a
409
+ transient attribute:
410
+
411
+ ```ruby
412
+ factory :post
413
+
414
+ factory :user do
415
+ transient do
416
+ post { build(:post) }
417
+ end
418
+ end
419
+ ```
275
420
 
276
421
  Method Name / Reserved Word Attributes
277
422
  -------------------------------
278
423
 
279
- If your attributes conflict with existing methods or reserved words you can define them with `add_attribute`.
424
+ 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
425
 
281
426
  ```ruby
282
427
  factory :dna do
@@ -292,14 +437,17 @@ end
292
437
  Inheritance
293
438
  -----------
294
439
 
295
- You can easily create multiple factories for the same class without repeating common attributes by nesting factories:
440
+ ### Nested factories
441
+
442
+ You can easily create multiple factories for the same class without repeating
443
+ common attributes by nesting factories:
296
444
 
297
445
  ```ruby
298
446
  factory :post do
299
- title "A title"
447
+ title { "A title" }
300
448
 
301
449
  factory :approved_post do
302
- approved true
450
+ approved { true }
303
451
  end
304
452
  end
305
453
 
@@ -308,18 +456,22 @@ approved_post.title # => "A title"
308
456
  approved_post.approved # => true
309
457
  ```
310
458
 
459
+ ### Assigning parent explicitly
460
+
311
461
  You can also assign the parent explicitly:
312
462
 
313
463
  ```ruby
314
464
  factory :post do
315
- title "A title"
465
+ title { "A title" }
316
466
  end
317
467
 
318
468
  factory :approved_post, parent: :post do
319
- approved true
469
+ approved { true }
320
470
  end
321
471
  ```
322
472
 
473
+ ### Best practices
474
+
323
475
  As mentioned above, it's good practice to define a basic factory for each class
324
476
  with only the attributes required to create it. Then, create more specific
325
477
  factories that inherit from this basic parent. Factory definitions are still
@@ -328,7 +480,10 @@ code, so keep them DRY.
328
480
  Associations
329
481
  ------------
330
482
 
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.
483
+ ### Implicit definition
484
+
485
+ It's possible to set up associations within factories. If the factory name is
486
+ the same as the association name, the factory name can be left out.
332
487
 
333
488
  ```ruby
334
489
  factory :post do
@@ -337,18 +492,95 @@ factory :post do
337
492
  end
338
493
  ```
339
494
 
340
- You can also specify a different factory or override attributes:
495
+ ### Explicit definition
496
+
497
+ You can define associations explicitly. This can be handy especially when
498
+ [Overriding attributes](#overriding-attributes)
499
+
500
+ ```ruby
501
+ factory :post do
502
+ # ...
503
+ association :author
504
+ end
505
+ ```
506
+
507
+ ### Specifying the factory
508
+
509
+ You can specify a different factory (although [Aliases](#aliases) might also
510
+ help you out here).
511
+
512
+ Implicitly:
513
+
514
+ ```ruby
515
+ factory :post do
516
+ # ...
517
+ author factory: :user
518
+ end
519
+ ```
520
+
521
+ Explicitly:
522
+
523
+ ```ruby
524
+ factory :post do
525
+ # ...
526
+ association :author, factory: :user
527
+ end
528
+ ```
529
+
530
+ ### Overriding attributes
531
+
532
+ You can also override attributes.
533
+
534
+ Implicitly:
535
+
536
+ ```ruby
537
+ factory :post do
538
+ # ...
539
+ author factory: :author, last_name: "Writely"
540
+ end
541
+ ```
542
+
543
+ Explicitly:
544
+
341
545
 
342
546
  ```ruby
343
547
  factory :post do
344
548
  # ...
345
- association :author, factory: :user, last_name: "Writely"
549
+ association :author, last_name: "Writely"
550
+ end
551
+ ```
552
+
553
+ ### Build strategies
554
+
555
+ In factory\_bot 5, associations default to using the same build strategy as
556
+ their parent object:
557
+
558
+ ```ruby
559
+ FactoryBot.define do
560
+ factory :author
561
+
562
+ factory :post do
563
+ author
564
+ end
346
565
  end
566
+
567
+ post = build(:post)
568
+ post.new_record? # => true
569
+ post.author.new_record? # => true
570
+
571
+ post = create(:post)
572
+ post.new_record? # => false
573
+ post.author.new_record? # => false
347
574
  ```
348
575
 
349
- The behavior of the association method varies depending on the build strategy used for the parent object.
576
+ This is different than the default behavior for previous versions of
577
+ factory\_bot, where the association strategy would not always match the strategy
578
+ of the parent object. If you want to continue using the old behavior, you can
579
+ set the `use_parent_strategy` configuration option to `false`.
350
580
 
351
581
  ```ruby
582
+ FactoryBot.use_parent_strategy = false
583
+
352
584
  # Builds and saves a User and a Post
353
585
  post = create(:post)
354
586
  post.new_record? # => false
@@ -360,9 +592,11 @@ post.new_record? # => true
360
592
  post.author.new_record? # => false
361
593
  ```
362
594
 
363
- To not save the associated object, specify strategy: :build in the factory:
595
+ To not save the associated object, specify `strategy: :build` in the factory:
364
596
 
365
597
  ```ruby
598
+ FactoryBot.use_parent_strategy = false
599
+
366
600
  factory :post do
367
601
  # ...
368
602
  association :author, factory: :user, strategy: :build
@@ -383,6 +617,8 @@ factory :post do
383
617
  author strategy: :build # <<< this does *not* work; causes author_id to be nil
384
618
  ```
385
619
 
620
+ ### `has_many` associations
621
+
386
622
  Generating data for a `has_many` relationship is a bit more involved,
387
623
  depending on the amount of flexibility desired, but here's a surefire example
388
624
  of generating associated data.
@@ -392,20 +628,20 @@ FactoryBot.define do
392
628
 
393
629
  # post factory with a `belongs_to` association for the user
394
630
  factory :post do
395
- title "Through the Looking Glass"
631
+ title { "Through the Looking Glass" }
396
632
  user
397
633
  end
398
634
 
399
635
  # user factory without associated posts
400
636
  factory :user do
401
- name "John Doe"
637
+ name { "John Doe" }
402
638
 
403
639
  # user_with_posts will create post data after the user has been created
404
640
  factory :user_with_posts do
405
641
  # posts_count is declared as a transient attribute and available in
406
642
  # attributes on the factory, as well as the callback via the evaluator
407
643
  transient do
408
- posts_count 5
644
+ posts_count { 5 }
409
645
  end
410
646
 
411
647
  # the after(:create) yields two values; the user instance itself and the
@@ -428,6 +664,8 @@ create(:user_with_posts).posts.length # 5
428
664
  create(:user_with_posts, posts_count: 15).posts.length # 15
429
665
  ```
430
666
 
667
+ ### `has_and_belongs_to_many` associations
668
+
431
669
  Generating data for a `has_and_belongs_to_many` relationship is very similar
432
670
  to the above `has_many` relationship, with a small change, you need to pass an
433
671
  array of objects to the model's pluralized attribute name rather than a single
@@ -441,13 +679,13 @@ FactoryBot.define do
441
679
 
442
680
  # language factory with a `belongs_to` association for the profile
443
681
  factory :language do
444
- title "Through the Looking Glass"
682
+ title { "Through the Looking Glass" }
445
683
  profile
446
684
  end
447
685
 
448
686
  # profile factory without associated languages
449
687
  factory :profile do
450
- name "John Doe"
688
+ name { "John Doe" }
451
689
 
452
690
  # profile_with_languages will create language data after the profile has
453
691
  # been created
@@ -455,7 +693,7 @@ FactoryBot.define do
455
693
  # languages_count is declared as an ignored attribute and available in
456
694
  # attributes on the factory, as well as the callback via the evaluator
457
695
  transient do
458
- languages_count 5
696
+ languages_count { 5 }
459
697
  end
460
698
 
461
699
  # the after(:create) yields two values; the profile instance itself and
@@ -479,9 +717,43 @@ create(:profile_with_languages).languages.length # 5
479
717
  create(:profile_with_languages, languages_count: 15).languages.length # 15
480
718
  ```
481
719
 
720
+ ### Polymorphic associations
721
+
722
+ Polymorphic associations can be handled with traits:
723
+
724
+ ```ruby
725
+ FactoryBot.define do
726
+ factory :video
727
+ factory :photo
728
+
729
+ factory :comment do
730
+ for_photo # default to the :for_photo trait if none is specified
731
+
732
+ trait :for_video do
733
+ association :commentable, factory: :video
734
+ end
735
+
736
+ trait :for_photo do
737
+ association :commentable, factory: :photo
738
+ end
739
+ end
740
+ end
741
+ ```
742
+
743
+ This allows us to do:
744
+
745
+ ```ruby
746
+ create(:comment)
747
+ create(:comment, :for_video)
748
+ create(:comment, :for_photo)
749
+ ```
750
+
751
+
482
752
  Sequences
483
753
  ---------
484
754
 
755
+ ### Global sequences
756
+
485
757
  Unique values in a specific format (for example, e-mail addresses) can be
486
758
  generated using sequences. Sequences are defined by calling `sequence` in a
487
759
  definition block, and values in a sequence are generated by calling
@@ -502,6 +774,8 @@ generate :email
502
774
  # => "person2@example.com"
503
775
  ```
504
776
 
777
+ ### With dynamic attributes
778
+
505
779
  Sequences can be used in dynamic attributes:
506
780
 
507
781
  ```ruby
@@ -510,6 +784,8 @@ factory :invite do
510
784
  end
511
785
  ```
512
786
 
787
+ ### As implicit attributes
788
+
513
789
  Or as implicit attributes:
514
790
 
515
791
  ```ruby
@@ -518,6 +794,11 @@ factory :user do
518
794
  end
519
795
  ```
520
796
 
797
+ Note that defining sequences as implicit attributes will not work if you have a
798
+ factory with the same name as the sequence.
799
+
800
+ ### Inline sequences
801
+
521
802
  And it's also possible to define an in-line sequence that is only used in
522
803
  a particular factory:
523
804
 
@@ -527,7 +808,10 @@ factory :user do
527
808
  end
528
809
  ```
529
810
 
530
- You can also override the initial value:
811
+ ### Initial value
812
+
813
+ You can override the initial value. Any value that response to the `#next`
814
+ method will work (e.g. 1, 2, 3, 'a', 'b', 'c')
531
815
 
532
816
  ```ruby
533
817
  factory :user do
@@ -535,6 +819,8 @@ factory :user do
535
819
  end
536
820
  ```
537
821
 
822
+ ### Without a block
823
+
538
824
  Without a block, the value will increment itself, starting at its initial value:
539
825
 
540
826
  ```ruby
@@ -543,6 +829,8 @@ factory :post do
543
829
  end
544
830
  ```
545
831
 
832
+ ### Aliases
833
+
546
834
  Sequences can also have aliases. The sequence aliases share the same counter:
547
835
 
548
836
  ```ruby
@@ -572,6 +860,8 @@ end
572
860
 
573
861
  The value just needs to support the `#next` method. Here the next value will be 'a', then 'b', etc.
574
862
 
863
+ ### Rewinding
864
+
575
865
  Sequences can also be rewound with `FactoryBot.rewind_sequences`:
576
866
 
577
867
  ```ruby
@@ -591,6 +881,8 @@ This rewinds all registered sequences.
591
881
  Traits
592
882
  ------
593
883
 
884
+ ### Defining traits
885
+
594
886
  Traits allow you to group attributes together and then apply them
595
887
  to any factory.
596
888
 
@@ -598,25 +890,25 @@ to any factory.
598
890
  factory :user, aliases: [:author]
599
891
 
600
892
  factory :story do
601
- title "My awesome story"
893
+ title { "My awesome story" }
602
894
  author
603
895
 
604
896
  trait :published do
605
- published true
897
+ published { true }
606
898
  end
607
899
 
608
900
  trait :unpublished do
609
- published false
901
+ published { false }
610
902
  end
611
903
 
612
904
  trait :week_long_publishing do
613
905
  start_at { 1.week.ago }
614
- end_at { Time.now }
906
+ end_at { Time.now }
615
907
  end
616
908
 
617
909
  trait :month_long_publishing do
618
910
  start_at { 1.month.ago }
619
- end_at { Time.now }
911
+ end_at { Time.now }
620
912
  end
621
913
 
622
914
  factory :week_long_published_story, traits: [:published, :week_long_publishing]
@@ -626,7 +918,9 @@ factory :story do
626
918
  end
627
919
  ```
628
920
 
629
- Traits can be used as attributes:
921
+ ### As implicit attributes
922
+
923
+ Traits can be used as implicit attributes:
630
924
 
631
925
  ```ruby
632
926
  factory :week_long_published_story_with_title, parent: :story do
@@ -636,28 +930,33 @@ factory :week_long_published_story_with_title, parent: :story do
636
930
  end
637
931
  ```
638
932
 
933
+ Note that defining traits as implicit attributes will not work if you have a
934
+ factory or sequence with the same name as the trait.
935
+
936
+ ### Attribute precedence
937
+
639
938
  Traits that define the same attributes won't raise AttributeDefinitionErrors;
640
939
  the trait that defines the attribute latest gets precedence.
641
940
 
642
941
  ```ruby
643
942
  factory :user do
644
- name "Friendly User"
943
+ name { "Friendly User" }
645
944
  login { name }
646
945
 
647
946
  trait :male do
648
- name "John Doe"
649
- gender "Male"
947
+ name { "John Doe" }
948
+ gender { "Male" }
650
949
  login { "#{name} (M)" }
651
950
  end
652
951
 
653
952
  trait :female do
654
- name "Jane Doe"
655
- gender "Female"
953
+ name { "Jane Doe" }
954
+ gender { "Female" }
656
955
  login { "#{name} (F)" }
657
956
  end
658
957
 
659
958
  trait :admin do
660
- admin true
959
+ admin { true }
661
960
  login { "admin-#{name}" }
662
961
  end
663
962
 
@@ -666,39 +965,44 @@ factory :user do
666
965
  end
667
966
  ```
668
967
 
669
- You can also override individual attributes granted by a trait in subclasses.
968
+ ### In child factories
969
+
970
+ You can override individual attributes granted by a trait in a child factory:
670
971
 
671
972
  ```ruby
672
973
  factory :user do
673
- name "Friendly User"
974
+ name { "Friendly User" }
674
975
  login { name }
675
976
 
676
977
  trait :male do
677
- name "John Doe"
678
- gender "Male"
978
+ name { "John Doe" }
979
+ gender { "Male" }
679
980
  login { "#{name} (M)" }
680
981
  end
681
982
 
682
983
  factory :brandon do
683
984
  male
684
- name "Brandon"
985
+ name { "Brandon" }
685
986
  end
686
987
  end
687
988
  ```
688
989
 
689
- Traits can also be passed in as a list of symbols when you construct an instance from factory_bot.
990
+ ### Using traits
991
+
992
+ Traits can also be passed in as a list of symbols when you construct an instance
993
+ from factory\_bot.
690
994
 
691
995
  ```ruby
692
996
  factory :user do
693
- name "Friendly User"
997
+ name { "Friendly User" }
694
998
 
695
999
  trait :male do
696
- name "John Doe"
697
- gender "Male"
1000
+ name { "John Doe" }
1001
+ gender { "Male" }
698
1002
  end
699
1003
 
700
1004
  trait :admin do
701
- admin true
1005
+ admin { true }
702
1006
  end
703
1007
  end
704
1008
 
@@ -714,10 +1018,10 @@ the number of instances to create/build as second parameter, as documented in th
714
1018
 
715
1019
  ```ruby
716
1020
  factory :user do
717
- name "Friendly User"
1021
+ name { "Friendly User" }
718
1022
 
719
1023
  trait :admin do
720
- admin true
1024
+ admin { true }
721
1025
  end
722
1026
  end
723
1027
 
@@ -725,14 +1029,16 @@ end
725
1029
  create_list(:user, 3, :admin, :male, name: "Jon Snow")
726
1030
  ```
727
1031
 
1032
+ ### With associations
1033
+
728
1034
  Traits can be used with associations easily too:
729
1035
 
730
1036
  ```ruby
731
1037
  factory :user do
732
- name "Friendly User"
1038
+ name { "Friendly User" }
733
1039
 
734
1040
  trait :admin do
735
- admin true
1041
+ admin { true }
736
1042
  end
737
1043
  end
738
1044
 
@@ -748,10 +1054,10 @@ When you're using association names that're different than the factory:
748
1054
 
749
1055
  ```ruby
750
1056
  factory :user do
751
- name "Friendly User"
1057
+ name { "Friendly User" }
752
1058
 
753
1059
  trait :admin do
754
- admin true
1060
+ admin { true }
755
1061
  end
756
1062
  end
757
1063
 
@@ -765,6 +1071,8 @@ end
765
1071
  create(:post).author
766
1072
  ```
767
1073
 
1074
+ ### Traits within traits
1075
+
768
1076
  Traits can be used within other traits to mix in their attributes.
769
1077
 
770
1078
  ```ruby
@@ -780,13 +1088,15 @@ factory :order do
780
1088
  end
781
1089
  ```
782
1090
 
1091
+ ### With transient attributes
1092
+
783
1093
  Finally, traits can accept transient attributes.
784
1094
 
785
1095
  ```ruby
786
1096
  factory :invoice do
787
1097
  trait :with_amount do
788
1098
  transient do
789
- amount 1
1099
+ amount { 1 }
790
1100
  end
791
1101
 
792
1102
  after(:create) do |invoice, evaluator|
@@ -798,9 +1108,103 @@ end
798
1108
  create :invoice, :with_amount, amount: 2
799
1109
  ```
800
1110
 
1111
+ ### Enum traits
1112
+
1113
+ Given an Active Record model with an enum attribute:
1114
+
1115
+ ```rb
1116
+ class Task < ActiveRecord::Base
1117
+ enum status: {queued: 0, started: 1, finished: 2}
1118
+ end
1119
+
1120
+ ```
1121
+
1122
+ factory\_bot will automatically define traits for each possible value of the
1123
+ enum:
1124
+
1125
+ ```rb
1126
+ FactoryBot.define do
1127
+ factory :task
1128
+ end
1129
+
1130
+ FactoryBot.build(:task, :queued)
1131
+ FactoryBot.build(:task, :started)
1132
+ FactoryBot.build(:task, :finished)
1133
+ ```
1134
+
1135
+ Writing the traits out manually would be cumbersome, and is not necessary:
1136
+
1137
+ ```rb
1138
+ FactoryBot.define do
1139
+ factory :task do
1140
+ trait :queued do
1141
+ status { :queued }
1142
+ end
1143
+
1144
+ trait :started do
1145
+ status { :started }
1146
+ end
1147
+
1148
+ trait :finished do
1149
+ status { :finished }
1150
+ end
1151
+ end
1152
+ end
1153
+ ```
1154
+
1155
+ If automatically defining traits for enum attributes on every factory is not
1156
+ desired, it is possible to disable the feature by setting
1157
+ `FactoryBot.automatically_define_enum_traits = false`
1158
+
1159
+ In that case, it is still possible to explicitly define traits for an enum
1160
+ attribute in a particular factory:
1161
+
1162
+ ```rb
1163
+ FactoryBot.automatically_define_enum_traits = false
1164
+
1165
+ FactoryBot.define do
1166
+ factory :task do
1167
+ traits_for_enum(:status)
1168
+ end
1169
+ end
1170
+ ```
1171
+
1172
+ It is also possible to use this feature for other enumerable values, not
1173
+ specifically tied to Active Record enum attributes.
1174
+
1175
+ With an array:
1176
+
1177
+ ```rb
1178
+ class Task
1179
+ attr_accessor :status
1180
+ end
1181
+
1182
+ FactoryBot.define do
1183
+ factory :task do
1184
+ traits_for_enum(:status, ["queued", "started", "finished"])
1185
+ end
1186
+ end
1187
+ ```
1188
+
1189
+ Or with a hash:
1190
+
1191
+ ```rb
1192
+ class Task
1193
+ attr_accessor :status
1194
+ end
1195
+
1196
+ FactoryBot.define do
1197
+ factory :task do
1198
+ traits_for_enum(:status, { queued: 0, started: 1, finished: 2 })
1199
+ end
1200
+ end
1201
+ ```
1202
+
801
1203
  Callbacks
802
1204
  ---------
803
1205
 
1206
+ ### Default callbacks
1207
+
804
1208
  factory\_bot makes available four callbacks for injecting some code:
805
1209
 
806
1210
  * after(:build) - called after a factory is built (via `FactoryBot.build`, `FactoryBot.create`)
@@ -819,6 +1223,8 @@ end
819
1223
 
820
1224
  Note that you'll have an instance of the user in the block. This can be useful.
821
1225
 
1226
+ ### Multiple callbacks
1227
+
822
1228
  You can also define multiple types of callbacks on the same factory:
823
1229
 
824
1230
  ```ruby
@@ -828,7 +1234,8 @@ factory :user do
828
1234
  end
829
1235
  ```
830
1236
 
831
- Factories can also define any number of the same kind of callback. These callbacks will be executed in the order they are specified:
1237
+ Factories can also define any number of the same kind of callback. These
1238
+ callbacks will be executed in the order they are specified:
832
1239
 
833
1240
  ```ruby
834
1241
  factory :user do
@@ -839,9 +1246,12 @@ end
839
1246
 
840
1247
  Calling `create` will invoke both `after_build` and `after_create` callbacks.
841
1248
 
842
- Also, like standard attributes, child factories will inherit (and can also define) callbacks from their parent factory.
1249
+ Also, like standard attributes, child factories will inherit (and can also
1250
+ define) callbacks from their parent factory.
843
1251
 
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).
1252
+ Multiple callbacks can be assigned to run a block; this is useful when building
1253
+ various strategies that run the same code (since there are no callbacks that are
1254
+ shared across all strategies).
845
1255
 
846
1256
  ```ruby
847
1257
  factory :user do
@@ -851,6 +1261,8 @@ factory :user do
851
1261
  end
852
1262
  ```
853
1263
 
1264
+ ### Global callbacks
1265
+
854
1266
  To override callbacks for all factories, define them within the
855
1267
  `FactoryBot.define` block:
856
1268
 
@@ -860,12 +1272,14 @@ FactoryBot.define do
860
1272
  after(:create) { |object| AuditLog.create(attrs: object.attributes) }
861
1273
 
862
1274
  factory :user do
863
- name "John Doe"
1275
+ name { "John Doe" }
864
1276
  end
865
1277
  end
866
1278
  ```
867
1279
 
868
- You can also call callbacks that rely on `Symbol#to_proc`:
1280
+ ### Symbol#to_proc
1281
+
1282
+ You can call callbacks that rely on `Symbol#to_proc`:
869
1283
 
870
1284
  ```ruby
871
1285
  # app/models/user.rb
@@ -888,17 +1302,18 @@ create(:user) # creates the user and confirms it
888
1302
  Modifying factories
889
1303
  -------------------
890
1304
 
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.
1305
+ If you're given a set of factories (say, from a gem developer) but want to
1306
+ change them to fit into your application better, you can modify that factory
1307
+ instead of creating a child factory and adding attributes there.
893
1308
 
894
1309
  If a gem were to give you a User factory:
895
1310
 
896
1311
  ```ruby
897
1312
  FactoryBot.define do
898
1313
  factory :user do
899
- full_name "John Doe"
1314
+ full_name { "John Doe" }
900
1315
  sequence(:username) { |n| "user#{n}" }
901
- password "password"
1316
+ password { "password" }
902
1317
  end
903
1318
  end
904
1319
  ```
@@ -908,10 +1323,10 @@ Instead of creating a child factory that added additional attributes:
908
1323
  ```ruby
909
1324
  FactoryBot.define do
910
1325
  factory :application_user, parent: :user do
911
- full_name "Jane Doe"
1326
+ full_name { "Jane Doe" }
912
1327
  date_of_birth { 21.years.ago }
913
- gender "Female"
914
- health 90
1328
+ gender { "Female" }
1329
+ health { 90 }
915
1330
  end
916
1331
  end
917
1332
  ```
@@ -921,10 +1336,10 @@ You could modify that factory instead.
921
1336
  ```ruby
922
1337
  FactoryBot.modify do
923
1338
  factory :user do
924
- full_name "Jane Doe"
1339
+ full_name { "Jane Doe" }
925
1340
  date_of_birth { 21.years.ago }
926
- gender "Female"
927
- health 90
1341
+ gender { "Female" }
1342
+ health { 90 }
928
1343
  end
929
1344
  end
930
1345
  ```
@@ -953,6 +1368,14 @@ To set the attributes for each of the factories, you can pass in a hash as you n
953
1368
  twenty_year_olds = build_list(:user, 25, date_of_birth: 20.years.ago)
954
1369
  ```
955
1370
 
1371
+ In order to set different attributes for each factory, these methods may be passed a block, with the factory and the index as parameters:
1372
+
1373
+ ```ruby
1374
+ twenty_somethings = build_list(:user, 10) do |user, i|
1375
+ user.date_of_birth = (20 + i).years.ago
1376
+ end
1377
+ ```
1378
+
956
1379
  `build_stubbed_list` will give you fully stubbed out instances:
957
1380
 
958
1381
  ```ruby
@@ -975,7 +1398,7 @@ users_attrs = attributes_for_list(:user, 25) # array of attribute hashes
975
1398
  Linting Factories
976
1399
  -----------------
977
1400
 
978
- factory_bot allows for linting known factories:
1401
+ factory\_bot allows for linting known factories:
979
1402
 
980
1403
  ```ruby
981
1404
  FactoryBot.lint
@@ -1002,8 +1425,10 @@ namespace :factory_bot do
1002
1425
  desc "Verify that all FactoryBot factories are valid"
1003
1426
  task lint: :environment do
1004
1427
  if Rails.env.test?
1005
- DatabaseCleaner.cleaning do
1428
+ conn = ActiveRecord::Base.connection
1429
+ conn.transaction do
1006
1430
  FactoryBot.lint
1431
+ raise ActiveRecord::Rollback
1007
1432
  end
1008
1433
  else
1009
1434
  system("bundle exec rake factory_bot:lint RAILS_ENV='test'")
@@ -1015,8 +1440,7 @@ end
1015
1440
 
1016
1441
  After calling `FactoryBot.lint`, you'll likely want to clear out the
1017
1442
  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.
1443
+ uses an sql transaction and rollback to leave the database clean.
1020
1444
 
1021
1445
  You can lint factories selectively by passing only factories you want linted:
1022
1446
 
@@ -1050,10 +1474,17 @@ You can also specify the strategy used for linting:
1050
1474
  FactoryBot.lint strategy: :build
1051
1475
  ```
1052
1476
 
1477
+ Verbose linting will include full backtraces for each error, which can be
1478
+ helpful for debugging:
1479
+
1480
+ ```ruby
1481
+ FactoryBot.lint verbose: true
1482
+ ```
1483
+
1053
1484
  Custom Construction
1054
1485
  -------------------
1055
1486
 
1056
- If you want to use factory_bot to construct an object where some attributes
1487
+ If you want to use factory\_bot to construct an object where some attributes
1057
1488
  are passed to `initialize` or if you want to do something other than simply
1058
1489
  calling `new` on your build class, you can override the default behavior by
1059
1490
  defining `initialize_with` on your factory. Example:
@@ -1072,7 +1503,7 @@ end
1072
1503
  sequence(:email) { |n| "person#{n}@example.com" }
1073
1504
 
1074
1505
  factory :user do
1075
- name "Jane Doe"
1506
+ name { "Jane Doe" }
1076
1507
  email
1077
1508
 
1078
1509
  initialize_with { new(name) }
@@ -1081,7 +1512,7 @@ end
1081
1512
  build(:user).name # Jane Doe
1082
1513
  ```
1083
1514
 
1084
- Although factory_bot is written to work with ActiveRecord out of the box, it
1515
+ Although factory\_bot is written to work with ActiveRecord out of the box, it
1085
1516
  can also work with any Ruby class. For maximum compatibility with ActiveRecord,
1086
1517
  the default initializer builds all instances by calling `new` on your build class
1087
1518
  without any arguments. It then calls attribute writer methods to assign all the
@@ -1092,7 +1523,7 @@ You can override the initializer in order to:
1092
1523
 
1093
1524
  * Build non-ActiveRecord objects that require arguments to `initialize`
1094
1525
  * Use a method other than `new` to instantiate the instance
1095
- * Do crazy things like decorate the instance after it's built
1526
+ * Do wild things like decorate the instance after it's built
1096
1527
 
1097
1528
  When using `initialize_with`, you don't have to declare the class itself when
1098
1529
  calling `new`; however, any other class methods you want to call will have to
@@ -1102,7 +1533,7 @@ For example:
1102
1533
 
1103
1534
  ```ruby
1104
1535
  factory :user do
1105
- name "John Doe"
1536
+ name { "John Doe" }
1106
1537
 
1107
1538
  initialize_with { User.build_with_name(name) }
1108
1539
  end
@@ -1114,7 +1545,7 @@ by calling `attributes`:
1114
1545
  ```ruby
1115
1546
  factory :user do
1116
1547
  transient do
1117
- comments_count 5
1548
+ comments_count { 5 }
1118
1549
  end
1119
1550
 
1120
1551
  name "John Doe"
@@ -1125,7 +1556,7 @@ end
1125
1556
 
1126
1557
  This will build a hash of all attributes to be passed to `new`. It won't
1127
1558
  include transient attributes, but everything else defined in the factory will be
1128
- passed (associations, evalued sequences, etc.)
1559
+ passed (associations, evaluated sequences, etc.)
1129
1560
 
1130
1561
  You can define `initialize_with` for all factories by including it in the
1131
1562
  `FactoryBot.define` block:
@@ -1154,7 +1585,7 @@ build(:user)
1154
1585
  User.new('value')
1155
1586
  ```
1156
1587
 
1157
- This prevents duplicate assignment; in versions of factory_bot before 4.0, it
1588
+ This prevents duplicate assignment; in versions of factory\_bot before 4.0, it
1158
1589
  would run this:
1159
1590
 
1160
1591
  ```ruby
@@ -1287,7 +1718,7 @@ FactoryBot.define do
1287
1718
 
1288
1719
 
1289
1720
  factory :user do
1290
- name "John Doe"
1721
+ name { "John Doe" }
1291
1722
  end
1292
1723
  end
1293
1724
  ```
@@ -1340,13 +1771,13 @@ with associations, as below:
1340
1771
 
1341
1772
  ```ruby
1342
1773
  FactoryBot.define do
1343
- factory :united_states, class: Location do
1344
- name 'United States'
1774
+ factory :united_states, class: "Location" do
1775
+ name { 'United States' }
1345
1776
  association :location_group, factory: :north_america
1346
1777
  end
1347
1778
 
1348
- factory :north_america, class: LocationGroup do
1349
- name 'North America'
1779
+ factory :north_america, class: "LocationGroup" do
1780
+ name { 'North America' }
1350
1781
  end
1351
1782
  end
1352
1783
  ```
@@ -1378,7 +1809,7 @@ require 'factory_bot'
1378
1809
  ```
1379
1810
 
1380
1811
  Once required, assuming you have a directory structure of `spec/factories` or
1381
- `test/factories`, all you'll need to do is run
1812
+ `test/factories`, all you'll need to do is run:
1382
1813
 
1383
1814
  ```ruby
1384
1815
  FactoryBot.find_definitions
@@ -1400,7 +1831,7 @@ require 'factory_bot'
1400
1831
 
1401
1832
  FactoryBot.define do
1402
1833
  factory :user do
1403
- name 'John Doe'
1834
+ name { 'John Doe' }
1404
1835
  date_of_birth { 21.years.ago }
1405
1836
  end
1406
1837
  end