factory_bot 6.2.1 → 6.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3bcbbd8bee01abdb25a5cfdbbbbca29396f587236f0c20f8300adbf6e32f783c
4
- data.tar.gz: 94d8e73507ae61edba7fb3129ee74c4fe9998a8fb78614ecba9966199561c8e4
3
+ metadata.gz: 44611a193b219b270cd43b7a8587718ff190b3c63162c17f02288afc362a37e9
4
+ data.tar.gz: a1a3d3ce45776e1d8d228f113af1c101a64090fde8f19a46321d40bec3df0e48
5
5
  SHA512:
6
- metadata.gz: e97d9530810f0de00f6e0129df37db52722ee8d430f7b118ffdcebdc0eecc1e1532356b7c8e01cc85265c04f18eb174d3d5ff09fe235c5f30ceb7b5e16432508
7
- data.tar.gz: 71b77c30b16c89588d6946505be547374321597e8e16f89673766cda94b22188dc28070a34144ae126dad93042de0173e1d92173237ae1e929a3131e85569a51
6
+ metadata.gz: 2e65a906e197e8e9f268440ba3ffbc0a717b211420419f0ce0f9ff0a5b5e90413d4a76b829f45fe4746541aae91869afdee8975b3171841c4655d6627979aa2b
7
+ data.tar.gz: 400e0cb1dab0994f26a46674a5d7f0cb6dc89a95815faab5da8838f732c9e6ac92fac6af17270ce4aaba3f84cdcbfcf96361021a7671a37e33a9d27e77cb652b
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
@@ -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`
@@ -1206,11 +1259,11 @@ FactoryBot.define do
1206
1259
  created_at { 8.days.ago }
1207
1260
  updated_at { 4.days.ago }
1208
1261
  end
1209
-
1262
+
1210
1263
  factory :user, traits: [:timestamps] do
1211
1264
  username { "john_doe" }
1212
1265
  end
1213
-
1266
+
1214
1267
  factory :post do
1215
1268
  timestamps
1216
1269
  title { "Traits rock" }
@@ -1872,6 +1925,10 @@ class JsonStrategy
1872
1925
  def result(evaluation)
1873
1926
  @strategy.result(evaluation).to_json
1874
1927
  end
1928
+
1929
+ def to_sym
1930
+ :json
1931
+ end
1875
1932
  end
1876
1933
  ```
1877
1934
 
@@ -1912,6 +1969,10 @@ class JsonStrategy
1912
1969
  evaluation.notify(:make_json_awesome, json)
1913
1970
  end
1914
1971
  end
1972
+
1973
+ def to_sym
1974
+ :json
1975
+ end
1915
1976
  end
1916
1977
 
1917
1978
  FactoryBot.register_strategy(:json, JsonStrategy)
@@ -1966,7 +2027,7 @@ ActiveSupport Instrumentation
1966
2027
 
1967
2028
  In order to track what factories are created (and with what build strategy),
1968
2029
  `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
2030
+ factories being compiled and run. One example would be to track factories based on a
1970
2031
  threshold of execution time.
1971
2032
 
1972
2033
  ```ruby
@@ -2000,6 +2061,29 @@ config.after(:suite) do
2000
2061
  end
2001
2062
  ```
2002
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
+
2003
2087
  Rails Preloaders and RSpec
2004
2088
  --------------------------
2005
2089
 
data/NEWS.md CHANGED
@@ -1,9 +1,92 @@
1
1
  # News
2
2
 
3
+ ## 6.5.0 (September 6, 2024)
4
+
5
+ * fix: issue 1621 broken links in ref/factory.md by @elasticspoon in https://github.com/thoughtbot/factory_bot/pull/1623
6
+ * Add standard settings by @ydah in https://github.com/thoughtbot/factory_bot/pull/1625
7
+ * Call dynamic-readme reusable workflow by @stefannibrasil in https://github.com/thoughtbot/factory_bot/pull/1628
8
+ * Update README again by @stefannibrasil in https://github.com/thoughtbot/factory_bot/pull/1630
9
+ * Only run this workflow if the README has been updated by @stefannibrasil in https://github.com/thoughtbot/factory_bot/pull/1635
10
+ * Automatically Generated: Update Dynamic Section in README by @github-actions in https://github.com/thoughtbot/factory_bot/pull/1637
11
+ * 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
12
+ * Add Ruby 3.3 to CI by @berkos in https://github.com/thoughtbot/factory_bot/pull/1615
13
+ * Update Dependabot configuration by @smaboshe in https://github.com/thoughtbot/factory_bot/pull/1655
14
+ * Add new maintainers to CODEOWNERS by @sarahraqueld in https://github.com/thoughtbot/factory_bot/pull/1651
15
+ * Improve docs formatting and fix filename conflicts by @sarahraqueld in https://github.com/thoughtbot/factory_bot/pull/1666
16
+ * Add a dynamic security workflow and a SECURITY.md file by @sarahraqueld in https://github.com/thoughtbot/factory_bot/pull/1677
17
+ * Automatically Generated: Update Dynamic Section in SECURITY by @github-actions in https://github.com/thoughtbot/factory_bot/pull/1678
18
+ * Ensure rails 7.2 compatibility by @Earlopain in https://github.com/thoughtbot/factory_bot/pull/1686
19
+ * Fix the factory definition in traits documentation by @ddieulivol in https://github.com/thoughtbot/factory_bot/pull/1688
20
+
21
+ ## 6.4.6 (January 30, 2023)
22
+
23
+ * Fix: Bump minimum required Ruby in gemspec (Earlopain).
24
+ * Fix: Broken link in `FactoryBot.modify` docs (Matt Brictson).
25
+ * Fix: Broken link in `FactoryBot.lint` docs (Anton Dieterle).
26
+
27
+ ## 6.4.5 (December 29, 2023)
28
+
29
+ * Changed: Support Ruby 3.0+, Rails 6.1+ (Mike Burns).
30
+
31
+ ## 6.4.4 (December 27, 2023)
32
+
33
+ * Internal: Remove observer dependency (Earlopain).
34
+
35
+ ## 6.4.3 (December 26, 2023)
36
+
37
+ * Fix: Support models without ID setters in build_stubbed (Olivier Bellone).
38
+ * Fix: Explicit observer dependency (Oleg Antonyan).
39
+ * Internal: Add Rails 7.1 to CI (Olivier Bellone).
40
+ * Internal: Bump github actions/checkout to v4 (Lorenzo Zabot)
41
+ * Internal: Stop passing disable-error_highlight in CI (Mike Burns).
42
+ * Internal: Relax the exception message check (Mike Burns).
43
+
44
+ ## 6.4.2 (November 22, 2023)
45
+
46
+ * Fix: top-level traits pass their class to ActiveSupport::Notifications
47
+ (makicamel).
48
+
49
+ ## 6.4.1 (November 20, 2023)
50
+
51
+ * Fix: factories with traits pass their class to ActiveSupport::Notifications
52
+ (makicamel).
53
+
54
+ ## 6.4.0 (November 17, 2023)
55
+
56
+ * Added: if `build_stubbed` detects a UUID primary key, generate the correct
57
+ type (Peter Boling, Alexandre Ruban).
58
+ * Docs: show examples of Ruby 3 syntactic sugars (Sean Doyle).
59
+ * Internal: resolve test warning messages (Mike Burns).
60
+
61
+
62
+ ## 6.3.0 (September 1, 2023)
63
+
64
+ * Fix: link to changelog for RubyGems (Berkan Ünal).
65
+ * Fix: integrate with Ruby 3.2's `did_you_mean` library (Daniel Colson).
66
+ * Changed: explicitly define `#destroyed?` within the `Stub` strategy to return `false` to be consistent
67
+ with ActiveRecord (Benjamin Fleischer).
68
+ * Added: announce `factory_bot.compile_factory` notification (Sean Doyle).
69
+ * Docs: clarify that custom strategies need to define `#to_sym` (Edmund Korley, Jonas S).
70
+ * Docs: fix CI link in README (Mark Huk).
71
+ * Docs: fix GitHub links (Robert Fletcher).
72
+ * Docs: install this library with `bundle add` (Glauco Custódio).
73
+ * Docs: re-write into mdBook (Mike Burns, Sara Jackson, Stefanni Brasil)
74
+ * Docs: clarify that automatic trait definitions could introduce new linting errors (Lawrence Chou).
75
+ * Internal: skip TruffleRuby on Rails 5.0, 5.1, 5.2 (Andrii Konchyn).
76
+ * Internal: fix typoes throughout codebase (Yudai Takada).
77
+ * Internal: run CI on `actions/checkout` v3 (Yudai Takada).
78
+ * Internal: follow standardrb code style (Yudai Takada).
79
+ * Internal: stop using Hound (Daniel Nolan).
80
+ * Internal: only run simplecov on C Ruby (Daniel Colson).
81
+ * Internal: quieter Cucumber (Daniel Colson).
82
+ * Internal: Ruby 3.2 support (Daniel Colson).
83
+ * Internal: Mike Burns is the CODEOWNER (Stefanni Brasil).
84
+
3
85
  ## 6.2.1 (March 8, 2022)
4
86
  * Added: CI testing against truffleruby
5
87
  * Changed: Documentation improvements for sequences and traits
6
88
  * Fixed: ActiveSupport::Notifications reporting strategy through associations now report as symbols
89
+ * BREAKING CHANGE: Custom strategies now need to define a `to_sym` method to specify the strategy identifier
7
90
  * Fixed: `add_attribute` with reserved keywords assigns values correctly
8
91
 
9
92
  ## 6.2.0 (May 7, 2021)
@@ -27,7 +110,9 @@
27
110
  * Added: automatic definition of traits for Active Record enum attributes, enabled by default
28
111
  (Note that this required changing where factory_bot constantizes the build
29
112
  class, which may affect applications that were using abstract factories for
30
- inheritance. See issue #1409.)
113
+ inheritance. See issue #1409.) (This may break `FactoryBot.lint` because
114
+ there may be previously non-existing factory+trait combinations being
115
+ defined and checked)
31
116
  * Added: `traits_for_enum` method to define traits for non-Active Record enums
32
117
  * Added: `build_stubbed_starting_id=` option to define the starting id for `build_stubbed`
33
118
  * 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,29 +75,32 @@ 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 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
 
84
+ <!-- START /templates/footer.md -->
85
+ ## About thoughtbot
82
86
 
83
- About thoughtbot
84
- ----------------
85
-
86
- ![thoughtbot](https://thoughtbot.com/brand_assets/93:44.svg)
87
+ ![thoughtbot](https://thoughtbot.com/thoughtbot-logo-for-readmes.svg)
87
88
 
88
- factory_bot is maintained and funded by thoughtbot, inc.
89
+ This repo is maintained and funded by thoughtbot, inc.
89
90
  The names and logos for thoughtbot are trademarks of thoughtbot, inc.
90
91
 
91
92
  We love open source software!
92
- See [our other projects][community] or
93
- [hire us][hire] to design, develop, and grow your product.
93
+ See [our other projects][community].
94
+ We are [available for hire][hire].
94
95
 
95
96
  [community]: https://thoughtbot.com/community?utm_source=github
96
97
  [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++
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
- 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
 
@@ -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
- if ::Gem::Version.new(::RUBY_VERSION) >= ::Gem::Version.new("2.7")
10
- class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
11
- def method_missing(...) # rubocop:disable Style/MethodMissingSuper, Style/MissingRespondToMissing
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
- def send(symbol, *args, &block)
25
- __send__(symbol, *args, &block)
26
- end
13
+ def send(...)
14
+ __send__(...)
27
15
  end
28
16
 
29
17
  def respond_to_missing?(name, include_private = false)
@@ -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)
@@ -119,8 +119,8 @@ module FactoryBot
119
119
  # end
120
120
  #
121
121
  # Except that no globally available sequence will be defined.
122
- def sequence(name, *args, &block)
123
- sequence = Sequence.new(name, *args, &block)
122
+ def sequence(name, ...)
123
+ sequence = Sequence.new(name, ...)
124
124
  FactoryBot::Internal.register_inline_sequence(sequence)
125
125
  add_attribute(name) { increment_sequence(sequence) }
126
126
  end
@@ -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
@@ -1,13 +1,10 @@
1
- require "observer"
2
-
3
1
  module FactoryBot
4
2
  class Evaluation
5
- include Observable
6
-
7
- def initialize(evaluator, attribute_assigner, to_create)
3
+ def initialize(evaluator, attribute_assigner, to_create, observer)
8
4
  @evaluator = evaluator
9
5
  @attribute_assigner = attribute_assigner
10
6
  @to_create = to_create
7
+ @observer = observer
11
8
  end
12
9
 
13
10
  delegate :object, :hash, to: :@attribute_assigner
@@ -20,8 +17,7 @@ module FactoryBot
20
17
  end
21
18
 
22
19
  def notify(name, result_instance)
23
- changed
24
- notify_observers(name, result_instance)
20
+ @observer.update(name, result_instance)
25
21
  end
26
22
  end
27
23
  end
@@ -35,14 +35,13 @@ module FactoryBot
35
35
 
36
36
  attr_accessor :instance
37
37
 
38
- def method_missing(method_name, *args, &block)
38
+ def method_missing(method_name, ...)
39
39
  if @instance.respond_to?(method_name)
40
- @instance.send(method_name, *args, &block)
40
+ @instance.send(method_name, ...)
41
41
  else
42
- SyntaxRunner.new.send(method_name, *args, &block)
42
+ SyntaxRunner.new.send(method_name, ...)
43
43
  end
44
44
  end
45
- ruby2_keywords :method_missing if respond_to?(:ruby2_keywords, true)
46
45
 
47
46
  def respond_to_missing?(method_name, _include_private = false)
48
47
  @instance.respond_to?(method_name) || SyntaxRunner.new.respond_to?(method_name)
@@ -22,6 +22,8 @@ module FactoryBot
22
22
  def build_class
23
23
  @build_class ||= if class_name.is_a? Class
24
24
  class_name
25
+ elsif class_name.to_s.safe_constantize
26
+ class_name.to_s.safe_constantize
25
27
  else
26
28
  class_name.to_s.camelize.constantize
27
29
  end
@@ -36,9 +38,9 @@ module FactoryBot
36
38
  evaluator = evaluator_class.new(strategy, overrides.symbolize_keys)
37
39
  attribute_assigner = AttributeAssigner.new(evaluator, build_class, &compiled_constructor)
38
40
 
41
+ observer = CallbacksObserver.new(callbacks, evaluator)
39
42
  evaluation =
40
- Evaluation.new(evaluator, attribute_assigner, compiled_to_create)
41
- evaluation.add_observer(CallbacksObserver.new(callbacks, evaluator))
43
+ Evaluation.new(evaluator, attribute_assigner, compiled_to_create, observer)
42
44
 
43
45
  strategy.result(evaluation).tap(&block)
44
46
  end
@@ -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
@@ -47,13 +47,17 @@ module FactoryBot
47
47
 
48
48
  private
49
49
 
50
- def next_id
51
- @@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
52
56
  end
53
57
 
54
58
  def stub_database_interaction_on_result(result_instance)
55
59
  if has_settable_id?(result_instance)
56
- result_instance.id ||= next_id
60
+ result_instance.id ||= next_id(result_instance)
57
61
  end
58
62
 
59
63
  result_instance.instance_eval do
@@ -66,12 +70,12 @@ module FactoryBot
66
70
  end
67
71
 
68
72
  def destroyed?
69
- nil
73
+ false
70
74
  end
71
75
 
72
76
  DISABLED_PERSISTENCE_METHODS.each do |write_method|
73
77
  define_singleton_method(write_method) do |*args|
74
- raise "stubbed models are not allowed to access the database - "\
78
+ raise "stubbed models are not allowed to access the database - " \
75
79
  "#{self.class}##{write_method}(#{args.join(",")})"
76
80
  end
77
81
  end
@@ -79,8 +83,16 @@ module FactoryBot
79
83
  end
80
84
 
81
85
  def has_settable_id?(result_instance)
82
- !result_instance.class.respond_to?(:primary_key) ||
83
- result_instance.class.primary_key
86
+ result_instance.respond_to?(:id=) &&
87
+ (!result_instance.class.respond_to?(:primary_key) ||
88
+ result_instance.class.primary_key)
89
+ end
90
+
91
+ def uuid_primary_key?(result_instance)
92
+ result_instance.respond_to?(:column_for_attribute) &&
93
+ (column = result_instance.column_for_attribute(result_instance.class.primary_key)) &&
94
+ column.respond_to?(:sql_type) &&
95
+ column.sql_type == "uuid"
84
96
  end
85
97
 
86
98
  def clear_changes_information(result_instance)
@@ -25,8 +25,8 @@ module FactoryBot
25
25
  end
26
26
  end
27
27
 
28
- def sequence(name, *args, &block)
29
- Internal.register_sequence(Sequence.new(name, *args, &block))
28
+ def sequence(name, ...)
29
+ Internal.register_sequence(Sequence.new(name, ...))
30
30
  end
31
31
 
32
32
  def trait(name, &block)
@@ -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.1".freeze
2
+ VERSION = "6.5.0".freeze
3
3
  end
data/lib/factory_bot.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require "set"
2
+ require "active_support"
2
3
  require "active_support/core_ext/module/delegation"
3
4
  require "active_support/core_ext/module/attribute_accessors"
4
5
  require "active_support/deprecation"
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.1
4
+ version: 6.5.0
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: 2022-03-18 00:00:00.000000000 Z
12
+ date: 2024-09-06 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:
@@ -245,14 +246,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
245
246
  requirements:
246
247
  - - ">="
247
248
  - !ruby/object:Gem::Version
248
- version: 2.5.0
249
+ version: 3.0.0
249
250
  required_rubygems_version: !ruby/object:Gem::Requirement
250
251
  requirements:
251
252
  - - ">="
252
253
  - !ruby/object:Gem::Version
253
254
  version: '0'
254
255
  requirements: []
255
- rubygems_version: 3.1.6
256
+ rubygems_version: 3.5.18
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