factory_bot 4.11.1 → 5.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/GETTING_STARTED.md +105 -29
  3. data/NEWS +17 -0
  4. data/README.md +3 -14
  5. data/lib/factory_bot.rb +56 -56
  6. data/lib/factory_bot/aliases.rb +1 -1
  7. data/lib/factory_bot/attribute.rb +4 -39
  8. data/lib/factory_bot/attribute_assigner.rb +20 -5
  9. data/lib/factory_bot/attribute_list.rb +2 -1
  10. data/lib/factory_bot/callback.rb +1 -0
  11. data/lib/factory_bot/configuration.rb +6 -18
  12. data/lib/factory_bot/declaration.rb +4 -4
  13. data/lib/factory_bot/declaration/association.rb +3 -1
  14. data/lib/factory_bot/declaration/dynamic.rb +3 -1
  15. data/lib/factory_bot/declaration/implicit.rb +3 -1
  16. data/lib/factory_bot/declaration_list.rb +1 -1
  17. data/lib/factory_bot/decorator.rb +5 -1
  18. data/lib/factory_bot/decorator/attribute_hash.rb +1 -1
  19. data/lib/factory_bot/decorator/invocation_tracker.rb +1 -1
  20. data/lib/factory_bot/definition.rb +4 -3
  21. data/lib/factory_bot/definition_proxy.rb +53 -62
  22. data/lib/factory_bot/errors.rb +4 -4
  23. data/lib/factory_bot/evaluation.rb +1 -1
  24. data/lib/factory_bot/evaluator.rb +4 -4
  25. data/lib/factory_bot/factory.rb +7 -7
  26. data/lib/factory_bot/factory_runner.rb +3 -3
  27. data/lib/factory_bot/find_definitions.rb +1 -1
  28. data/lib/factory_bot/linter.rb +35 -18
  29. data/lib/factory_bot/null_factory.rb +3 -0
  30. data/lib/factory_bot/null_object.rb +2 -2
  31. data/lib/factory_bot/registry.rb +15 -6
  32. data/lib/factory_bot/sequence.rb +0 -1
  33. data/lib/factory_bot/strategy/null.rb +2 -4
  34. data/lib/factory_bot/strategy/stub.rb +23 -29
  35. data/lib/factory_bot/strategy_syntax_method_registrar.rb +2 -2
  36. data/lib/factory_bot/syntax.rb +2 -2
  37. data/lib/factory_bot/syntax/default.rb +1 -1
  38. data/lib/factory_bot/trait.rb +2 -1
  39. data/lib/factory_bot/version.rb +1 -1
  40. metadata +68 -29
  41. data/lib/factory_bot/attribute/static.rb +0 -16
  42. data/lib/factory_bot/declaration/static.rb +0 -26
  43. data/lib/factory_bot/decorator/class_key_hash.rb +0 -28
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 14d67d2d0498cdfe3d47717279561f299566ecd20084af6958e3c5143188ccae
4
- data.tar.gz: bb6daffb31d969293032bbb2d655c3628095bdd285708fdc93fe2a60e4cd072e
3
+ metadata.gz: c22373774f12578e26bfcb3885c5cb3e03651230880b1d7817458c8b09637581
4
+ data.tar.gz: f75b530fbfce32a94367db37ecfe55a2b5c568f95d0b24e9a55d9d6b63e4fbcc
5
5
  SHA512:
6
- metadata.gz: 24178c541ce3b726ad7274febd2bbf69ccaff9446a15a79b9bfce5525b0e2f63cc4af50a48950abe5b8b80397151bf86c31263463b0d7309093c870cb925c97d
7
- data.tar.gz: 630e120e664a503de162d11d9dc36f83a7fc5602a8935875cacfb905b28c3cf1c8f0978137281b5aa8d2fed3fa40c236dd567cb7544bca44cb85e1f43fb2ac83
6
+ metadata.gz: '08c78ce623a22e0b9b7da186fdc66acc24e267ecda60ff79940ff41756d1065ef30fa52fc5e5f58d619137db876b3f8cd611f211d919f50724839272ad0e449d'
7
+ data.tar.gz: fff4a17d150ccdd07ed4c6efacfd51dc6c64cd07e563f042b864983b2569215f431ed67481e8907c4b48ba190d64369432c0259f3b6d860fbd4b588c97ec645b
data/GETTING_STARTED.md CHANGED
@@ -4,16 +4,16 @@ Getting Started
4
4
  Update Your Gemfile
5
5
  -------------------
6
6
 
7
- If you're using Rails, you'll need to change the required version of `factory_bot_rails`:
7
+ If you're using Rails:
8
8
 
9
9
  ```ruby
10
- gem "factory_bot_rails", "~> 4.0"
10
+ gem "factory_bot_rails"
11
11
  ```
12
12
 
13
- If you're *not* using Rails, you'll just have to change the required version of `factory_bot`:
13
+ If you're *not* using Rails:
14
14
 
15
15
  ```ruby
16
- gem "factory_bot", "~> 4.0"
16
+ gem "factory_bot"
17
17
  ```
18
18
 
19
19
  JRuby users: factory_bot works with JRuby starting with 1.6.7.2 (latest stable, as per July 2012).
@@ -102,7 +102,7 @@ If you do not include `FactoryBot::Syntax::Methods` in your test suite, then all
102
102
  Defining factories
103
103
  ------------------
104
104
 
105
- Each factory has a name and a set of attributes. The name is used to guess the class of the object by default, but it's possible to explicitly specify it:
105
+ Each factory has a name and a set of attributes. The name is used to guess the class of the object by default:
106
106
 
107
107
  ```ruby
108
108
  # This will guess the User class
@@ -112,16 +112,26 @@ FactoryBot.define do
112
112
  last_name { "Doe" }
113
113
  admin { false }
114
114
  end
115
-
116
- # This will use the User class (Admin would have been guessed)
117
- factory :admin, class: User do
118
- first_name { "Admin" }
119
- last_name { "User" }
120
- admin { true }
121
- end
122
115
  end
123
116
  ```
124
117
 
118
+ It is also possible to explicitly specify the class:
119
+
120
+ ```ruby
121
+ # This will use the User class (otherwise Admin would have been guessed)
122
+ factory :admin, class: User
123
+ ```
124
+
125
+ If the constant is not available
126
+ (if you are using a Rails engine that waits to load models, for example),
127
+ you can also pass a symbol or string,
128
+ which factory_bot will constantize later, once you start building objects:
129
+
130
+ ```ruby
131
+ # It's OK if Doorkeeper::AccessToken isn't loaded yet
132
+ factory :access_token, class: "Doorkeeper::AccessToken"
133
+ ```
134
+
125
135
  Because of the block syntax in Ruby, defining attributes as `Hash`es (for
126
136
  serialized/JSON columns, for example) requires two sets of curly brackets:
127
137
 
@@ -177,21 +187,15 @@ user.first_name
177
187
  # => "Joe"
178
188
  ```
179
189
 
190
+ Note that objects created with `build_stubbed` cannot be serialized with
191
+ `Marshal.dump`, since factory_bot defines singleton methods on these objects.
192
+
180
193
  Static Attributes
181
194
  ------------------
182
195
 
183
- Static attributes, without a block, are deprecated and will be removed in
184
- factory\_bot 5.
185
-
186
- ```ruby
187
- factory :user do
188
- # Do not use deprecated static attributes
189
- admin true
190
-
191
- # Use dynamic attributes instead
192
- admin { true }
193
- end
194
- ```
196
+ Static attributes (without a block) are no longer available in factory\_bot 5.
197
+ You can read more about the decision to remove them in
198
+ [this blog post](https://robots.thoughtbot.com/deprecating-static-attributes-in-factory_bot-4-11).
195
199
 
196
200
  Aliases
197
201
  -------
@@ -261,8 +265,8 @@ create(:user, upcased: true).name
261
265
  #=> "JOHN DOE - ROCKSTAR"
262
266
  ```
263
267
 
264
- Static and dynamic attributes can be created as transient attributes. Transient
265
- attributes will be ignored within attributes\_for and won't be set on the model,
268
+ Transient attributes will be ignored within attributes\_for and won't be
269
+ set on the model,
266
270
  even if the attribute exists or you attempt to override it.
267
271
 
268
272
  Within factory_bot's dynamic attributes, you can access transient attributes as
@@ -273,7 +277,7 @@ transient attributes from there.
273
277
  Method Name / Reserved Word Attributes
274
278
  -------------------------------
275
279
 
276
- If your attributes conflict with existing methods or reserved words you can define them with `add_attribute`.
280
+ 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`.
277
281
 
278
282
  ```ruby
279
283
  factory :dna do
@@ -343,9 +347,35 @@ factory :post do
343
347
  end
344
348
  ```
345
349
 
346
- The behavior of the association method varies depending on the build strategy used for the parent object.
350
+ In factory\_bot 5, associations default to using the same build strategy as
351
+ their parent object:
347
352
 
348
353
  ```ruby
354
+ FactoryBot.define do
355
+ factory :author
356
+
357
+ factory :post do
358
+ author
359
+ end
360
+ end
361
+
362
+ post = build(:post)
363
+ post.new_record? # => true
364
+ post.author.new_record? # => true
365
+
366
+ post = create(:post)
367
+ post.new_record? # => false
368
+ post.author.new_record? # => false
369
+ ```
370
+
371
+ This is different than the default behavior for previous versions of
372
+ factory\_bot, where the association strategy would not always match the strategy
373
+ of the parent object. If you want to continue using the old behavior, you can
374
+ set the `use_parent_strategy` configuration option to `false`.
375
+
376
+ ```ruby
377
+ FactoryBot.use_parent_strategy = false
378
+
349
379
  # Builds and saves a User and a Post
350
380
  post = create(:post)
351
381
  post.new_record? # => false
@@ -360,6 +390,8 @@ post.author.new_record? # => false
360
390
  To not save the associated object, specify strategy: :build in the factory:
361
391
 
362
392
  ```ruby
393
+ FactoryBot.use_parent_strategy = false
394
+
363
395
  factory :post do
364
396
  # ...
365
397
  association :author, factory: :user, strategy: :build
@@ -476,6 +508,36 @@ create(:profile_with_languages).languages.length # 5
476
508
  create(:profile_with_languages, languages_count: 15).languages.length # 15
477
509
  ```
478
510
 
511
+ Polymorphic associations can be handled with traits:
512
+
513
+ ```
514
+ FactoryBot.define do
515
+ factory :video
516
+ factory :photo
517
+
518
+ factory :comment do
519
+ for_photo
520
+
521
+ trait :for_video do
522
+ association(:commentable, factory: :video)
523
+ end
524
+
525
+ trait :for_photo do
526
+ association(:commentable, factory: :photo)
527
+ end
528
+ end
529
+ end
530
+ ```
531
+
532
+ This allows us to do:
533
+
534
+ ```
535
+ create(:comment)
536
+ create(:comment, :for_video)
537
+ create(:comment, :for_photo)
538
+ ```
539
+
540
+
479
541
  Sequences
480
542
  ---------
481
543
 
@@ -515,6 +577,9 @@ factory :user do
515
577
  end
516
578
  ```
517
579
 
580
+ Note that defining sequences as implicit attributes will not work if you have a
581
+ factory with the same name as the sequence.
582
+
518
583
  And it's also possible to define an in-line sequence that is only used in
519
584
  a particular factory:
520
585
 
@@ -623,7 +688,7 @@ factory :story do
623
688
  end
624
689
  ```
625
690
 
626
- Traits can be used as attributes:
691
+ Traits can be used as implicit attributes:
627
692
 
628
693
  ```ruby
629
694
  factory :week_long_published_story_with_title, parent: :story do
@@ -633,6 +698,9 @@ factory :week_long_published_story_with_title, parent: :story do
633
698
  end
634
699
  ```
635
700
 
701
+ Note that defining traits as implicit attributes will not work if you have a
702
+ factory or sequence with the same name as the trait.
703
+
636
704
  Traits that define the same attributes won't raise AttributeDefinitionErrors;
637
705
  the trait that defines the attribute latest gets precedence.
638
706
 
@@ -999,6 +1067,7 @@ namespace :factory_bot do
999
1067
  desc "Verify that all FactoryBot factories are valid"
1000
1068
  task lint: :environment do
1001
1069
  if Rails.env.test?
1070
+ DatabaseCleaner.clean_with(:deletion)
1002
1071
  DatabaseCleaner.cleaning do
1003
1072
  FactoryBot.lint
1004
1073
  end
@@ -1047,6 +1116,13 @@ You can also specify the strategy used for linting:
1047
1116
  FactoryBot.lint strategy: :build
1048
1117
  ```
1049
1118
 
1119
+ Verbose linting will include full backtraces for each error, which can be
1120
+ helpful for debugging:
1121
+
1122
+ ```ruby
1123
+ FactoryBot.lint verbose: :true
1124
+ ```
1125
+
1050
1126
  Custom Construction
1051
1127
  -------------------
1052
1128
 
data/NEWS CHANGED
@@ -1,3 +1,20 @@
1
+ 5.0.0
2
+ Added: Verbose option to include full backtraces in the linting output
3
+ Changed: use_parent_strategy now defaults to true, so by default the
4
+ build strategy will build, rather than create associations
5
+ Changed: Passing a block when defining associations now raises an error
6
+ Bugfix: use_parent_strategy is no longer reset by FactoryBot.reload
7
+ Bugfix: rewind_sequences will now rewind local sequences along with the global ones
8
+ Bugfix: the build_stubbed strategy now sets timestamps without changing the
9
+ the original behavior of the timestamp methods
10
+ Bugfix: avoid a stack error when referring to an "attributes" attribute in initialize_with
11
+ Removed: support for EOL versions of Ruby and Rails
12
+ Removed: static attributes (use dynamic attributes with a block instead)
13
+ Removed: looking up factories by class
14
+ Removed: ignore method (use transient instead)
15
+ Removed: duplicate_attribute_assignment_from_initialize_with configuration option
16
+ Deprecated: allow_class_lookup configuration option
17
+
1
18
  4.11.1 (September 7, 2018)
2
19
  Documentation: Include .yardopts in the gem to fix broken RubyDoc links
3
20
 
data/README.md CHANGED
@@ -21,7 +21,7 @@ You should find the documentation for your version of factory_bot on [Rubygems](
21
21
  See [GETTING_STARTED] for information on defining and using factories. We also
22
22
  have [a detailed introductory video][], available for free on Upcase.
23
23
 
24
- [a detailed introductory video]: https://upcase.com/videos/factory-girl?utm_source=github&utm_medium=open-source&utm_campaign=factory-girl
24
+ [a detailed introductory video]: https://upcase.com/videos/factory-bot?utm_source=github&utm_medium=open-source&utm_campaign=factory-girl
25
25
 
26
26
  Install
27
27
  --------
@@ -40,22 +40,11 @@ To install the gem manually from your shell, run:
40
40
  gem install factory_bot
41
41
  ```
42
42
 
43
- **Caveat:** As of ActiveSupport 5.0 and above, Ruby 2.2.2+ is required. Because
44
- of Rubygems' dependency resolution when installing gems, you may see an error
45
- similar to:
46
-
47
- ```
48
- $ gem install factory_bot
49
- ERROR: Error installing factory_bot:
50
- activesupport requires Ruby version >= 2.2.2.
51
- ```
52
-
53
- To bypass this, install a pre-5.0 version of ActiveSupport before installing
54
- manually.
55
-
56
43
  Supported Ruby versions
57
44
  -----------------------
58
45
 
46
+ The factory_bot 5.x series supports MRI Ruby 2.3+.
47
+
59
48
  The factory_bot 3.x+ series supports MRI Ruby 1.9. Additionally, factory_bot
60
49
  3.6+ supports JRuby 1.6.7.2+ while running in 1.9 mode. See [GETTING_STARTED]
61
50
  for more information on configuring the JRuby environment.
data/lib/factory_bot.rb CHANGED
@@ -1,52 +1,54 @@
1
- require 'set'
2
- require 'active_support/core_ext/module/delegation'
3
- require 'active_support/deprecation'
4
- require 'active_support/notifications'
5
-
6
- require 'factory_bot/definition_hierarchy'
7
- require 'factory_bot/configuration'
8
- require 'factory_bot/errors'
9
- require 'factory_bot/factory_runner'
10
- require 'factory_bot/strategy_syntax_method_registrar'
11
- require 'factory_bot/strategy_calculator'
12
- require 'factory_bot/strategy/build'
13
- require 'factory_bot/strategy/create'
14
- require 'factory_bot/strategy/attributes_for'
15
- require 'factory_bot/strategy/stub'
16
- require 'factory_bot/strategy/null'
17
- require 'factory_bot/registry'
18
- require 'factory_bot/null_factory'
19
- require 'factory_bot/null_object'
20
- require 'factory_bot/evaluation'
21
- require 'factory_bot/factory'
22
- require 'factory_bot/attribute_assigner'
23
- require 'factory_bot/evaluator'
24
- require 'factory_bot/evaluator_class_definer'
25
- require 'factory_bot/attribute'
26
- require 'factory_bot/callback'
27
- require 'factory_bot/callbacks_observer'
28
- require 'factory_bot/declaration_list'
29
- require 'factory_bot/declaration'
30
- require 'factory_bot/sequence'
31
- require 'factory_bot/attribute_list'
32
- require 'factory_bot/trait'
33
- require 'factory_bot/aliases'
34
- require 'factory_bot/definition'
35
- require 'factory_bot/definition_proxy'
36
- require 'factory_bot/syntax'
37
- require 'factory_bot/syntax_runner'
38
- require 'factory_bot/find_definitions'
39
- require 'factory_bot/reload'
40
- require 'factory_bot/decorator'
41
- require 'factory_bot/decorator/attribute_hash'
42
- require 'factory_bot/decorator/class_key_hash'
43
- require 'factory_bot/decorator/disallows_duplicates_registry'
44
- require 'factory_bot/decorator/invocation_tracker'
45
- require 'factory_bot/decorator/new_constructor'
46
- require 'factory_bot/linter'
47
- require 'factory_bot/version'
1
+ require "set"
2
+ require "active_support/core_ext/module/delegation"
3
+ require "active_support/core_ext/module/attribute_accessors"
4
+ require "active_support/deprecation"
5
+ require "active_support/notifications"
6
+
7
+ require "factory_bot/definition_hierarchy"
8
+ require "factory_bot/configuration"
9
+ require "factory_bot/errors"
10
+ require "factory_bot/factory_runner"
11
+ require "factory_bot/strategy_syntax_method_registrar"
12
+ require "factory_bot/strategy_calculator"
13
+ require "factory_bot/strategy/build"
14
+ require "factory_bot/strategy/create"
15
+ require "factory_bot/strategy/attributes_for"
16
+ require "factory_bot/strategy/stub"
17
+ require "factory_bot/strategy/null"
18
+ require "factory_bot/registry"
19
+ require "factory_bot/null_factory"
20
+ require "factory_bot/null_object"
21
+ require "factory_bot/evaluation"
22
+ require "factory_bot/factory"
23
+ require "factory_bot/attribute_assigner"
24
+ require "factory_bot/evaluator"
25
+ require "factory_bot/evaluator_class_definer"
26
+ require "factory_bot/attribute"
27
+ require "factory_bot/callback"
28
+ require "factory_bot/callbacks_observer"
29
+ require "factory_bot/declaration_list"
30
+ require "factory_bot/declaration"
31
+ require "factory_bot/sequence"
32
+ require "factory_bot/attribute_list"
33
+ require "factory_bot/trait"
34
+ require "factory_bot/aliases"
35
+ require "factory_bot/definition"
36
+ require "factory_bot/definition_proxy"
37
+ require "factory_bot/syntax"
38
+ require "factory_bot/syntax_runner"
39
+ require "factory_bot/find_definitions"
40
+ require "factory_bot/reload"
41
+ require "factory_bot/decorator"
42
+ require "factory_bot/decorator/attribute_hash"
43
+ require "factory_bot/decorator/disallows_duplicates_registry"
44
+ require "factory_bot/decorator/invocation_tracker"
45
+ require "factory_bot/decorator/new_constructor"
46
+ require "factory_bot/linter"
47
+ require "factory_bot/version"
48
48
 
49
49
  module FactoryBot
50
+ DEPRECATOR = ActiveSupport::Deprecation.new("6.0", "factory_bot")
51
+
50
52
  def self.configuration
51
53
  @configuration ||= Configuration.new
52
54
  end
@@ -55,18 +57,19 @@ module FactoryBot
55
57
  @configuration = nil
56
58
  end
57
59
 
60
+ mattr_accessor :use_parent_strategy, instance_accessor: false, default: true
61
+
58
62
  # Look for errors in factories and (optionally) their traits.
59
63
  # Parameters:
60
64
  # factories - which factories to lint; omit for all factories
61
65
  # options:
62
66
  # traits: true - to lint traits as well as factories
63
67
  # strategy: :create - to specify the strategy for linting
68
+ # verbose: true - to include full backtraces for each linting error
64
69
  def self.lint(*args)
65
70
  options = args.extract_options!
66
71
  factories_to_lint = args[0] || FactoryBot.factories
67
- linting_strategy = options[:traits] ? :factory_and_traits : :factory
68
- factory_strategy = options[:strategy] || :create
69
- Linter.new(factories_to_lint, linting_strategy, factory_strategy).lint!
72
+ Linter.new(factories_to_lint, options).lint!
70
73
  end
71
74
 
72
75
  class << self
@@ -80,13 +83,10 @@ module FactoryBot
80
83
  :skip_create,
81
84
  :initialize_with,
82
85
  :constructor,
83
- :duplicate_attribute_assignment_from_initialize_with,
84
- :duplicate_attribute_assignment_from_initialize_with=,
85
- :allow_class_lookup,
86
- :allow_class_lookup=,
87
- :use_parent_strategy,
88
- :use_parent_strategy=,
89
86
  to: :configuration
87
+
88
+ attr_accessor :allow_class_lookup
89
+ deprecate :allow_class_lookup, :allow_class_lookup=, deprecator: DEPRECATOR
90
90
  end
91
91
 
92
92
  def self.register_factory(factory)