factory_bot 6.2.1 → 6.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CONTRIBUTING.md +2 -2
- data/GETTING_STARTED.md +94 -8
- data/NEWS.md +113 -1
- data/README.md +28 -23
- data/lib/factory_bot/attribute/dynamic.rb +2 -2
- data/lib/factory_bot/attribute_assigner.rb +1 -1
- data/lib/factory_bot/decorator.rb +5 -17
- data/lib/factory_bot/definition.rb +37 -11
- data/lib/factory_bot/definition_proxy.rb +19 -6
- data/lib/factory_bot/evaluation.rb +3 -7
- data/lib/factory_bot/evaluator.rb +3 -4
- data/lib/factory_bot/factory.rb +16 -5
- data/lib/factory_bot/find_definitions.rb +2 -2
- data/lib/factory_bot/internal.rb +35 -2
- data/lib/factory_bot/linter.rb +13 -2
- data/lib/factory_bot/registry.rb +15 -3
- data/lib/factory_bot/sequence.rb +117 -4
- data/lib/factory_bot/strategy/stub.rb +23 -9
- data/lib/factory_bot/syntax/default.rb +2 -2
- data/lib/factory_bot/syntax/methods.rb +61 -12
- data/lib/factory_bot/trait.rb +11 -5
- data/lib/factory_bot/uri_manager.rb +63 -0
- data/lib/factory_bot/version.rb +1 -1
- data/lib/factory_bot.rb +34 -3
- metadata +23 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '0658ea1fd8d3b33128d6a88be3b64855cf80238bc0d2bf109f85a59b4398504f'
|
4
|
+
data.tar.gz: 1cc9fb919e03d2ad95589e5519b19b1c8bd0ec1b6d0e45ee6479ff6d8f2541ad
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '092799b8ba784bb640a2422ff8556d5c13c92a67b8224bd4730c4b2791995d4f56797ccf2815416e2fb21a474c41b47cc87df61564adae4cb3d0dc832c22f520'
|
7
|
+
data.tar.gz: 1cc5060b814c06ed943ed825df2b913fb857b118837a850152f7b9044328de0a277f112365f10d8e66001d270b0059da77bef190ed712558c7186af00a1ccc4c
|
data/CONTRIBUTING.md
CHANGED
@@ -94,12 +94,12 @@ Use [standard] to automatically format your code:
|
|
94
94
|
bundle exec rake standard:fix
|
95
95
|
```
|
96
96
|
|
97
|
-
[repo]: https://github.com/thoughtbot/factory_bot/tree/
|
97
|
+
[repo]: https://github.com/thoughtbot/factory_bot/tree/main
|
98
98
|
[fork]: https://help.github.com/articles/fork-a-repo/
|
99
99
|
[branch]: https://help.github.com/articles/creating-and-deleting-branches-within-your-repository/
|
100
100
|
[pr]: https://help.github.com/articles/using-pull-requests/
|
101
101
|
[standard]: https://github.com/testdouble/standard
|
102
102
|
[appraisal]: https://github.com/thoughtbot/appraisal
|
103
|
-
[reproduction script]: https://github.com/thoughtbot/factory_bot/blob/
|
103
|
+
[reproduction script]: https://github.com/thoughtbot/factory_bot/blob/main/.github/REPRODUCTION_SCRIPT.rb
|
104
104
|
|
105
105
|
Inspired by https://github.com/middleman/middleman-heroku/blob/master/CONTRIBUTING.md
|
data/GETTING_STARTED.md
CHANGED
@@ -1,3 +1,19 @@
|
|
1
|
+
**Deprecated**
|
2
|
+
|
3
|
+
See our extensive reference, guides, and cookbook in [the factory_bot book][].
|
4
|
+
|
5
|
+
For information on integrations with third party libraries, such as RSpec or
|
6
|
+
Rails, see [the factory_bot wiki][].
|
7
|
+
|
8
|
+
We also have [a detailed introductory video][], available for free on Upcase.
|
9
|
+
|
10
|
+
[a detailed introductory video]: https://upcase.com/videos/factory-bot?utm_source=github&utm_medium=open-source&utm_campaign=factory-girl
|
11
|
+
[the factory_bot book]: https://thoughtbot.github.io/factory_bot
|
12
|
+
[the factory_bot wiki]: https://github.com/thoughtbot/factory_bot/wiki
|
13
|
+
|
14
|
+
This document is deprecated and preserved for historical use. It may disappear
|
15
|
+
at any time.
|
16
|
+
|
1
17
|
Getting Started
|
2
18
|
===============
|
3
19
|
|
@@ -239,10 +255,12 @@ Factories can be defined anywhere, but will be automatically loaded after
|
|
239
255
|
calling `FactoryBot.find_definitions` if factories are defined in files at the
|
240
256
|
following locations:
|
241
257
|
|
258
|
+
factories.rb
|
259
|
+
factories/**/*.rb
|
242
260
|
test/factories.rb
|
261
|
+
test/factories/**/*.rb
|
243
262
|
spec/factories.rb
|
244
|
-
|
245
|
-
spec/factories/*.rb
|
263
|
+
spec/factories/**/*.rb
|
246
264
|
|
247
265
|
### Static Attributes
|
248
266
|
|
@@ -269,6 +287,9 @@ user = create(:user)
|
|
269
287
|
# Returns a hash of attributes that can be used to build a User instance
|
270
288
|
attrs = attributes_for(:user)
|
271
289
|
|
290
|
+
# Integrates with Ruby 3.0's support for pattern matching assignment
|
291
|
+
attributes_for(:user) => {email:, name:, **attrs}
|
292
|
+
|
272
293
|
# Returns an object with all defined attributes stubbed out
|
273
294
|
stub = build_stubbed(:user)
|
274
295
|
|
@@ -281,7 +302,7 @@ end
|
|
281
302
|
### Attribute overrides
|
282
303
|
|
283
304
|
No matter which strategy is used, it's possible to override the defined
|
284
|
-
attributes by passing a
|
305
|
+
attributes by passing a Hash:
|
285
306
|
|
286
307
|
```ruby
|
287
308
|
# Build a User instance and override the first_name property
|
@@ -290,6 +311,29 @@ user.first_name
|
|
290
311
|
# => "Joe"
|
291
312
|
```
|
292
313
|
|
314
|
+
Overriding associations is also supported:
|
315
|
+
|
316
|
+
```ruby
|
317
|
+
account = build(:account, :deluxe)
|
318
|
+
friends = build_list(:user, 2)
|
319
|
+
|
320
|
+
user = build(:user, account: account, friends: friends)
|
321
|
+
```
|
322
|
+
|
323
|
+
Ruby 3.1's support for [omitting values][] from `Hash` literals dovetails with
|
324
|
+
attribute overrides and provides an opportunity to limit the repetition of
|
325
|
+
variable names:
|
326
|
+
|
327
|
+
```ruby
|
328
|
+
account = build(:account, :deluxe)
|
329
|
+
friends = build_list(:user, 2)
|
330
|
+
|
331
|
+
# The keyword arguments correspond to local variable names, so omit their values
|
332
|
+
user = build(:user, account:, friends:)
|
333
|
+
```
|
334
|
+
|
335
|
+
[omitting values]: https://docs.ruby-lang.org/en/3.1/syntax/literals_rdoc.html#label-Hash+Literals
|
336
|
+
|
293
337
|
### `build_stubbed` and `Marshal.dump`
|
294
338
|
|
295
339
|
Note that objects created with `build_stubbed` cannot be serialized with
|
@@ -424,7 +468,7 @@ end
|
|
424
468
|
Method Name / Reserved Word Attributes
|
425
469
|
-------------------------------
|
426
470
|
|
427
|
-
If your attributes conflict with existing methods or reserved words (all methods in the [DefinitionProxy](https://github.com/thoughtbot/factory_bot/blob/
|
471
|
+
If your attributes conflict with existing methods or reserved words (all methods in the [DefinitionProxy](https://github.com/thoughtbot/factory_bot/blob/main/lib/factory_bot/definition_proxy.rb) class) you can define them with `add_attribute`.
|
428
472
|
|
429
473
|
```ruby
|
430
474
|
factory :dna do
|
@@ -929,7 +973,7 @@ end
|
|
929
973
|
Note that this approach works with `build`, `build_stubbed`, and `create`, but
|
930
974
|
the associations will return `nil` when using `attributes_for`.
|
931
975
|
|
932
|
-
Also, note that if you assign any attributes inside a custom `initialize_with`
|
976
|
+
Also, note that if you assign any attributes inside a custom `initialize_with`
|
933
977
|
(e.g. `initialize_with { new(**attributes) }`), those attributes should not refer to `instance`,
|
934
978
|
since it will be `nil`.
|
935
979
|
|
@@ -992,6 +1036,17 @@ factory :user do
|
|
992
1036
|
end
|
993
1037
|
```
|
994
1038
|
|
1039
|
+
With Ruby 2.7's support for [numbered parameters][], inline definitions can be
|
1040
|
+
even more abbreviated:
|
1041
|
+
|
1042
|
+
```ruby
|
1043
|
+
factory :user do
|
1044
|
+
sequence(:email) { "person#{_1}@example.com" }
|
1045
|
+
end
|
1046
|
+
```
|
1047
|
+
|
1048
|
+
[numbered parameters]: https://ruby-doc.org/core-2.7.1/Proc.html#class-Proc-label-Numbered+parameters
|
1049
|
+
|
995
1050
|
### Initial value
|
996
1051
|
|
997
1052
|
You can override the initial value. Any value that responds to the `#next`
|
@@ -1206,11 +1261,11 @@ FactoryBot.define do
|
|
1206
1261
|
created_at { 8.days.ago }
|
1207
1262
|
updated_at { 4.days.ago }
|
1208
1263
|
end
|
1209
|
-
|
1264
|
+
|
1210
1265
|
factory :user, traits: [:timestamps] do
|
1211
1266
|
username { "john_doe" }
|
1212
1267
|
end
|
1213
|
-
|
1268
|
+
|
1214
1269
|
factory :post do
|
1215
1270
|
timestamps
|
1216
1271
|
title { "Traits rock" }
|
@@ -1872,6 +1927,10 @@ class JsonStrategy
|
|
1872
1927
|
def result(evaluation)
|
1873
1928
|
@strategy.result(evaluation).to_json
|
1874
1929
|
end
|
1930
|
+
|
1931
|
+
def to_sym
|
1932
|
+
:json
|
1933
|
+
end
|
1875
1934
|
end
|
1876
1935
|
```
|
1877
1936
|
|
@@ -1912,6 +1971,10 @@ class JsonStrategy
|
|
1912
1971
|
evaluation.notify(:make_json_awesome, json)
|
1913
1972
|
end
|
1914
1973
|
end
|
1974
|
+
|
1975
|
+
def to_sym
|
1976
|
+
:json
|
1977
|
+
end
|
1915
1978
|
end
|
1916
1979
|
|
1917
1980
|
FactoryBot.register_strategy(:json, JsonStrategy)
|
@@ -1966,7 +2029,7 @@ ActiveSupport Instrumentation
|
|
1966
2029
|
|
1967
2030
|
In order to track what factories are created (and with what build strategy),
|
1968
2031
|
`ActiveSupport::Notifications` are included to provide a way to subscribe to
|
1969
|
-
factories being run. One example would be to track factories based on a
|
2032
|
+
factories being compiled and run. One example would be to track factories based on a
|
1970
2033
|
threshold of execution time.
|
1971
2034
|
|
1972
2035
|
```ruby
|
@@ -2000,6 +2063,29 @@ config.after(:suite) do
|
|
2000
2063
|
end
|
2001
2064
|
```
|
2002
2065
|
|
2066
|
+
Another example could involve tracking the attributes and traits that factories are compiled with. If you're using RSpec, you could add `before(:suite)` and `after(:suite)` blocks that subscribe to `factory_bot.compile_factory` notifications:
|
2067
|
+
|
2068
|
+
```ruby
|
2069
|
+
factory_bot_results = {}
|
2070
|
+
config.before(:suite) do
|
2071
|
+
ActiveSupport::Notifications.subscribe("factory_bot.compile_factory") do |name, start, finish, id, payload|
|
2072
|
+
factory_name = payload[:name]
|
2073
|
+
factory_class = payload[:class]
|
2074
|
+
attributes = payload[:attributes]
|
2075
|
+
traits = payload[:traits]
|
2076
|
+
factory_bot_results[factory_class] ||= {}
|
2077
|
+
factory_bot_results[factory_class][factory_name] = {
|
2078
|
+
attributes: attributes.map(&:name)
|
2079
|
+
traits: traits.map(&:name)
|
2080
|
+
}
|
2081
|
+
end
|
2082
|
+
end
|
2083
|
+
|
2084
|
+
config.after(:suite) do
|
2085
|
+
puts factory_bot_results
|
2086
|
+
end
|
2087
|
+
```
|
2088
|
+
|
2003
2089
|
Rails Preloaders and RSpec
|
2004
2090
|
--------------------------
|
2005
2091
|
|
data/NEWS.md
CHANGED
@@ -1,9 +1,119 @@
|
|
1
1
|
# News
|
2
2
|
|
3
|
+
## 6.5.4 (June 13, 2025)
|
4
|
+
|
5
|
+
* Fix bug where user-defined method named `definition` could not be set through `method_missing` in factories. (CodeMeister)
|
6
|
+
|
7
|
+
## 6.5.3 (June 2, 2025)
|
8
|
+
|
9
|
+
* Fix: Factory sequences without blocks (CodeMeister)
|
10
|
+
* Added: New methods for setting, generating and rewinding sequences (CodeMeister)
|
11
|
+
|
12
|
+
## 6.5.2 (May 30, 2025)
|
13
|
+
|
14
|
+
* Changed: Updated "verbose linting" test to allow for backtrace changes in Ruby 3.4 (CodeMeister)
|
15
|
+
* Fix: Set the same timestamps for `created_at` and `updated_at` on `build_stubbed` (Kim Emmanuel)
|
16
|
+
* Fix: Refactored sequences to ensure cloned traits use parent sequences. (CodeMeister)
|
17
|
+
* Docs: Fix definition_file_paths comment (Milo Winningham)
|
18
|
+
* Docs: Add ruby-lsp extensions to Useful Tools in README.md (johansenja)
|
19
|
+
* Docs: Fix docs about definition file paths (Ryo Nakamura)
|
20
|
+
* Docs: Update has_many-associations.md to mention that traits can use inline associations (Matthew Zagaja)
|
21
|
+
* Docs: Fix "Transitioning from Factory Girl" guide link (Neil Carvalho)
|
22
|
+
|
23
|
+
## 6.5.1 (January 31, 2025)
|
24
|
+
|
25
|
+
* Changed: execute linting tests within ActiveRecord transactions when available (Sean Doyle)
|
26
|
+
* Fix: Random test failure when tracking compilation time (CodeMeister)
|
27
|
+
* Fix: Bump the minimum required activesupport version to 6.1 (Earlopain)
|
28
|
+
* Internal: Update development dependencies (Neil Carvalho)
|
29
|
+
|
30
|
+
## 6.5.0 (September 6, 2024)
|
31
|
+
|
32
|
+
* fix: issue 1621 broken links in ref/factory.md by @elasticspoon in https://github.com/thoughtbot/factory_bot/pull/1623
|
33
|
+
* Add standard settings by @ydah in https://github.com/thoughtbot/factory_bot/pull/1625
|
34
|
+
* Call dynamic-readme reusable workflow by @stefannibrasil in https://github.com/thoughtbot/factory_bot/pull/1628
|
35
|
+
* Update README again by @stefannibrasil in https://github.com/thoughtbot/factory_bot/pull/1630
|
36
|
+
* Only run this workflow if the README has been updated by @stefannibrasil in https://github.com/thoughtbot/factory_bot/pull/1635
|
37
|
+
* Automatically Generated: Update Dynamic Section in README by @github-actions in https://github.com/thoughtbot/factory_bot/pull/1637
|
38
|
+
* Added a case for build_class to handle class names with underscores passed as a string by @m-gizzi in https://github.com/thoughtbot/factory_bot/pull/1642
|
39
|
+
* Add Ruby 3.3 to CI by @berkos in https://github.com/thoughtbot/factory_bot/pull/1615
|
40
|
+
* Update Dependabot configuration by @smaboshe in https://github.com/thoughtbot/factory_bot/pull/1655
|
41
|
+
* Add new maintainers to CODEOWNERS by @sarahraqueld in https://github.com/thoughtbot/factory_bot/pull/1651
|
42
|
+
* Improve docs formatting and fix filename conflicts by @sarahraqueld in https://github.com/thoughtbot/factory_bot/pull/1666
|
43
|
+
* Add a dynamic security workflow and a SECURITY.md file by @sarahraqueld in https://github.com/thoughtbot/factory_bot/pull/1677
|
44
|
+
* Automatically Generated: Update Dynamic Section in SECURITY by @github-actions in https://github.com/thoughtbot/factory_bot/pull/1678
|
45
|
+
* Ensure rails 7.2 compatibility by @Earlopain in https://github.com/thoughtbot/factory_bot/pull/1686
|
46
|
+
* Fix the factory definition in traits documentation by @ddieulivol in https://github.com/thoughtbot/factory_bot/pull/1688
|
47
|
+
|
48
|
+
## 6.4.6 (January 30, 2023)
|
49
|
+
|
50
|
+
* Fix: Bump minimum required Ruby in gemspec (Earlopain).
|
51
|
+
* Fix: Broken link in `FactoryBot.modify` docs (Matt Brictson).
|
52
|
+
* Fix: Broken link in `FactoryBot.lint` docs (Anton Dieterle).
|
53
|
+
|
54
|
+
## 6.4.5 (December 29, 2023)
|
55
|
+
|
56
|
+
* Changed: Support Ruby 3.0+, Rails 6.1+ (Mike Burns).
|
57
|
+
|
58
|
+
## 6.4.4 (December 27, 2023)
|
59
|
+
|
60
|
+
* Internal: Remove observer dependency (Earlopain).
|
61
|
+
|
62
|
+
## 6.4.3 (December 26, 2023)
|
63
|
+
|
64
|
+
* Fix: Support models without ID setters in build_stubbed (Olivier Bellone).
|
65
|
+
* Fix: Explicit observer dependency (Oleg Antonyan).
|
66
|
+
* Internal: Add Rails 7.1 to CI (Olivier Bellone).
|
67
|
+
* Internal: Bump github actions/checkout to v4 (Lorenzo Zabot)
|
68
|
+
* Internal: Stop passing disable-error_highlight in CI (Mike Burns).
|
69
|
+
* Internal: Relax the exception message check (Mike Burns).
|
70
|
+
|
71
|
+
## 6.4.2 (November 22, 2023)
|
72
|
+
|
73
|
+
* Fix: top-level traits pass their class to ActiveSupport::Notifications
|
74
|
+
(makicamel).
|
75
|
+
|
76
|
+
## 6.4.1 (November 20, 2023)
|
77
|
+
|
78
|
+
* Fix: factories with traits pass their class to ActiveSupport::Notifications
|
79
|
+
(makicamel).
|
80
|
+
|
81
|
+
## 6.4.0 (November 17, 2023)
|
82
|
+
|
83
|
+
* Added: if `build_stubbed` detects a UUID primary key, generate the correct
|
84
|
+
type (Peter Boling, Alexandre Ruban).
|
85
|
+
* Docs: show examples of Ruby 3 syntactic sugars (Sean Doyle).
|
86
|
+
* Internal: resolve test warning messages (Mike Burns).
|
87
|
+
|
88
|
+
|
89
|
+
## 6.3.0 (September 1, 2023)
|
90
|
+
|
91
|
+
* Fix: link to changelog for RubyGems (Berkan Ünal).
|
92
|
+
* Fix: integrate with Ruby 3.2's `did_you_mean` library (Daniel Colson).
|
93
|
+
* Changed: explicitly define `#destroyed?` within the `Stub` strategy to return `false` to be consistent
|
94
|
+
with ActiveRecord (Benjamin Fleischer).
|
95
|
+
* Added: announce `factory_bot.compile_factory` notification (Sean Doyle).
|
96
|
+
* Docs: clarify that custom strategies need to define `#to_sym` (Edmund Korley, Jonas S).
|
97
|
+
* Docs: fix CI link in README (Mark Huk).
|
98
|
+
* Docs: fix GitHub links (Robert Fletcher).
|
99
|
+
* Docs: install this library with `bundle add` (Glauco Custódio).
|
100
|
+
* Docs: re-write into mdBook (Mike Burns, Sara Jackson, Stefanni Brasil)
|
101
|
+
* Docs: clarify that automatic trait definitions could introduce new linting errors (Lawrence Chou).
|
102
|
+
* Internal: skip TruffleRuby on Rails 5.0, 5.1, 5.2 (Andrii Konchyn).
|
103
|
+
* Internal: fix typoes throughout codebase (Yudai Takada).
|
104
|
+
* Internal: run CI on `actions/checkout` v3 (Yudai Takada).
|
105
|
+
* Internal: follow standardrb code style (Yudai Takada).
|
106
|
+
* Internal: stop using Hound (Daniel Nolan).
|
107
|
+
* Internal: only run simplecov on C Ruby (Daniel Colson).
|
108
|
+
* Internal: quieter Cucumber (Daniel Colson).
|
109
|
+
* Internal: Ruby 3.2 support (Daniel Colson).
|
110
|
+
* Internal: Mike Burns is the CODEOWNER (Stefanni Brasil).
|
111
|
+
|
3
112
|
## 6.2.1 (March 8, 2022)
|
4
113
|
* Added: CI testing against truffleruby
|
5
114
|
* Changed: Documentation improvements for sequences and traits
|
6
115
|
* Fixed: ActiveSupport::Notifications reporting strategy through associations now report as symbols
|
116
|
+
* BREAKING CHANGE: Custom strategies now need to define a `to_sym` method to specify the strategy identifier
|
7
117
|
* Fixed: `add_attribute` with reserved keywords assigns values correctly
|
8
118
|
|
9
119
|
## 6.2.0 (May 7, 2021)
|
@@ -27,7 +137,9 @@
|
|
27
137
|
* Added: automatic definition of traits for Active Record enum attributes, enabled by default
|
28
138
|
(Note that this required changing where factory_bot constantizes the build
|
29
139
|
class, which may affect applications that were using abstract factories for
|
30
|
-
inheritance. See issue #1409.)
|
140
|
+
inheritance. See issue #1409.) (This may break `FactoryBot.lint` because
|
141
|
+
there may be previously non-existing factory+trait combinations being
|
142
|
+
defined and checked)
|
31
143
|
* Added: `traits_for_enum` method to define traits for non-Active Record enums
|
32
144
|
* Added: `build_stubbed_starting_id=` option to define the starting id for `build_stubbed`
|
33
145
|
* Removed: deprecated methods on the top-level `FactoryBot` module meant only for internal use
|
data/README.md
CHANGED
@@ -10,30 +10,32 @@ _[Interested in the history of the project name?][NAME]_
|
|
10
10
|
|
11
11
|
### Transitioning from factory\_girl?
|
12
12
|
|
13
|
-
Check out the [guide](https://github.com/thoughtbot/factory_bot/blob/
|
13
|
+
Check out the [guide](https://github.com/thoughtbot/factory_bot/blob/v4.9.0/UPGRADE_FROM_FACTORY_GIRL.md).
|
14
14
|
|
15
15
|
|
16
16
|
Documentation
|
17
17
|
-------------
|
18
18
|
|
19
|
-
|
19
|
+
See our extensive reference, guides, and cookbook in [the factory_bot book][].
|
20
20
|
|
21
|
-
|
22
|
-
|
21
|
+
For information on integrations with third party libraries, such as RSpec or
|
22
|
+
Rails, see [the factory_bot wiki][].
|
23
|
+
|
24
|
+
We also have [a detailed introductory video][], available for free on Upcase.
|
23
25
|
|
24
26
|
[a detailed introductory video]: https://upcase.com/videos/factory-bot?utm_source=github&utm_medium=open-source&utm_campaign=factory-girl
|
27
|
+
[the factory_bot book]: https://thoughtbot.github.io/factory_bot
|
28
|
+
[the factory_bot wiki]: https://github.com/thoughtbot/factory_bot/wiki
|
25
29
|
|
26
30
|
Install
|
27
31
|
--------
|
28
32
|
|
29
|
-
|
33
|
+
Run:
|
30
34
|
|
31
35
|
```ruby
|
32
|
-
|
36
|
+
bundle add factory_bot
|
33
37
|
```
|
34
38
|
|
35
|
-
and run `bundle install` from your shell.
|
36
|
-
|
37
39
|
To install the gem manually from your shell, run:
|
38
40
|
|
39
41
|
```shell
|
@@ -43,7 +45,7 @@ gem install factory_bot
|
|
43
45
|
Supported Ruby versions
|
44
46
|
-----------------------
|
45
47
|
|
46
|
-
Supported Ruby versions are listed in [`.github/workflows/build.yml`](https://github.com/thoughtbot/factory_bot/blob/
|
48
|
+
Supported Ruby versions are listed in [`.github/workflows/build.yml`](https://github.com/thoughtbot/factory_bot/blob/main/.github/workflows/build.yml)
|
47
49
|
|
48
50
|
More Information
|
49
51
|
----------------
|
@@ -53,18 +55,19 @@ More Information
|
|
53
55
|
* [Issues](https://github.com/thoughtbot/factory_bot/issues)
|
54
56
|
* [GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS](https://robots.thoughtbot.com/)
|
55
57
|
|
56
|
-
[GETTING_STARTED]: https://github.com/thoughtbot/factory_bot/blob/
|
57
|
-
[NAME]: https://github.com/thoughtbot/factory_bot/blob/
|
58
|
+
[GETTING_STARTED]: https://github.com/thoughtbot/factory_bot/blob/main/GETTING_STARTED.md
|
59
|
+
[NAME]: https://github.com/thoughtbot/factory_bot/blob/main/NAME.md
|
58
60
|
|
59
61
|
Useful Tools
|
60
62
|
------------
|
61
63
|
|
62
64
|
* [FactoryTrace](https://github.com/djezzzl/factory_trace) - helps to find unused factories and traits.
|
65
|
+
* [ruby-lsp-factory_bot](https://github.com/donny741/ruby-lsp-factory_bot) / [ruby-lsp-rails-factory-bot](https://github.com/johansenja/ruby-lsp-rails-factory-bot) - integration with [ruby-lsp](https://github.com/Shopify/ruby-lsp) to provide intellisense
|
63
66
|
|
64
67
|
Contributing
|
65
68
|
------------
|
66
69
|
|
67
|
-
Please see [CONTRIBUTING.md](https://github.com/thoughtbot/factory_bot/blob/
|
70
|
+
Please see [CONTRIBUTING.md](https://github.com/thoughtbot/factory_bot/blob/main/CONTRIBUTING.md).
|
68
71
|
|
69
72
|
factory_bot was originally written by Joe Ferris and is maintained by thoughtbot.
|
70
73
|
Many improvements and bugfixes were contributed by the [open source
|
@@ -73,29 +76,31 @@ community](https://github.com/thoughtbot/factory_bot/graphs/contributors).
|
|
73
76
|
License
|
74
77
|
-------
|
75
78
|
|
76
|
-
factory_bot is Copyright © 2008
|
79
|
+
factory_bot is Copyright © 2008 Joe Ferris and thoughtbot. It is free
|
77
80
|
software, and may be redistributed under the terms specified in the
|
78
81
|
[LICENSE] file.
|
79
82
|
|
80
|
-
[LICENSE]: https://github.com/thoughtbot/factory_bot/blob/
|
81
|
-
|
83
|
+
[LICENSE]: https://github.com/thoughtbot/factory_bot/blob/main/LICENSE
|
82
84
|
|
83
|
-
|
84
|
-
|
85
|
+
<!-- START /templates/footer.md -->
|
86
|
+
## About thoughtbot
|
85
87
|
|
86
|
-

|
87
89
|
|
88
|
-
|
90
|
+
This repo is maintained and funded by thoughtbot, inc.
|
89
91
|
The names and logos for thoughtbot are trademarks of thoughtbot, inc.
|
90
92
|
|
91
93
|
We love open source software!
|
92
|
-
See [our other projects][community]
|
93
|
-
[hire
|
94
|
+
See [our other projects][community].
|
95
|
+
We are [available for hire][hire].
|
94
96
|
|
95
97
|
[community]: https://thoughtbot.com/community?utm_source=github
|
96
98
|
[hire]: https://thoughtbot.com/hire-us?utm_source=github
|
97
|
-
|
98
|
-
|
99
|
+
|
100
|
+
<!-- END /templates/footer.md -->
|
101
|
+
|
102
|
+
[ci-image]: https://github.com/thoughtbot/factory_bot/actions/workflows/build.yml/badge.svg?branch=main
|
103
|
+
[ci]: https://github.com/thoughtbot/factory_bot/actions?query=workflow%3ABuild+branch%3Amain
|
99
104
|
[grade-image]: https://codeclimate.com/github/thoughtbot/factory_bot/badges/gpa.svg
|
100
105
|
[grade]: https://codeclimate.com/github/thoughtbot/factory_bot
|
101
106
|
[version-image]: https://badge.fury.io/rb/factory_bot.svg
|
@@ -12,8 +12,8 @@ module FactoryBot
|
|
12
12
|
|
13
13
|
-> {
|
14
14
|
value = case block.arity
|
15
|
-
|
16
|
-
|
15
|
+
when 1, -1, -2 then instance_exec(self, &block)
|
16
|
+
else instance_exec(&block)
|
17
17
|
end
|
18
18
|
raise SequenceAbuseError if FactoryBot::Sequence === value
|
19
19
|
|
@@ -13,7 +13,7 @@ module FactoryBot
|
|
13
13
|
@evaluator.instance = build_class_instance
|
14
14
|
build_class_instance.tap do |instance|
|
15
15
|
attributes_to_set_on_instance.each do |attribute|
|
16
|
-
instance.public_send("#{attribute}=", get(attribute))
|
16
|
+
instance.public_send(:"#{attribute}=", get(attribute))
|
17
17
|
@attribute_names_assigned << attribute
|
18
18
|
end
|
19
19
|
end
|
@@ -6,24 +6,12 @@ module FactoryBot
|
|
6
6
|
@component = component
|
7
7
|
end
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
@component.send(...)
|
13
|
-
end
|
14
|
-
|
15
|
-
def send(...)
|
16
|
-
__send__(...)
|
17
|
-
end
|
18
|
-
RUBY
|
19
|
-
else
|
20
|
-
def method_missing(name, *args, &block) # rubocop:disable Style/MissingRespondToMissing
|
21
|
-
@component.send(name, *args, &block)
|
22
|
-
end
|
9
|
+
def method_missing(...) # rubocop:disable Style/MethodMissingSuper
|
10
|
+
@component.send(...)
|
11
|
+
end
|
23
12
|
|
24
|
-
|
25
|
-
|
26
|
-
end
|
13
|
+
def send(...)
|
14
|
+
__send__(...)
|
27
15
|
end
|
28
16
|
|
29
17
|
def respond_to_missing?(name, include_private = false)
|
@@ -1,10 +1,12 @@
|
|
1
1
|
module FactoryBot
|
2
2
|
# @api private
|
3
3
|
class Definition
|
4
|
-
attr_reader :defined_traits, :declarations, :name, :registered_enums
|
4
|
+
attr_reader :defined_traits, :declarations, :name, :registered_enums, :uri_manager
|
5
|
+
attr_accessor :klass
|
5
6
|
|
6
|
-
def initialize(name, base_traits = [])
|
7
|
+
def initialize(name, base_traits = [], **opts)
|
7
8
|
@name = name
|
9
|
+
@uri_manager = opts[:uri_manager]
|
8
10
|
@declarations = DeclarationList.new(name)
|
9
11
|
@callbacks = []
|
10
12
|
@defined_traits = Set.new
|
@@ -51,12 +53,21 @@ module FactoryBot
|
|
51
53
|
|
52
54
|
declarations.attributes
|
53
55
|
|
56
|
+
self.klass ||= klass
|
54
57
|
defined_traits.each do |defined_trait|
|
58
|
+
defined_trait.klass ||= klass
|
55
59
|
base_traits.each { |bt| bt.define_trait defined_trait }
|
56
60
|
additional_traits.each { |at| at.define_trait defined_trait }
|
57
61
|
end
|
58
62
|
|
59
63
|
@compiled = true
|
64
|
+
|
65
|
+
ActiveSupport::Notifications.instrument "factory_bot.compile_factory", {
|
66
|
+
name: name,
|
67
|
+
attributes: declarations.attributes,
|
68
|
+
traits: defined_traits,
|
69
|
+
class: klass || self.klass
|
70
|
+
}
|
60
71
|
end
|
61
72
|
end
|
62
73
|
|
@@ -85,6 +96,10 @@ module FactoryBot
|
|
85
96
|
@defined_traits.add(trait)
|
86
97
|
end
|
87
98
|
|
99
|
+
def defined_traits_names
|
100
|
+
@defined_traits.map(&:name)
|
101
|
+
end
|
102
|
+
|
88
103
|
def register_enum(enum)
|
89
104
|
@registered_enums << enum
|
90
105
|
end
|
@@ -115,15 +130,26 @@ module FactoryBot
|
|
115
130
|
raise error_with_definition_name(error)
|
116
131
|
end
|
117
132
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
" referenced within \"#{name}\" definition"
|
123
|
-
)
|
133
|
+
# detailed_message introduced in Ruby 3.2 for cleaner integration with
|
134
|
+
# did_you_mean. See https://bugs.ruby-lang.org/issues/18564
|
135
|
+
if KeyError.method_defined?(:detailed_message)
|
136
|
+
def error_with_definition_name(error)
|
137
|
+
message = error.message + " referenced within \"#{name}\" definition"
|
124
138
|
|
125
|
-
|
126
|
-
|
139
|
+
error.class.new(message, key: error.key, receiver: error.receiver)
|
140
|
+
.tap { |new_error| new_error.set_backtrace(error.backtrace) }
|
141
|
+
end
|
142
|
+
else
|
143
|
+
def error_with_definition_name(error)
|
144
|
+
message = error.message
|
145
|
+
message.insert(
|
146
|
+
message.index("\nDid you mean?") || message.length,
|
147
|
+
" referenced within \"#{name}\" definition"
|
148
|
+
)
|
149
|
+
|
150
|
+
error.class.new(message).tap do |new_error|
|
151
|
+
new_error.set_backtrace(error.backtrace)
|
152
|
+
end
|
127
153
|
end
|
128
154
|
end
|
129
155
|
|
@@ -132,7 +158,7 @@ module FactoryBot
|
|
132
158
|
end
|
133
159
|
|
134
160
|
def trait_by_name(name)
|
135
|
-
trait_for(name) || Internal.trait_by_name(name)
|
161
|
+
trait_for(name) || Internal.trait_by_name(name, klass)
|
136
162
|
end
|
137
163
|
|
138
164
|
def trait_for(name)
|
@@ -120,9 +120,13 @@ module FactoryBot
|
|
120
120
|
#
|
121
121
|
# Except that no globally available sequence will be defined.
|
122
122
|
def sequence(name, *args, &block)
|
123
|
-
|
124
|
-
|
125
|
-
|
123
|
+
options = args.extract_options!
|
124
|
+
options[:uri_paths] = @definition.uri_manager.to_a
|
125
|
+
args << options
|
126
|
+
|
127
|
+
new_sequence = Sequence.new(name, *args, &block)
|
128
|
+
registered_sequence = __fetch_or_register_sequence(new_sequence)
|
129
|
+
add_attribute(name) { increment_sequence(registered_sequence) }
|
126
130
|
end
|
127
131
|
|
128
132
|
# Adds an attribute that builds an association. The associated instance will
|
@@ -151,7 +155,7 @@ module FactoryBot
|
|
151
155
|
def association(name, *options)
|
152
156
|
if block_given?
|
153
157
|
raise AssociationDefinitionError.new(
|
154
|
-
"Unexpected block passed to '#{name}' association "\
|
158
|
+
"Unexpected block passed to '#{name}' association " \
|
155
159
|
"in '#{@definition.name}' factory"
|
156
160
|
)
|
157
161
|
else
|
@@ -169,11 +173,11 @@ module FactoryBot
|
|
169
173
|
end
|
170
174
|
|
171
175
|
def factory(name, options = {}, &block)
|
172
|
-
|
176
|
+
child_factories << [name, options, block]
|
173
177
|
end
|
174
178
|
|
175
179
|
def trait(name, &block)
|
176
|
-
@definition.define_trait(Trait.new(name, &block))
|
180
|
+
@definition.define_trait(Trait.new(name, uri_paths: @definition.uri_manager.to_a, &block))
|
177
181
|
end
|
178
182
|
|
179
183
|
# Creates traits for enumerable values.
|
@@ -252,5 +256,14 @@ module FactoryBot
|
|
252
256
|
def __valid_association_options?(options)
|
253
257
|
options.respond_to?(:has_key?) && options.has_key?(:factory)
|
254
258
|
end
|
259
|
+
|
260
|
+
##
|
261
|
+
# If the inline sequence has already been registered by a parent,
|
262
|
+
# return that one, otherwise register and return the given sequence
|
263
|
+
#
|
264
|
+
def __fetch_or_register_sequence(sequence)
|
265
|
+
FactoryBot::Sequence.find_by_uri(sequence.uri_manager.first) ||
|
266
|
+
FactoryBot::Internal.register_inline_sequence(sequence)
|
267
|
+
end
|
255
268
|
end
|
256
269
|
end
|