factory_bot 6.2.0 → 6.4.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a928c94babd835a0756175aa3d7a1f03d4dae15b0782818a8c9688489f6e18d3
4
- data.tar.gz: e2875eca60137531b83267dcdfd87ba1329ed8a52e460a0e609fa5fb04f39244
3
+ metadata.gz: b5f21ea97d90ed0a9c175d1ff2b04961bcf38fa981c2957ac3c9fd77fa7e2612
4
+ data.tar.gz: 4698bcccd79fe5252ec751637f7f86b1e0810b2d9d5b52a69fb1d7dd5d238894
5
5
  SHA512:
6
- metadata.gz: bf8f7006ff4e0f34533259c6e747bb61cd8ebcd6d68b7a9076b811bf4b152662997f18ad467953c07f3a0c7c10585b48b4f0489ce6aa1a16b42ad02641e7169b
7
- data.tar.gz: a80c3ed49517c2cee0dc7bdafc9dd3459d7fcd83443873e2a8c72db8a3c96b6d902975c8a586ecbfb1cd6b8dab9513a4bdfaa22f84c297f81b2736a8f4317e8d
6
+ metadata.gz: 74a79d529f84cece38fe558e1f6c9cb3213d9038e1b853bbe378ce86f3ce6c8168f057a438039670275845530122bb28e41cd8a5669a6f14a2886bfd20201c41
7
+ data.tar.gz: d2b13eb9ca94da825becc7fb04a0535dfb72547375b2b824a6c447dec27a0426d37907a88de95b80f2b78d412fc7f8290311d102ad31bbcafcee4c78a24babf5
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/master
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/master/.github/REPRODUCTION_SCRIPT.rb
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
 
@@ -269,6 +285,9 @@ user = create(:user)
269
285
  # Returns a hash of attributes that can be used to build a User instance
270
286
  attrs = attributes_for(:user)
271
287
 
288
+ # Integrates with Ruby 3.0's support for pattern matching assignment
289
+ attributes_for(:user) => {email:, name:, **attrs}
290
+
272
291
  # Returns an object with all defined attributes stubbed out
273
292
  stub = build_stubbed(:user)
274
293
 
@@ -281,7 +300,7 @@ end
281
300
  ### Attribute overrides
282
301
 
283
302
  No matter which strategy is used, it's possible to override the defined
284
- attributes by passing a hash:
303
+ attributes by passing a Hash:
285
304
 
286
305
  ```ruby
287
306
  # Build a User instance and override the first_name property
@@ -290,6 +309,29 @@ user.first_name
290
309
  # => "Joe"
291
310
  ```
292
311
 
312
+ Overriding associations is also supported:
313
+
314
+ ```ruby
315
+ account = build(:account, :deluxe)
316
+ friends = build_list(:user, 2)
317
+
318
+ user = build(:user, account: account, friends: friends)
319
+ ```
320
+
321
+ Ruby 3.1's support for [omitting values][] from `Hash` literals dovetails with
322
+ attribute overrides and provides an opportunity to limit the repetition of
323
+ variable names:
324
+
325
+ ```ruby
326
+ account = build(:account, :deluxe)
327
+ friends = build_list(:user, 2)
328
+
329
+ # The keyword arguments correspond to local variable names, so omit their values
330
+ user = build(:user, account:, friends:)
331
+ ```
332
+
333
+ [omitting values]: https://docs.ruby-lang.org/en/3.1/syntax/literals_rdoc.html#label-Hash+Literals
334
+
293
335
  ### `build_stubbed` and `Marshal.dump`
294
336
 
295
337
  Note that objects created with `build_stubbed` cannot be serialized with
@@ -424,7 +466,7 @@ end
424
466
  Method Name / Reserved Word Attributes
425
467
  -------------------------------
426
468
 
427
- 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`.
469
+ 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
470
 
429
471
  ```ruby
430
472
  factory :dna do
@@ -592,7 +634,7 @@ Attribute overrides can be used to link associated objects:
592
634
  ```ruby
593
635
  FactoryBot.define do
594
636
  factory :author do
595
- author_last_name { 'Taylor' }
637
+ name { 'Taylor' }
596
638
  end
597
639
 
598
640
  factory :post do
@@ -929,7 +971,7 @@ end
929
971
  Note that this approach works with `build`, `build_stubbed`, and `create`, but
930
972
  the associations will return `nil` when using `attributes_for`.
931
973
 
932
- Also, note that if you assign any attributes inside a custom `initialize_with`
974
+ Also, note that if you assign any attributes inside a custom `initialize_with`
933
975
  (e.g. `initialize_with { new(**attributes) }`), those attributes should not refer to `instance`,
934
976
  since it will be `nil`.
935
977
 
@@ -992,6 +1034,17 @@ factory :user do
992
1034
  end
993
1035
  ```
994
1036
 
1037
+ With Ruby 2.7's support for [numbered parameters][], inline definitions can be
1038
+ even more abbreviated:
1039
+
1040
+ ```ruby
1041
+ factory :user do
1042
+ sequence(:email) { "person#{_1}@example.com" }
1043
+ end
1044
+ ```
1045
+
1046
+ [numbered parameters]: https://ruby-doc.org/core-2.7.1/Proc.html#class-Proc-label-Numbered+parameters
1047
+
995
1048
  ### Initial value
996
1049
 
997
1050
  You can override the initial value. Any value that responds to the `#next`
@@ -1013,6 +1066,15 @@ factory :post do
1013
1066
  end
1014
1067
  ```
1015
1068
 
1069
+ Please note, that the value for the sequence could be any Enumerable instance,
1070
+ as long as it responds to `#next`:
1071
+
1072
+ ```ruby
1073
+ factory :task do
1074
+ sequence :priority, %i[low medium high urgent].cycle
1075
+ end
1076
+ ```
1077
+
1016
1078
  ### Aliases
1017
1079
 
1018
1080
  Sequences can also have aliases. The sequence aliases share the same counter:
@@ -1187,6 +1249,28 @@ factory :user do
1187
1249
  end
1188
1250
  ```
1189
1251
 
1252
+ ### As mixins
1253
+
1254
+ Traits can be defined outside of factories and used as mixins to compose shared attributes
1255
+
1256
+ ```ruby
1257
+ FactoryBot.define do
1258
+ trait :timestamps do
1259
+ created_at { 8.days.ago }
1260
+ updated_at { 4.days.ago }
1261
+ end
1262
+
1263
+ factory :user, traits: [:timestamps] do
1264
+ username { "john_doe" }
1265
+ end
1266
+
1267
+ factory :post do
1268
+ timestamps
1269
+ title { "Traits rock" }
1270
+ end
1271
+ end
1272
+ ```
1273
+
1190
1274
  ### Using traits
1191
1275
 
1192
1276
  Traits can also be passed in as a list of symbols when you construct an instance
@@ -1574,6 +1658,15 @@ twenty_somethings = build_list(:user, 10) do |user, i|
1574
1658
  end
1575
1659
  ```
1576
1660
 
1661
+ `create_list` passes saved instances into the block. If you modify the instance, you must save it again:
1662
+
1663
+ ```ruby
1664
+ twenty_somethings = create_list(:user, 10) do |user, i|
1665
+ user.date_of_birth = (20 + i).years.ago
1666
+ user.save!
1667
+ end
1668
+ ```
1669
+
1577
1670
  `build_stubbed_list` will give you fully stubbed out instances:
1578
1671
 
1579
1672
  ```ruby
@@ -1832,6 +1925,10 @@ class JsonStrategy
1832
1925
  def result(evaluation)
1833
1926
  @strategy.result(evaluation).to_json
1834
1927
  end
1928
+
1929
+ def to_sym
1930
+ :json
1931
+ end
1835
1932
  end
1836
1933
  ```
1837
1934
 
@@ -1872,6 +1969,10 @@ class JsonStrategy
1872
1969
  evaluation.notify(:make_json_awesome, json)
1873
1970
  end
1874
1971
  end
1972
+
1973
+ def to_sym
1974
+ :json
1975
+ end
1875
1976
  end
1876
1977
 
1877
1978
  FactoryBot.register_strategy(:json, JsonStrategy)
@@ -1926,7 +2027,7 @@ ActiveSupport Instrumentation
1926
2027
 
1927
2028
  In order to track what factories are created (and with what build strategy),
1928
2029
  `ActiveSupport::Notifications` are included to provide a way to subscribe to
1929
- factories being run. One example would be to track factories based on a
2030
+ factories being compiled and run. One example would be to track factories based on a
1930
2031
  threshold of execution time.
1931
2032
 
1932
2033
  ```ruby
@@ -1960,6 +2061,29 @@ config.after(:suite) do
1960
2061
  end
1961
2062
  ```
1962
2063
 
2064
+ 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:
2065
+
2066
+ ```ruby
2067
+ factory_bot_results = {}
2068
+ config.before(:suite) do
2069
+ ActiveSupport::Notifications.subscribe("factory_bot.compile_factory") do |name, start, finish, id, payload|
2070
+ factory_name = payload[:name]
2071
+ factory_class = payload[:class]
2072
+ attributes = payload[:attributes]
2073
+ traits = payload[:traits]
2074
+ factory_bot_results[factory_class] ||= {}
2075
+ factory_bot_results[factory_class][factory_name] = {
2076
+ attributes: attributes.map(&:name)
2077
+ traits: traits.map(&:name)
2078
+ }
2079
+ end
2080
+ end
2081
+
2082
+ config.after(:suite) do
2083
+ puts factory_bot_results
2084
+ end
2085
+ ```
2086
+
1963
2087
  Rails Preloaders and RSpec
1964
2088
  --------------------------
1965
2089
 
data/NEWS.md CHANGED
@@ -1,5 +1,53 @@
1
1
  # News
2
2
 
3
+ ## 6.4.2 (November 22, 2023)
4
+
5
+ * Fix: top-level traits pass their class to ActiveSupport::Notifications
6
+ (makicamel).
7
+
8
+ ## 6.4.1 (November 20, 2023)
9
+
10
+ * Fix: factories with traits pass their class to ActiveSupport::Notifications
11
+ (makicamel).
12
+
13
+ ## 6.4.0 (November 17, 2023)
14
+
15
+ * Added: if `build_stubbed` detects a UUID primary key, generate the correct
16
+ type (Peter Boling, Alexandre Ruban).
17
+ * Docs: show examples of Ruby 3 syntactic sugars (Sean Doyle).
18
+ * Internal: resolve test warning messages (Mike Burns).
19
+
20
+
21
+ ## 6.3.0 (September 1, 2023)
22
+
23
+ * Fix: link to changelog for RubyGems (Berkan Ünal).
24
+ * Fix: integrate with Ruby 3.2's `did_you_mean` library (Daniel Colson).
25
+ * Changed: explicitly define `#destroyed?` within the `Stub` strategy to return `false` to be consistent
26
+ with ActiveRecord (Benjamin Fleischer).
27
+ * Added: announce `factory_bot.compile_factory` notification (Sean Doyle).
28
+ * Docs: clarify that custom strategies need to define `#to_sym` (Edmund Korley, Jonas S).
29
+ * Docs: fix CI link in README (Mark Huk).
30
+ * Docs: fix GitHub links (Robert Fletcher).
31
+ * Docs: install this library with `bundle add` (Glauco Custódio).
32
+ * Docs: re-write into mdBook (Mike Burns, Sara Jackson, Stefanni Brasil)
33
+ * Docs: clarify that automatic trait definitions could introduce new linting errors (Lawrence Chou).
34
+ * Internal: skip TruffleRuby on Rails 5.0, 5.1, 5.2 (Andrii Konchyn).
35
+ * Internal: fix typoes throughout codebase (Yudai Takada).
36
+ * Internal: run CI on `actions/checkout` v3 (Yudai Takada).
37
+ * Internal: follow standardrb code style (Yudai Takada).
38
+ * Internal: stop using Hound (Daniel Nolan).
39
+ * Internal: only run simplecov on C Ruby (Daniel Colson).
40
+ * Internal: quieter Cucumber (Daniel Colson).
41
+ * Internal: Ruby 3.2 support (Daniel Colson).
42
+ * Internal: Mike Burns is the CODEOWNER (Stefanni Brasil).
43
+
44
+ ## 6.2.1 (March 8, 2022)
45
+ * Added: CI testing against truffleruby
46
+ * Changed: Documentation improvements for sequences and traits
47
+ * Fixed: ActiveSupport::Notifications reporting strategy through associations now report as symbols
48
+ * BREAKING CHANGE: Custom strategies now need to define a `to_sym` method to specify the strategy identifier
49
+ * Fixed: `add_attribute` with reserved keywords assigns values correctly
50
+
3
51
  ## 6.2.0 (May 7, 2021)
4
52
  * Added: support for Ruby 3.0
5
53
  * Changed: Include factory or trait name in error messages for missing traits. d05a9a3c
@@ -21,7 +69,9 @@
21
69
  * Added: automatic definition of traits for Active Record enum attributes, enabled by default
22
70
  (Note that this required changing where factory_bot constantizes the build
23
71
  class, which may affect applications that were using abstract factories for
24
- inheritance. See issue #1409.)
72
+ inheritance. See issue #1409.) (This may break `FactoryBot.lint` because
73
+ there may be previously non-existing factory+trait combinations being
74
+ defined and checked)
25
75
  * Added: `traits_for_enum` method to define traits for non-Active Record enums
26
76
  * Added: `build_stubbed_starting_id=` option to define the starting id for `build_stubbed`
27
77
  * Removed: deprecated methods on the top-level `FactoryBot` module meant only for internal use
data/README.md CHANGED
@@ -16,24 +16,26 @@ Check out the [guide](https://github.com/thoughtbot/factory_bot/blob/4-9-0-stabl
16
16
  Documentation
17
17
  -------------
18
18
 
19
- You should find the documentation for your version of factory_bot on [Rubygems](https://rubygems.org/gems/factory_bot).
19
+ See our extensive reference, guides, and cookbook in [the factory_bot book][].
20
20
 
21
- See [GETTING_STARTED] for information on defining and using factories. We also
22
- have [a detailed introductory video][], available for free on Upcase.
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
- Add the following line to Gemfile:
33
+ Run:
30
34
 
31
35
  ```ruby
32
- gem 'factory_bot'
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/master/.github/workflows/build.yml)
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,8 +55,8 @@ 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/master/GETTING_STARTED.md
57
- [NAME]: https://github.com/thoughtbot/factory_bot/blob/master/NAME.md
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
  ------------
@@ -64,7 +66,7 @@ Useful Tools
64
66
  Contributing
65
67
  ------------
66
68
 
67
- Please see [CONTRIBUTING.md](https://github.com/thoughtbot/factory_bot/blob/master/CONTRIBUTING.md).
69
+ Please see [CONTRIBUTING.md](https://github.com/thoughtbot/factory_bot/blob/main/CONTRIBUTING.md).
68
70
 
69
71
  factory_bot was originally written by Joe Ferris and is maintained by thoughtbot.
70
72
  Many improvements and bugfixes were contributed by the [open source
@@ -73,11 +75,11 @@ community](https://github.com/thoughtbot/factory_bot/graphs/contributors).
73
75
  License
74
76
  -------
75
77
 
76
- factory_bot is Copyright © 2008-2020 Joe Ferris and thoughtbot. It is free
78
+ factory_bot is Copyright © 2008-2022 Joe Ferris and thoughtbot. It is free
77
79
  software, and may be redistributed under the terms specified in the
78
80
  [LICENSE] file.
79
81
 
80
- [LICENSE]: https://github.com/thoughtbot/factory_bot/blob/master/LICENSE
82
+ [LICENSE]: https://github.com/thoughtbot/factory_bot/blob/main/LICENSE
81
83
 
82
84
 
83
85
  About thoughtbot
@@ -94,8 +96,8 @@ See [our other projects][community] or
94
96
 
95
97
  [community]: https://thoughtbot.com/community?utm_source=github
96
98
  [hire]: https://thoughtbot.com/hire-us?utm_source=github
97
- [ci-image]: https://github.com/thoughtbot/factory_bot/actions/workflows/build.yml/badge.svg
98
- [ci]: https://github.com/thoughtbot/factory_bot/actions?query=workflow%3A.github%2Fworkflows%2Fbuild.yml+branch%3Amaster++
99
+ [ci-image]: https://github.com/thoughtbot/factory_bot/actions/workflows/build.yml/badge.svg?branch=main
100
+ [ci]: https://github.com/thoughtbot/factory_bot/actions?query=workflow%3ABuild+branch%3Amain
99
101
  [grade-image]: https://codeclimate.com/github/thoughtbot/factory_bot/badges/gpa.svg
100
102
  [grade]: https://codeclimate.com/github/thoughtbot/factory_bot
101
103
  [version-image]: https://badge.fury.io/rb/factory_bot.svg
@@ -10,7 +10,7 @@ module FactoryBot
10
10
 
11
11
  def self.aliases_for(attribute)
12
12
  aliases.map { |(pattern, replace)|
13
- if pattern.match(attribute.to_s)
13
+ if pattern.match?(attribute)
14
14
  attribute.to_s.sub(pattern, replace).to_sym
15
15
  end
16
16
  }.compact << attribute
@@ -12,8 +12,8 @@ module FactoryBot
12
12
 
13
13
  -> {
14
14
  value = case block.arity
15
- when 1, -1, -2 then instance_exec(self, &block)
16
- else instance_exec(&block)
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
 
@@ -37,8 +37,9 @@ module FactoryBot
37
37
  end
38
38
 
39
39
  def decorated_evaluator
40
- Decorator::InvocationTracker.new(
41
- Decorator::NewConstructor.new(@evaluator, @build_class)
40
+ Decorator::NewConstructor.new(
41
+ Decorator::InvocationTracker.new(@evaluator),
42
+ @build_class
42
43
  )
43
44
  end
44
45
 
@@ -17,7 +17,7 @@ module FactoryBot
17
17
  end
18
18
  RUBY
19
19
  else
20
- def method_missing(name, *args, &block) # rubocop:disable Style/MethodMissingSuper, Style/MissingRespondToMissing
20
+ def method_missing(name, *args, &block) # rubocop:disable Style/MissingRespondToMissing
21
21
  @component.send(name, *args, &block)
22
22
  end
23
23
 
@@ -2,6 +2,7 @@ module FactoryBot
2
2
  # @api private
3
3
  class Definition
4
4
  attr_reader :defined_traits, :declarations, :name, :registered_enums
5
+ attr_accessor :klass
5
6
 
6
7
  def initialize(name, base_traits = [])
7
8
  @name = name
@@ -51,12 +52,21 @@ module FactoryBot
51
52
 
52
53
  declarations.attributes
53
54
 
55
+ self.klass ||= klass
54
56
  defined_traits.each do |defined_trait|
57
+ defined_trait.klass ||= klass
55
58
  base_traits.each { |bt| bt.define_trait defined_trait }
56
59
  additional_traits.each { |at| at.define_trait defined_trait }
57
60
  end
58
61
 
59
62
  @compiled = true
63
+
64
+ ActiveSupport::Notifications.instrument "factory_bot.compile_factory", {
65
+ name: name,
66
+ attributes: declarations.attributes,
67
+ traits: defined_traits,
68
+ class: klass || self.klass
69
+ }
60
70
  end
61
71
  end
62
72
 
@@ -115,15 +125,26 @@ module FactoryBot
115
125
  raise error_with_definition_name(error)
116
126
  end
117
127
 
118
- def error_with_definition_name(error)
119
- message = error.message
120
- message.insert(
121
- message.index("\nDid you mean?") || message.length,
122
- " referenced within \"#{name}\" definition"
123
- )
128
+ # detailed_message introduced in Ruby 3.2 for cleaner integration with
129
+ # did_you_mean. See https://bugs.ruby-lang.org/issues/18564
130
+ if KeyError.method_defined?(:detailed_message)
131
+ def error_with_definition_name(error)
132
+ message = error.message + " referenced within \"#{name}\" definition"
124
133
 
125
- error.class.new(message).tap do |new_error|
126
- new_error.set_backtrace(error.backtrace)
134
+ error.class.new(message, key: error.key, receiver: error.receiver)
135
+ .tap { |new_error| new_error.set_backtrace(error.backtrace) }
136
+ end
137
+ else
138
+ def error_with_definition_name(error)
139
+ message = error.message
140
+ message.insert(
141
+ message.index("\nDid you mean?") || message.length,
142
+ " referenced within \"#{name}\" definition"
143
+ )
144
+
145
+ error.class.new(message).tap do |new_error|
146
+ new_error.set_backtrace(error.backtrace)
147
+ end
127
148
  end
128
149
  end
129
150
 
@@ -132,7 +153,7 @@ module FactoryBot
132
153
  end
133
154
 
134
155
  def trait_by_name(name)
135
- trait_for(name) || Internal.trait_by_name(name)
156
+ trait_for(name) || Internal.trait_by_name(name, klass)
136
157
  end
137
158
 
138
159
  def trait_for(name)
@@ -88,7 +88,7 @@ module FactoryBot
88
88
  # end
89
89
  #
90
90
  # are equivalent.
91
- def method_missing(name, *args, &block) # rubocop:disable Style/MissingRespondToMissing, Style/MethodMissingSuper
91
+ def method_missing(name, *args, &block) # rubocop:disable Style/MissingRespondToMissing
92
92
  association_options = args.first
93
93
 
94
94
  if association_options.nil?
@@ -151,7 +151,7 @@ module FactoryBot
151
151
  def association(name, *options)
152
152
  if block_given?
153
153
  raise AssociationDefinitionError.new(
154
- "Unexpected block passed to '#{name}' association "\
154
+ "Unexpected block passed to '#{name}' association " \
155
155
  "in '#{@definition.name}' factory"
156
156
  )
157
157
  else
@@ -24,7 +24,7 @@ module FactoryBot
24
24
  def association(factory_name, *traits_and_overrides)
25
25
  overrides = traits_and_overrides.extract_options!
26
26
  strategy_override = overrides.fetch(:strategy) {
27
- FactoryBot.use_parent_strategy ? @build_strategy.class : :create
27
+ FactoryBot.use_parent_strategy ? @build_strategy.to_sym : :create
28
28
  }
29
29
 
30
30
  traits_and_overrides += [overrides.except(:strategy)]
@@ -35,7 +35,7 @@ module FactoryBot
35
35
 
36
36
  attr_accessor :instance
37
37
 
38
- def method_missing(method_name, *args, &block) # rubocop:disable Style/MethodMissingSuper, Style/MissingRespondToMissing
38
+ def method_missing(method_name, *args, &block)
39
39
  if @instance.respond_to?(method_name)
40
40
  @instance.send(method_name, *args, &block)
41
41
  else
@@ -39,8 +39,8 @@ module FactoryBot
39
39
  trait
40
40
  end
41
41
 
42
- def trait_by_name(name)
43
- traits.find(name)
42
+ def trait_by_name(name, klass)
43
+ traits.find(name).tap { |t| t.klass = klass }
44
44
  end
45
45
 
46
46
  def register_sequence(sequence)
@@ -39,9 +39,21 @@ module FactoryBot
39
39
 
40
40
  def key_error_with_custom_message(key_error)
41
41
  message = key_error.message.sub("key not found", "#{@name} not registered")
42
- error = KeyError.new(message)
43
- error.set_backtrace(key_error.backtrace)
44
- error
42
+ new_key_error(message, key_error).tap do |error|
43
+ error.set_backtrace(key_error.backtrace)
44
+ end
45
+ end
46
+
47
+ # detailed_message introduced in Ruby 3.2 for cleaner integration with
48
+ # did_you_mean. See https://bugs.ruby-lang.org/issues/18564
49
+ if KeyError.method_defined?(:detailed_message)
50
+ def new_key_error(message, key_error)
51
+ KeyError.new(message, key: key_error.key, receiver: key_error.receiver)
52
+ end
53
+ else
54
+ def new_key_error(message, _)
55
+ KeyError.new(message)
56
+ end
45
57
  end
46
58
  end
47
59
  end
@@ -8,6 +8,10 @@ module FactoryBot
8
8
  def result(evaluation)
9
9
  evaluation.hash
10
10
  end
11
+
12
+ def to_sym
13
+ :attributes_for
14
+ end
11
15
  end
12
16
  end
13
17
  end
@@ -10,6 +10,10 @@ module FactoryBot
10
10
  evaluation.notify(:after_build, instance)
11
11
  end
12
12
  end
13
+
14
+ def to_sym
15
+ :build
16
+ end
13
17
  end
14
18
  end
15
19
  end
@@ -13,6 +13,10 @@ module FactoryBot
13
13
  evaluation.notify(:after_create, instance)
14
14
  end
15
15
  end
16
+
17
+ def to_sym
18
+ :create
19
+ end
16
20
  end
17
21
  end
18
22
  end
@@ -6,6 +6,10 @@ module FactoryBot
6
6
 
7
7
  def result(evaluation)
8
8
  end
9
+
10
+ def to_sym
11
+ :null
12
+ end
9
13
  end
10
14
  end
11
15
  end
@@ -41,15 +41,23 @@ module FactoryBot
41
41
  end
42
42
  end
43
43
 
44
+ def to_sym
45
+ :stub
46
+ end
47
+
44
48
  private
45
49
 
46
- def next_id
47
- @@next_id += 1
50
+ def next_id(result_instance)
51
+ if uuid_primary_key?(result_instance)
52
+ SecureRandom.uuid
53
+ else
54
+ @@next_id += 1
55
+ end
48
56
  end
49
57
 
50
58
  def stub_database_interaction_on_result(result_instance)
51
59
  if has_settable_id?(result_instance)
52
- result_instance.id ||= next_id
60
+ result_instance.id ||= next_id(result_instance)
53
61
  end
54
62
 
55
63
  result_instance.instance_eval do
@@ -62,12 +70,12 @@ module FactoryBot
62
70
  end
63
71
 
64
72
  def destroyed?
65
- nil
73
+ false
66
74
  end
67
75
 
68
76
  DISABLED_PERSISTENCE_METHODS.each do |write_method|
69
77
  define_singleton_method(write_method) do |*args|
70
- raise "stubbed models are not allowed to access the database - "\
78
+ raise "stubbed models are not allowed to access the database - " \
71
79
  "#{self.class}##{write_method}(#{args.join(",")})"
72
80
  end
73
81
  end
@@ -79,6 +87,13 @@ module FactoryBot
79
87
  result_instance.class.primary_key
80
88
  end
81
89
 
90
+ def uuid_primary_key?(result_instance)
91
+ result_instance.respond_to?(:column_for_attribute) &&
92
+ (column = result_instance.column_for_attribute(result_instance.class.primary_key)) &&
93
+ column.respond_to?(:sql_type) &&
94
+ column.sql_type == "uuid"
95
+ end
96
+
82
97
  def clear_changes_information(result_instance)
83
98
  if result_instance.respond_to?(:clear_changes_information)
84
99
  result_instance.clear_changes_information
@@ -15,7 +15,7 @@ module FactoryBot
15
15
  end
16
16
 
17
17
  delegate :add_callback, :declare_attribute, :to_create, :define_trait, :constructor,
18
- :callbacks, :attributes, to: :@definition
18
+ :callbacks, :attributes, :klass, :klass=, to: :@definition
19
19
 
20
20
  def names
21
21
  [@name]
@@ -1,3 +1,3 @@
1
1
  module FactoryBot
2
- VERSION = "6.2.0".freeze
2
+ VERSION = "6.4.2".freeze
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: factory_bot
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.2.0
4
+ version: 6.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josh Clayton
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-05-07 00:00:00.000000000 Z
12
+ date: 2023-11-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -236,7 +236,8 @@ files:
236
236
  homepage: https://github.com/thoughtbot/factory_bot
237
237
  licenses:
238
238
  - MIT
239
- metadata: {}
239
+ metadata:
240
+ changelog_uri: https://github.com/thoughtbot/factory_bot/blob/main/NEWS.md
240
241
  post_install_message:
241
242
  rdoc_options: []
242
243
  require_paths:
@@ -252,7 +253,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
252
253
  - !ruby/object:Gem::Version
253
254
  version: '0'
254
255
  requirements: []
255
- rubygems_version: 3.2.16
256
+ rubygems_version: 3.4.10
256
257
  signing_key:
257
258
  specification_version: 4
258
259
  summary: factory_bot provides a framework and DSL for defining and using model instance