factory_bot 6.1.0 → 6.2.1

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: fe33ad3bb5d907e38ceac543f969484fb0ec67a4708a701cdfea0696d4a292c4
4
- data.tar.gz: 54cdb44f4ac7782360c8e9efd02ac46f40336d00c34a5767d5d7fc0f86f8d7a5
3
+ metadata.gz: 3bcbbd8bee01abdb25a5cfdbbbbca29396f587236f0c20f8300adbf6e32f783c
4
+ data.tar.gz: 94d8e73507ae61edba7fb3129ee74c4fe9998a8fb78614ecba9966199561c8e4
5
5
  SHA512:
6
- metadata.gz: cdc3ec9def71e797058fb13cff95b911eceb61d1488f193ef1bfb6bdf12c6c7835d1f67dc1885d5539e6da7135f04e4a417a16fbc60cbc0c4d60056a1948c89d
7
- data.tar.gz: 2f04ab1a184266a86cf8510be688b8a01b0dd570615d25e314176b4492f9635053596636aa4ec9ab8133e86e4c9f630acdb52468c01ea1bfd2fb8777fc27b2ab
6
+ metadata.gz: e97d9530810f0de00f6e0129df37db52722ee8d430f7b118ffdcebdc0eecc1e1532356b7c8e01cc85265c04f18eb174d3d5ff09fe235c5f30ceb7b5e16432508
7
+ data.tar.gz: 71b77c30b16c89588d6946505be547374321597e8e16f89673766cda94b22188dc28070a34144ae126dad93042de0173e1d92173237ae1e929a3131e85569a51
data/CONTRIBUTING.md CHANGED
@@ -51,6 +51,12 @@ Here are some ways *you* can contribute:
51
51
  asking for help. We love helping!
52
52
  * Please don't update the Gem version.
53
53
 
54
+ ## Setting up
55
+
56
+ ```sh
57
+ bundle install
58
+ ```
59
+
54
60
  ## Running the test suite
55
61
 
56
62
  The default rake task will run the full test suite and [standard]:
data/GETTING_STARTED.md CHANGED
@@ -37,12 +37,15 @@ Getting Started
37
37
  * [Associations](#associations)
38
38
  + [Implicit definition](#implicit-definition)
39
39
  + [Explicit definition](#explicit-definition)
40
+ + [Inline definition](#inline-definition)
40
41
  + [Specifying the factory](#specifying-the-factory)
41
42
  + [Overriding attributes](#overriding-attributes)
43
+ + [Association overrides](#association-overrides)
42
44
  + [Build strategies](#build-strategies-1)
43
45
  + [`has_many` associations](#has_many-associations)
44
46
  + [`has_and_belongs_to_many` associations](#has_and_belongs_to_many-associations)
45
47
  + [Polymorphic associations](#polymorphic-associations)
48
+ + [Interconnected associations](#interconnected-associations)
46
49
  * [Sequences](#sequences)
47
50
  + [Global sequences](#global-sequences)
48
51
  + [With dynamic attributes](#with-dynamic-attributes)
@@ -197,17 +200,15 @@ It is also possible to explicitly specify the class:
197
200
 
198
201
  ```ruby
199
202
  # This will use the User class (otherwise Admin would have been guessed)
200
- factory :admin, class: User
203
+ factory :admin, class: "User"
201
204
  ```
202
205
 
203
- If the constant is not available
204
- (if you are using a Rails engine that waits to load models, for example),
205
- you can also pass a symbol or string,
206
- which factory\_bot will constantize later, once you start building objects:
206
+ You can pass a constant as well, if the constant is available (note that this
207
+ can cause test performance problems in large Rails applications, since
208
+ referring to the constant will cause it to be eagerly loaded).
207
209
 
208
210
  ```ruby
209
- # It's OK if Doorkeeper::AccessToken isn't loaded yet
210
- factory :access_token, class: "Doorkeeper::AccessToken"
211
+ factory :access_token, class: User
211
212
  ```
212
213
 
213
214
  ### Hash attributes
@@ -312,17 +313,17 @@ factory :user, aliases: [:author, :commenter] do
312
313
  end
313
314
 
314
315
  factory :post do
315
- author
316
- # instead of
316
+ # The alias allows us to write author instead of
317
317
  # association :author, factory: :user
318
+ author
318
319
  title { "How to read a book effectively" }
319
320
  body { "There are five steps involved." }
320
321
  end
321
322
 
322
323
  factory :comment do
323
- commenter
324
- # instead of
324
+ # The alias allows us to write commenter instead of
325
325
  # association :commenter, factory: :user
326
+ commenter
326
327
  body { "Great article!" }
327
328
  end
328
329
  ```
@@ -346,6 +347,7 @@ create(:user, last_name: "Doe").email
346
347
 
347
348
  Transient Attributes
348
349
  --------------------
350
+ Transient attributes are attributes only available within the factory definition, and not set on the object being built. This allows for more complex logic inside factories.
349
351
 
350
352
  ### With other attributes
351
353
 
@@ -505,6 +507,19 @@ factory :post do
505
507
  end
506
508
  ```
507
509
 
510
+ ### Inline definition
511
+
512
+ You can also define associations inline within regular attributes,
513
+ but note that the value will be `nil`
514
+ when using the `attributes_for` strategy.
515
+
516
+ ```ruby
517
+ factory :post do
518
+ # ...
519
+ author { association :author }
520
+ end
521
+ ```
522
+
508
523
  ### Specifying the factory
509
524
 
510
525
  You can specify a different factory (although [Aliases](#aliases) might also
@@ -528,6 +543,15 @@ factory :post do
528
543
  end
529
544
  ```
530
545
 
546
+ Inline:
547
+
548
+ ```ruby
549
+ factory :post do
550
+ # ...
551
+ author { association :user }
552
+ end
553
+ ```
554
+
531
555
  ### Overriding attributes
532
556
 
533
557
  You can also override attributes.
@@ -551,6 +575,35 @@ factory :post do
551
575
  end
552
576
  ```
553
577
 
578
+ Or inline using attributes from the factory:
579
+
580
+ ```rb
581
+ factory :post do
582
+ # ...
583
+ author_last_name { "Writely" }
584
+ author { association :author, last_name: author_last_name }
585
+ end
586
+ ```
587
+
588
+ ### Association overrides
589
+
590
+ Attribute overrides can be used to link associated objects:
591
+
592
+ ```ruby
593
+ FactoryBot.define do
594
+ factory :author do
595
+ name { 'Taylor' }
596
+ end
597
+
598
+ factory :post do
599
+ author
600
+ end
601
+ end
602
+
603
+ eunji = build(:author, name: 'Eunji')
604
+ post = build(:post, author: eunji)
605
+ ```
606
+
554
607
  ### Build strategies
555
608
 
556
609
  In factory\_bot 5, associations default to using the same build strategy as
@@ -620,27 +673,51 @@ factory :post do
620
673
 
621
674
  ### `has_many` associations
622
675
 
623
- Generating data for a `has_many` relationship is a bit more involved,
624
- depending on the amount of flexibility desired, but here's a surefire example
625
- of generating associated data.
676
+ There are a few ways to generate data for a `has_many` relationship. The
677
+ simplest approach is to write a helper method in plain Ruby to tie together the
678
+ different records:
626
679
 
627
680
  ```ruby
628
681
  FactoryBot.define do
682
+ factory :post do
683
+ title { "Through the Looking Glass" }
684
+ user
685
+ end
686
+
687
+ factory :user do
688
+ name { "Rachel Sanchez" }
689
+ end
690
+ end
691
+
692
+ def user_with_posts(posts_count: 5)
693
+ FactoryBot.create(:user) do |user|
694
+ FactoryBot.create_list(:post, posts_count, user: user)
695
+ end
696
+ end
697
+
698
+ create(:user).posts.length # 0
699
+ user_with_posts.posts.length # 5
700
+ user_with_posts(posts_count: 15).posts.length # 15
701
+ ```
629
702
 
630
- # post factory with a `belongs_to` association for the user
703
+ If you prefer to keep the object creation fully within factory\_bot, you can
704
+ build the posts in an `after(:create)` callback.
705
+
706
+
707
+ ```ruby
708
+ FactoryBot.define do
631
709
  factory :post do
632
710
  title { "Through the Looking Glass" }
633
711
  user
634
712
  end
635
713
 
636
- # user factory without associated posts
637
714
  factory :user do
638
715
  name { "John Doe" }
639
716
 
640
717
  # user_with_posts will create post data after the user has been created
641
718
  factory :user_with_posts do
642
- # posts_count is declared as a transient attribute and available in
643
- # attributes on the factory, as well as the callback via the evaluator
719
+ # posts_count is declared as a transient attribute available in the
720
+ # callback via the evaluator
644
721
  transient do
645
722
  posts_count { 5 }
646
723
  end
@@ -651,71 +728,122 @@ FactoryBot.define do
651
728
  # to create and we make sure the user is associated properly to the post
652
729
  after(:create) do |user, evaluator|
653
730
  create_list(:post, evaluator.posts_count, user: user)
731
+
732
+ # You may need to reload the record here, depending on your application
733
+ user.reload
654
734
  end
655
735
  end
656
736
  end
657
737
  end
738
+
739
+ create(:user).posts.length # 0
740
+ create(:user_with_posts).posts.length # 5
741
+ create(:user_with_posts, posts_count: 15).posts.length # 15
658
742
  ```
659
743
 
660
- This allows us to do:
744
+ Or, for a solution that works with `build`, `build_stubbed`, and `create`
745
+ (although it doesn't work well with `attributes_for`), you can use inline
746
+ associations:
661
747
 
662
748
  ```ruby
749
+ FactoryBot.define do
750
+ factory :post do
751
+ title { "Through the Looking Glass" }
752
+ user
753
+ end
754
+
755
+ factory :user do
756
+ name { "Taylor Kim" }
757
+
758
+ factory :user_with_posts do
759
+ posts { [association(:post)] }
760
+ end
761
+ end
762
+ end
763
+
663
764
  create(:user).posts.length # 0
765
+ create(:user_with_posts).posts.length # 1
766
+ build(:user_with_posts).posts.length # 1
767
+ build_stubbed(:user_with_posts).posts.length # 1
768
+ ```
769
+
770
+ For more flexibility you can combine this with the `posts_count` transient
771
+ attribute from the callback example:
772
+
773
+ ```ruby
774
+ FactoryBot.define do
775
+ factory :post do
776
+ title { "Through the Looking Glass" }
777
+ user
778
+ end
779
+
780
+ factory :user do
781
+ name { "Adiza Kumato" }
782
+
783
+ factory :user_with_posts do
784
+ transient do
785
+ posts_count { 5 }
786
+ end
787
+
788
+ posts do
789
+ Array.new(posts_count) { association(:post) }
790
+ end
791
+ end
792
+ end
793
+ end
794
+
664
795
  create(:user_with_posts).posts.length # 5
665
796
  create(:user_with_posts, posts_count: 15).posts.length # 15
797
+ build(:user_with_posts, posts_count: 15).posts.length # 15
798
+ build_stubbed(:user_with_posts, posts_count: 15).posts.length # 15
666
799
  ```
667
800
 
668
801
  ### `has_and_belongs_to_many` associations
669
802
 
670
803
  Generating data for a `has_and_belongs_to_many` relationship is very similar
671
- to the above `has_many` relationship, with a small change, you need to pass an
804
+ to the above `has_many` relationship, with a small change: you need to pass an
672
805
  array of objects to the model's pluralized attribute name rather than a single
673
806
  object to the singular version of the attribute name.
674
807
 
675
- Here's an example with two models that are related via
676
- `has_and_belongs_to_many`:
677
808
 
678
809
  ```ruby
679
- FactoryBot.define do
680
-
681
- # language factory with a `belongs_to` association for the profile
682
- factory :language do
683
- title { "Through the Looking Glass" }
684
- profile
810
+ def profile_with_languages(languages_count: 2)
811
+ FactoryBot.create(:profile) do |profile|
812
+ FactoryBot.create_list(:language, languages_count, profiles: [profile])
685
813
  end
814
+ end
815
+ ```
686
816
 
687
- # profile factory without associated languages
688
- factory :profile do
689
- name { "John Doe" }
817
+ Or with the callback approach:
690
818
 
691
- # profile_with_languages will create language data after the profile has
692
- # been created
693
- factory :profile_with_languages do
694
- # languages_count is declared as an ignored attribute and available in
695
- # attributes on the factory, as well as the callback via the evaluator
696
- transient do
697
- languages_count { 5 }
698
- end
819
+ ```ruby
820
+ factory :profile_with_languages do
821
+ transient do
822
+ languages_count { 2 }
823
+ end
699
824
 
700
- # the after(:create) yields two values; the profile instance itself and
701
- # the evaluator, which stores all values from the factory, including
702
- # ignored attributes; `create_list`'s second argument is the number of
703
- # records to create and we make sure the profile is associated properly
704
- # to the language
705
- after(:create) do |profile, evaluator|
706
- create_list(:language, evaluator.languages_count, profiles: [profile])
707
- end
708
- end
825
+ after(:create) do |profile, evaluator|
826
+ create_list(:language, evaluator.languages_count, profiles: [profile])
827
+ profile.reload
709
828
  end
710
829
  end
711
830
  ```
712
831
 
713
- This allows us to do:
832
+ Or the inline association approach (note the use of the `instance` method here
833
+ to refer to the profile being built):
714
834
 
715
835
  ```ruby
716
- create(:profile).languages.length # 0
717
- create(:profile_with_languages).languages.length # 5
718
- create(:profile_with_languages, languages_count: 15).languages.length # 15
836
+ factory :profile_with_languages do
837
+ transient do
838
+ languages_count { 2 }
839
+ end
840
+
841
+ languages do
842
+ Array.new(languages_count) do
843
+ association(:language, profiles: [instance])
844
+ end
845
+ end
846
+ end
719
847
  ```
720
848
 
721
849
  ### Polymorphic associations
@@ -749,6 +877,61 @@ create(:comment, :for_video)
749
877
  create(:comment, :for_photo)
750
878
  ```
751
879
 
880
+ ### Interconnected associations
881
+
882
+ There are limitless ways objects might be interconnected, and
883
+ factory\_bot may not always be suited to handle those relationships. In some
884
+ cases it makes sense to use factory\_bot to build each individual object, and
885
+ then to write helper methods in plain Ruby to tie those objects together.
886
+
887
+ That said, some more complex, interconnected relationships can be built in factory\_bot
888
+ using inline associations with reference to the `instance` being built.
889
+
890
+ Let's say your models look like this, where an associated `Student` and
891
+ `Profile` should both belong to the same `School`:
892
+
893
+ ```ruby
894
+ class Student < ApplicationRecord
895
+ belongs_to :school
896
+ has_one :profile
897
+ end
898
+
899
+ class Profile < ApplicationRecord
900
+ belongs_to :school
901
+ belongs_to :student
902
+ end
903
+
904
+ class School < ApplicationRecord
905
+ has_many :students
906
+ has_many :profiles
907
+ end
908
+ ```
909
+
910
+ We can ensure the student and profile are connected to each other and to the
911
+ same school with a factory like this:
912
+
913
+ ```ruby
914
+ FactoryBot.define do
915
+ factory :student do
916
+ school
917
+ profile { association :profile, student: instance, school: school }
918
+ end
919
+
920
+ factory :profile do
921
+ school
922
+ student { association :student, profile: instance, school: school }
923
+ end
924
+
925
+ factory :school
926
+ end
927
+ ```
928
+
929
+ Note that this approach works with `build`, `build_stubbed`, and `create`, but
930
+ the associations will return `nil` when using `attributes_for`.
931
+
932
+ Also, note that if you assign any attributes inside a custom `initialize_with`
933
+ (e.g. `initialize_with { new(**attributes) }`), those attributes should not refer to `instance`,
934
+ since it will be `nil`.
752
935
 
753
936
  Sequences
754
937
  ---------
@@ -811,7 +994,7 @@ end
811
994
 
812
995
  ### Initial value
813
996
 
814
- You can override the initial value. Any value that response to the `#next`
997
+ You can override the initial value. Any value that responds to the `#next`
815
998
  method will work (e.g. 1, 2, 3, 'a', 'b', 'c')
816
999
 
817
1000
  ```ruby
@@ -830,6 +1013,15 @@ factory :post do
830
1013
  end
831
1014
  ```
832
1015
 
1016
+ Please note, that the value for the sequence could be any Enumerable instance,
1017
+ as long as it responds to `#next`:
1018
+
1019
+ ```ruby
1020
+ factory :task do
1021
+ sequence :priority, %i[low medium high urgent].cycle
1022
+ end
1023
+ ```
1024
+
833
1025
  ### Aliases
834
1026
 
835
1027
  Sequences can also have aliases. The sequence aliases share the same counter:
@@ -960,16 +1152,16 @@ factory :user do
960
1152
  name { "Friendly User" }
961
1153
  login { name }
962
1154
 
963
- trait :male do
1155
+ trait :active do
964
1156
  name { "John Doe" }
965
- gender { "Male" }
966
- login { "#{name} (M)" }
1157
+ status { :active }
1158
+ login { "#{name} (active)" }
967
1159
  end
968
1160
 
969
- trait :female do
1161
+ trait :inactive do
970
1162
  name { "Jane Doe" }
971
- gender { "Female" }
972
- login { "#{name} (F)" }
1163
+ status { :inactive }
1164
+ login { "#{name} (inactive)" }
973
1165
  end
974
1166
 
975
1167
  trait :admin do
@@ -977,8 +1169,8 @@ factory :user do
977
1169
  login { "admin-#{name}" }
978
1170
  end
979
1171
 
980
- factory :male_admin, traits: [:male, :admin] # login will be "admin-John Doe"
981
- factory :female_admin, traits: [:admin, :female] # login will be "Jane Doe (F)"
1172
+ factory :active_admin, traits: [:active, :admin] # login will be "admin-John Doe"
1173
+ factory :inactive_admin, traits: [:admin, :inactive] # login will be "Jane Doe (inactive)"
982
1174
  end
983
1175
  ```
984
1176
 
@@ -991,19 +1183,41 @@ factory :user do
991
1183
  name { "Friendly User" }
992
1184
  login { name }
993
1185
 
994
- trait :male do
1186
+ trait :active do
995
1187
  name { "John Doe" }
996
- gender { "Male" }
1188
+ status { :active }
997
1189
  login { "#{name} (M)" }
998
1190
  end
999
1191
 
1000
1192
  factory :brandon do
1001
- male
1193
+ active
1002
1194
  name { "Brandon" }
1003
1195
  end
1004
1196
  end
1005
1197
  ```
1006
1198
 
1199
+ ### As mixins
1200
+
1201
+ Traits can be defined outside of factories and used as mixins to compose shared attributes
1202
+
1203
+ ```ruby
1204
+ FactoryBot.define do
1205
+ trait :timestamps do
1206
+ created_at { 8.days.ago }
1207
+ updated_at { 4.days.ago }
1208
+ end
1209
+
1210
+ factory :user, traits: [:timestamps] do
1211
+ username { "john_doe" }
1212
+ end
1213
+
1214
+ factory :post do
1215
+ timestamps
1216
+ title { "Traits rock" }
1217
+ end
1218
+ end
1219
+ ```
1220
+
1007
1221
  ### Using traits
1008
1222
 
1009
1223
  Traits can also be passed in as a list of symbols when you construct an instance
@@ -1013,9 +1227,9 @@ from factory\_bot.
1013
1227
  factory :user do
1014
1228
  name { "Friendly User" }
1015
1229
 
1016
- trait :male do
1230
+ trait :active do
1017
1231
  name { "John Doe" }
1018
- gender { "Male" }
1232
+ status { :active }
1019
1233
  end
1020
1234
 
1021
1235
  trait :admin do
@@ -1023,8 +1237,8 @@ factory :user do
1023
1237
  end
1024
1238
  end
1025
1239
 
1026
- # creates an admin user with gender "Male" and name "Jon Snow"
1027
- create(:user, :admin, :male, name: "Jon Snow")
1240
+ # creates an admin user with :active status and name "Jon Snow"
1241
+ create(:user, :admin, :active, name: "Jon Snow")
1028
1242
  ```
1029
1243
 
1030
1244
  This ability works with `build`, `build_stubbed`, `attributes_for`, and `create`.
@@ -1042,8 +1256,8 @@ factory :user do
1042
1256
  end
1043
1257
  end
1044
1258
 
1045
- # creates 3 admin users with gender "Male" and name "Jon Snow"
1046
- create_list(:user, 3, :admin, :male, name: "Jon Snow")
1259
+ # creates 3 admin users with :active status and name "Jon Snow"
1260
+ create_list(:user, 3, :admin, :active, name: "Jon Snow")
1047
1261
  ```
1048
1262
 
1049
1263
  ### With associations
@@ -1342,7 +1556,6 @@ FactoryBot.define do
1342
1556
  factory :application_user, parent: :user do
1343
1557
  full_name { "Jane Doe" }
1344
1558
  date_of_birth { 21.years.ago }
1345
- gender { "Female" }
1346
1559
  health { 90 }
1347
1560
  end
1348
1561
  end
@@ -1355,7 +1568,6 @@ FactoryBot.modify do
1355
1568
  factory :user do
1356
1569
  full_name { "Jane Doe" }
1357
1570
  date_of_birth { 21.years.ago }
1358
- gender { "Female" }
1359
1571
  health { 90 }
1360
1572
  end
1361
1573
  end
@@ -1393,6 +1605,15 @@ twenty_somethings = build_list(:user, 10) do |user, i|
1393
1605
  end
1394
1606
  ```
1395
1607
 
1608
+ `create_list` passes saved instances into the block. If you modify the instance, you must save it again:
1609
+
1610
+ ```ruby
1611
+ twenty_somethings = create_list(:user, 10) do |user, i|
1612
+ user.date_of_birth = (20 + i).years.ago
1613
+ user.save!
1614
+ end
1615
+ ```
1616
+
1396
1617
  `build_stubbed_list` will give you fully stubbed out instances:
1397
1618
 
1398
1619
  ```ruby
@@ -1567,7 +1788,7 @@ factory :user do
1567
1788
 
1568
1789
  name "John Doe"
1569
1790
 
1570
- initialize_with { new(attributes) }
1791
+ initialize_with { new(**attributes) }
1571
1792
  end
1572
1793
  ```
1573
1794
 
data/NEWS.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # News
2
2
 
3
+ ## 6.2.1 (March 8, 2022)
4
+ * Added: CI testing against truffleruby
5
+ * Changed: Documentation improvements for sequences and traits
6
+ * Fixed: ActiveSupport::Notifications reporting strategy through associations now report as symbols
7
+ * Fixed: `add_attribute` with reserved keywords assigns values correctly
8
+
9
+ ## 6.2.0 (May 7, 2021)
10
+ * Added: support for Ruby 3.0
11
+ * Changed: Include factory or trait name in error messages for missing traits. d05a9a3c
12
+ * Changed: Switched from Travis CI to GitHub Actions
13
+ * Fixed: More Ruby 2.7 kwarg deprecation warnings
14
+
3
15
  ## 6.1.0 (July 8, 2020)
4
16
  * Added: public reader for the evaluation instance, helpful for building interrelated associations
5
17
  * Changed: raise a more helpful error when passing an invalid argument to an association
@@ -20,6 +32,7 @@
20
32
  * Added: `build_stubbed_starting_id=` option to define the starting id for `build_stubbed`
21
33
  * Removed: deprecated methods on the top-level `FactoryBot` module meant only for internal use
22
34
  * Removed: support for EOL versions of Ruby (2.3, 2.4) and Rails (4.2)
35
+ * Removed: support for "abstract" factories with no associated class; use traits instead.
23
36
 
24
37
  ## 5.2.0 (April 24, 2020)
25
38
  * Added: Pass index to block for `*_list` methods
data/README.md CHANGED
@@ -43,7 +43,7 @@ gem install factory_bot
43
43
  Supported Ruby versions
44
44
  -----------------------
45
45
 
46
- Supported Ruby versions are listed in [`.travis.yml`](https://github.com/thoughtbot/factory_bot/blob/master/.travis.yml)
46
+ Supported Ruby versions are listed in [`.github/workflows/build.yml`](https://github.com/thoughtbot/factory_bot/blob/master/.github/workflows/build.yml)
47
47
 
48
48
  More Information
49
49
  ----------------
@@ -94,8 +94,8 @@ See [our other projects][community] or
94
94
 
95
95
  [community]: https://thoughtbot.com/community?utm_source=github
96
96
  [hire]: https://thoughtbot.com/hire-us?utm_source=github
97
- [ci-image]: https://travis-ci.org/thoughtbot/factory_bot.svg
98
- [ci]: https://travis-ci.org/thoughtbot/factory_bot?branch=master
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
99
  [grade-image]: https://codeclimate.com/github/thoughtbot/factory_bot/badges/gpa.svg
100
100
  [grade]: https://codeclimate.com/github/thoughtbot/factory_bot
101
101
  [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,7 +12,7 @@ module FactoryBot
12
12
 
13
13
  -> {
14
14
  value = case block.arity
15
- when 1, -1 then instance_exec(self, &block)
15
+ when 1, -1, -2 then instance_exec(self, &block)
16
16
  else instance_exec(&block)
17
17
  end
18
18
  raise SequenceAbuseError if FactoryBot::Sequence === value
@@ -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
 
@@ -9,7 +9,7 @@ module FactoryBot
9
9
 
10
10
  def run(instance, evaluator)
11
11
  case block.arity
12
- when 1, -1 then syntax_runner.instance_exec(instance, &block)
12
+ when 1, -1, -2 then syntax_runner.instance_exec(instance, &block)
13
13
  when 2 then syntax_runner.instance_exec(instance, evaluator, &block)
14
14
  else syntax_runner.instance_exec(&block)
15
15
  end
@@ -6,17 +6,11 @@ module FactoryBot
6
6
  @invoked_methods = []
7
7
  end
8
8
 
9
- if ::Gem::Version.new(::RUBY_VERSION) >= ::Gem::Version.new("2.7")
10
- def method_missing(name, *args, **kwargs, &block) # rubocop:disable Style/MissingRespondToMissing
11
- @invoked_methods << name
12
- super
13
- end
14
- else
15
- def method_missing(name, *args, &block) # rubocop:disable Style/MissingRespondToMissing
16
- @invoked_methods << name
17
- super
18
- end
9
+ def method_missing(name, *args, &block) # rubocop:disable Style/MissingRespondToMissing
10
+ @invoked_methods << name
11
+ super
19
12
  end
13
+ ruby2_keywords :method_missing if respond_to?(:ruby2_keywords, true)
20
14
 
21
15
  def __invoked_methods__
22
16
  @invoked_methods.uniq
@@ -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
 
@@ -30,7 +30,7 @@ module FactoryBot
30
30
  end
31
31
 
32
32
  def to_create(&block)
33
- if block_given?
33
+ if block
34
34
  @to_create = block
35
35
  else
36
36
  aggregate_from_traits_and_self(:to_create) { @to_create }.last
@@ -111,6 +111,20 @@ module FactoryBot
111
111
 
112
112
  def base_traits
113
113
  @base_traits.map { |name| trait_by_name(name) }
114
+ rescue KeyError => error
115
+ raise error_with_definition_name(error)
116
+ end
117
+
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
+ )
124
+
125
+ error.class.new(message).tap do |new_error|
126
+ new_error.set_backtrace(error.backtrace)
127
+ end
114
128
  end
115
129
 
116
130
  def additional_traits
@@ -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?
@@ -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,23 +35,14 @@ module FactoryBot
35
35
 
36
36
  attr_accessor :instance
37
37
 
38
- if ::Gem::Version.new(::RUBY_VERSION) >= ::Gem::Version.new("2.7")
39
- def method_missing(method_name, *args, **kwargs, &block) # rubocop:disable Style/MethodMissingSuper, Style/MissingRespondToMissing
40
- if @instance.respond_to?(method_name)
41
- @instance.send(method_name, *args, **kwargs, &block)
42
- else
43
- SyntaxRunner.new.send(method_name, *args, **kwargs, &block)
44
- end
45
- end
46
- else
47
- def method_missing(method_name, *args, &block) # rubocop:disable Style/MethodMissingSuper, Style/MissingRespondToMissing
48
- if @instance.respond_to?(method_name)
49
- @instance.send(method_name, *args, &block)
50
- else
51
- SyntaxRunner.new.send(method_name, *args, &block)
52
- end
38
+ def method_missing(method_name, *args, &block)
39
+ if @instance.respond_to?(method_name)
40
+ @instance.send(method_name, *args, &block)
41
+ else
42
+ SyntaxRunner.new.send(method_name, *args, &block)
53
43
  end
54
44
  end
45
+ ruby2_keywords :method_missing if respond_to?(:ruby2_keywords, true)
55
46
 
56
47
  def respond_to_missing?(method_name, _include_private = false)
57
48
  @instance.respond_to?(method_name) || SyntaxRunner.new.respond_to?(method_name)
@@ -25,7 +25,7 @@ module FactoryBot
25
25
  raise key_error_with_custom_message(e)
26
26
  end
27
27
 
28
- alias [] find
28
+ alias_method :[], :find
29
29
 
30
30
  def register(name, item)
31
31
  @items[name] = item
@@ -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,6 +41,10 @@ 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
50
  def next_id
@@ -15,7 +15,7 @@ module FactoryBot
15
15
  def factory(name, options = {}, &block)
16
16
  factory = Factory.new(name, options)
17
17
  proxy = FactoryBot::DefinitionProxy.new(factory.definition)
18
- proxy.instance_eval(&block) if block_given?
18
+ proxy.instance_eval(&block) if block
19
19
 
20
20
  Internal.register_factory(factory)
21
21
 
@@ -9,7 +9,7 @@ module FactoryBot
9
9
  @definition = Definition.new(@name)
10
10
  proxy = FactoryBot::DefinitionProxy.new(@definition)
11
11
 
12
- if block_given?
12
+ if block
13
13
  proxy.instance_eval(&@block)
14
14
  end
15
15
  end
@@ -1,3 +1,3 @@
1
1
  module FactoryBot
2
- VERSION = "6.1.0".freeze
2
+ VERSION = "6.2.1".freeze
3
3
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: factory_bot
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.1.0
4
+ version: 6.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josh Clayton
8
8
  - Joe Ferris
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2020-07-08 00:00:00.000000000 Z
12
+ date: 2022-03-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -237,7 +237,7 @@ homepage: https://github.com/thoughtbot/factory_bot
237
237
  licenses:
238
238
  - MIT
239
239
  metadata: {}
240
- post_install_message:
240
+ post_install_message:
241
241
  rdoc_options: []
242
242
  require_paths:
243
243
  - lib
@@ -252,8 +252,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
252
252
  - !ruby/object:Gem::Version
253
253
  version: '0'
254
254
  requirements: []
255
- rubygems_version: 3.1.2
256
- signing_key:
255
+ rubygems_version: 3.1.6
256
+ signing_key:
257
257
  specification_version: 4
258
258
  summary: factory_bot provides a framework and DSL for defining and using model instance
259
259
  factories.