factory_bot 5.0.2 → 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 +4 -4
- data/CONTRIBUTING.md +58 -13
- data/GETTING_STARTED.md +745 -149
- data/NEWS.md +53 -0
- data/README.md +19 -18
- data/lib/factory_bot/aliases.rb +4 -4
- data/lib/factory_bot/attribute/association.rb +2 -2
- data/lib/factory_bot/attribute/dynamic.rb +3 -2
- data/lib/factory_bot/attribute_assigner.rb +10 -10
- data/lib/factory_bot/attribute_list.rb +1 -1
- data/lib/factory_bot/callback.rb +3 -11
- data/lib/factory_bot/configuration.rb +6 -6
- data/lib/factory_bot/declaration/association.rb +30 -2
- data/lib/factory_bot/declaration/implicit.rb +4 -1
- data/lib/factory_bot/declaration.rb +1 -1
- data/lib/factory_bot/declaration_list.rb +2 -2
- data/lib/factory_bot/decorator/invocation_tracker.rb +2 -1
- data/lib/factory_bot/decorator.rb +18 -6
- data/lib/factory_bot/definition.rb +66 -19
- data/lib/factory_bot/definition_hierarchy.rb +1 -11
- data/lib/factory_bot/definition_proxy.rb +77 -12
- data/lib/factory_bot/enum.rb +27 -0
- data/lib/factory_bot/errors.rb +3 -0
- data/lib/factory_bot/evaluator.rb +8 -9
- data/lib/factory_bot/evaluator_class_definer.rb +1 -1
- data/lib/factory_bot/factory.rb +13 -13
- data/lib/factory_bot/factory_runner.rb +4 -4
- data/lib/factory_bot/find_definitions.rb +1 -1
- data/lib/factory_bot/internal.rb +68 -1
- data/lib/factory_bot/linter.rb +9 -13
- data/lib/factory_bot/null_factory.rb +10 -4
- data/lib/factory_bot/null_object.rb +2 -6
- data/lib/factory_bot/registry.rb +4 -4
- data/lib/factory_bot/reload.rb +1 -2
- data/lib/factory_bot/sequence.rb +5 -5
- data/lib/factory_bot/strategy/attributes_for.rb +4 -0
- data/lib/factory_bot/strategy/build.rb +4 -0
- data/lib/factory_bot/strategy/create.rb +4 -0
- data/lib/factory_bot/strategy/null.rb +8 -2
- data/lib/factory_bot/strategy/stub.rb +20 -5
- data/lib/factory_bot/strategy_calculator.rb +1 -1
- data/lib/factory_bot/strategy_syntax_method_registrar.rb +12 -1
- data/lib/factory_bot/syntax/default.rb +12 -24
- data/lib/factory_bot/syntax/methods.rb +3 -3
- data/lib/factory_bot/trait.rb +5 -3
- data/lib/factory_bot/version.rb +1 -1
- data/lib/factory_bot.rb +21 -93
- metadata +12 -39
data/NEWS.md
CHANGED
|
@@ -1,5 +1,58 @@
|
|
|
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
|
+
|
|
15
|
+
## 6.1.0 (July 8, 2020)
|
|
16
|
+
* Added: public reader for the evaluation instance, helpful for building interrelated associations
|
|
17
|
+
* Changed: raise a more helpful error when passing an invalid argument to an association
|
|
18
|
+
* Fixed: Ruby 2.7 kwarg deprecation warnings
|
|
19
|
+
|
|
20
|
+
## 6.0.2 (June 19, 2020)
|
|
21
|
+
* Fixed: bug causing traits to consume more memory each time they were used
|
|
22
|
+
|
|
23
|
+
## 6.0.1 (June 19, 2020)
|
|
24
|
+
* Fixed: bug with constant resolution causing unexpected uninitialized constant errors
|
|
25
|
+
|
|
26
|
+
## 6.0.0 (June 18, 2020)
|
|
27
|
+
* Added: automatic definition of traits for Active Record enum attributes, enabled by default
|
|
28
|
+
(Note that this required changing where factory_bot constantizes the build
|
|
29
|
+
class, which may affect applications that were using abstract factories for
|
|
30
|
+
inheritance. See issue #1409.)
|
|
31
|
+
* Added: `traits_for_enum` method to define traits for non-Active Record enums
|
|
32
|
+
* Added: `build_stubbed_starting_id=` option to define the starting id for `build_stubbed`
|
|
33
|
+
* Removed: deprecated methods on the top-level `FactoryBot` module meant only for internal use
|
|
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.
|
|
36
|
+
|
|
37
|
+
## 5.2.0 (April 24, 2020)
|
|
38
|
+
* Added: Pass index to block for `*_list` methods
|
|
39
|
+
* Deprecated: methods on the top-level `FactoryBot` module meant only for internal use: `callbacks`, `configuration`, `constructor`, `initialize_with`, `register_sequence`, `resent_configuration`, `skip_create`, `to_create`
|
|
40
|
+
|
|
41
|
+
## 5.1.2 (March 25, 2020)
|
|
42
|
+
* Fixed: Ruby 2.7 keyword deprecation warning in FactoryBot.lint
|
|
43
|
+
|
|
44
|
+
## 5.1.1 (October 2, 2019)
|
|
45
|
+
* Improved: performance of traits
|
|
46
|
+
* Fixed: registering strategies on JRuby
|
|
47
|
+
|
|
48
|
+
## 5.1.0 (September 21, 2019)
|
|
49
|
+
* Added: "Did you mean?" style error message to help with typos in association declarations
|
|
50
|
+
* Changed: `NoMethodError` for static attributes now offers a "Did you mean?" style message
|
|
51
|
+
* Fixed: avoid undefining inherited evaluator methods
|
|
52
|
+
* Fixed: avoid stubbing id for records without a primary key
|
|
53
|
+
* Fixed: raise a helpful error for self-referencing traits to avoid a `SystemStackError`
|
|
54
|
+
* Deprecated: methods on the top-level `FactoryBot` module meant only for internal use: `allow_class_lookup`, `allow_class_lookup`=, `register_trait`, `trait_by_name`, `traits`, `sequence_by_name`, `sequences`, `factory_by_name`, `register_factory`, `callback_names`, `register_callback`, `register_default_callbacks`, `register_default_strategies`, `strategies`
|
|
55
|
+
|
|
3
56
|
## 5.0.2 (February 22, 2019)
|
|
4
57
|
* Bugfix: raise "Trait not registered" error when passing invalid trait arguments
|
|
5
58
|
|
data/README.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
# factory_bot [![Build Status][ci-image]][ci] [![Code Climate][grade-image]][grade] [![Gem Version][version-image]][version]
|
|
1
|
+
# factory_bot [![Build Status][ci-image]][ci] [![Code Climate][grade-image]][grade] [![Gem Version][version-image]][version]
|
|
2
2
|
|
|
3
3
|
factory_bot is a fixtures replacement with a straightforward definition syntax, support for multiple build strategies (saved instances, unsaved instances, attribute hashes, and stubbed objects), and support for multiple factories for the same class (user, admin_user, and so on), including factory inheritance.
|
|
4
4
|
|
|
5
5
|
If you want to use factory_bot with Rails, see
|
|
6
6
|
[factory_bot_rails](https://github.com/thoughtbot/factory_bot_rails).
|
|
7
7
|
|
|
8
|
-
_[Interested in the history of the project name?]
|
|
8
|
+
_[Interested in the history of the project name?][NAME]_
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
### Transitioning from factory\_girl?
|
|
@@ -43,13 +43,7 @@ gem install factory_bot
|
|
|
43
43
|
Supported Ruby versions
|
|
44
44
|
-----------------------
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
The factory_bot 3.x+ series supports MRI Ruby 1.9. Additionally, factory_bot
|
|
49
|
-
3.6+ supports JRuby 1.6.7.2+ while running in 1.9 mode. See [GETTING_STARTED]
|
|
50
|
-
for more information on configuring the JRuby environment.
|
|
51
|
-
|
|
52
|
-
For versions of Ruby prior to 1.9, please use factory_bot 2.x.
|
|
46
|
+
Supported Ruby versions are listed in [`.github/workflows/build.yml`](https://github.com/thoughtbot/factory_bot/blob/master/.github/workflows/build.yml)
|
|
53
47
|
|
|
54
48
|
More Information
|
|
55
49
|
----------------
|
|
@@ -59,30 +53,37 @@ More Information
|
|
|
59
53
|
* [Issues](https://github.com/thoughtbot/factory_bot/issues)
|
|
60
54
|
* [GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS](https://robots.thoughtbot.com/)
|
|
61
55
|
|
|
62
|
-
|
|
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
|
+
|
|
59
|
+
Useful Tools
|
|
60
|
+
------------
|
|
63
61
|
|
|
64
|
-
[
|
|
62
|
+
* [FactoryTrace](https://github.com/djezzzl/factory_trace) - helps to find unused factories and traits.
|
|
65
63
|
|
|
66
64
|
Contributing
|
|
67
65
|
------------
|
|
68
66
|
|
|
69
67
|
Please see [CONTRIBUTING.md](https://github.com/thoughtbot/factory_bot/blob/master/CONTRIBUTING.md).
|
|
70
68
|
|
|
71
|
-
factory_bot was originally written by Joe Ferris and is
|
|
72
|
-
|
|
69
|
+
factory_bot was originally written by Joe Ferris and is maintained by thoughtbot.
|
|
70
|
+
Many improvements and bugfixes were contributed by the [open source
|
|
73
71
|
community](https://github.com/thoughtbot/factory_bot/graphs/contributors).
|
|
74
72
|
|
|
75
73
|
License
|
|
76
74
|
-------
|
|
77
75
|
|
|
78
|
-
factory_bot is Copyright © 2008-
|
|
76
|
+
factory_bot is Copyright © 2008-2020 Joe Ferris and thoughtbot. It is free
|
|
79
77
|
software, and may be redistributed under the terms specified in the
|
|
80
|
-
[LICENSE]
|
|
78
|
+
[LICENSE] file.
|
|
79
|
+
|
|
80
|
+
[LICENSE]: https://github.com/thoughtbot/factory_bot/blob/master/LICENSE
|
|
81
|
+
|
|
81
82
|
|
|
82
83
|
About thoughtbot
|
|
83
84
|
----------------
|
|
84
85
|
|
|
85
|
-

|
|
86
87
|
|
|
87
88
|
factory_bot is maintained and funded by thoughtbot, inc.
|
|
88
89
|
The names and logos for thoughtbot are trademarks of thoughtbot, inc.
|
|
@@ -93,8 +94,8 @@ See [our other projects][community] or
|
|
|
93
94
|
|
|
94
95
|
[community]: https://thoughtbot.com/community?utm_source=github
|
|
95
96
|
[hire]: https://thoughtbot.com/hire-us?utm_source=github
|
|
96
|
-
[ci-image]: https://
|
|
97
|
-
[ci]: https://
|
|
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
|
[grade-image]: https://codeclimate.com/github/thoughtbot/factory_bot/badges/gpa.svg
|
|
99
100
|
[grade]: https://codeclimate.com/github/thoughtbot/factory_bot
|
|
100
101
|
[version-image]: https://badge.fury.io/rb/factory_bot.svg
|
data/lib/factory_bot/aliases.rb
CHANGED
|
@@ -5,14 +5,14 @@ module FactoryBot
|
|
|
5
5
|
|
|
6
6
|
self.aliases = [
|
|
7
7
|
[/(.+)_id/, '\1'],
|
|
8
|
-
[/(.*)/, '\1_id']
|
|
8
|
+
[/(.*)/, '\1_id']
|
|
9
9
|
]
|
|
10
10
|
|
|
11
11
|
def self.aliases_for(attribute)
|
|
12
|
-
aliases.map
|
|
13
|
-
if pattern.match(attribute
|
|
12
|
+
aliases.map { |(pattern, replace)|
|
|
13
|
+
if pattern.match?(attribute)
|
|
14
14
|
attribute.to_s.sub(pattern, replace).to_sym
|
|
15
15
|
end
|
|
16
|
-
|
|
16
|
+
}.compact << attribute
|
|
17
17
|
end
|
|
18
18
|
end
|
|
@@ -6,12 +6,12 @@ module FactoryBot
|
|
|
6
6
|
|
|
7
7
|
def initialize(name, factory, overrides)
|
|
8
8
|
super(name, false)
|
|
9
|
-
@factory
|
|
9
|
+
@factory = factory
|
|
10
10
|
@overrides = overrides
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def to_proc
|
|
14
|
-
factory
|
|
14
|
+
factory = @factory
|
|
15
15
|
overrides = @overrides
|
|
16
16
|
traits_and_overrides = [factory, overrides].flatten
|
|
17
17
|
factory_name = traits_and_overrides.shift
|
|
@@ -12,10 +12,11 @@ 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
|
|
19
|
+
|
|
19
20
|
value
|
|
20
21
|
}
|
|
21
22
|
end
|
|
@@ -3,9 +3,9 @@ module FactoryBot
|
|
|
3
3
|
class AttributeAssigner
|
|
4
4
|
def initialize(evaluator, build_class, &instance_builder)
|
|
5
5
|
@build_class = build_class
|
|
6
|
-
@instance_builder
|
|
7
|
-
@evaluator
|
|
8
|
-
@attribute_list
|
|
6
|
+
@instance_builder = instance_builder
|
|
7
|
+
@evaluator = evaluator
|
|
8
|
+
@attribute_list = evaluator.class.attribute_list
|
|
9
9
|
@attribute_names_assigned = []
|
|
10
10
|
end
|
|
11
11
|
|
|
@@ -22,9 +22,8 @@ module FactoryBot
|
|
|
22
22
|
def hash
|
|
23
23
|
@evaluator.instance = build_hash
|
|
24
24
|
|
|
25
|
-
attributes_to_set_on_hash.
|
|
25
|
+
attributes_to_set_on_hash.each_with_object({}) do |attribute, result|
|
|
26
26
|
result[attribute] = get(attribute)
|
|
27
|
-
result
|
|
28
27
|
end
|
|
29
28
|
end
|
|
30
29
|
|
|
@@ -33,13 +32,14 @@ module FactoryBot
|
|
|
33
32
|
def method_tracking_evaluator
|
|
34
33
|
@method_tracking_evaluator ||= Decorator::AttributeHash.new(
|
|
35
34
|
decorated_evaluator,
|
|
36
|
-
attribute_names_to_assign
|
|
35
|
+
attribute_names_to_assign
|
|
37
36
|
)
|
|
38
37
|
end
|
|
39
38
|
|
|
40
39
|
def decorated_evaluator
|
|
41
|
-
Decorator::
|
|
42
|
-
Decorator::
|
|
40
|
+
Decorator::NewConstructor.new(
|
|
41
|
+
Decorator::InvocationTracker.new(@evaluator),
|
|
42
|
+
@build_class
|
|
43
43
|
)
|
|
44
44
|
end
|
|
45
45
|
|
|
@@ -96,11 +96,11 @@ module FactoryBot
|
|
|
96
96
|
end
|
|
97
97
|
|
|
98
98
|
def alias_names_to_ignore
|
|
99
|
-
@attribute_list.non_ignored.flat_map
|
|
99
|
+
@attribute_list.non_ignored.flat_map { |attribute|
|
|
100
100
|
override_names.map do |override|
|
|
101
101
|
attribute.name if ignorable_alias?(attribute, override)
|
|
102
102
|
end
|
|
103
|
-
|
|
103
|
+
}.compact
|
|
104
104
|
end
|
|
105
105
|
|
|
106
106
|
def ignorable_alias?(attribute, override)
|
data/lib/factory_bot/callback.rb
CHANGED
|
@@ -3,16 +3,15 @@ module FactoryBot
|
|
|
3
3
|
attr_reader :name
|
|
4
4
|
|
|
5
5
|
def initialize(name, block)
|
|
6
|
-
@name
|
|
6
|
+
@name = name.to_sym
|
|
7
7
|
@block = block
|
|
8
|
-
ensure_valid_callback_name!
|
|
9
8
|
end
|
|
10
9
|
|
|
11
10
|
def run(instance, evaluator)
|
|
12
11
|
case block.arity
|
|
13
|
-
when 1, -1 then syntax_runner.instance_exec(instance, &block)
|
|
12
|
+
when 1, -1, -2 then syntax_runner.instance_exec(instance, &block)
|
|
14
13
|
when 2 then syntax_runner.instance_exec(instance, evaluator, &block)
|
|
15
|
-
else
|
|
14
|
+
else syntax_runner.instance_exec(&block)
|
|
16
15
|
end
|
|
17
16
|
end
|
|
18
17
|
|
|
@@ -27,13 +26,6 @@ module FactoryBot
|
|
|
27
26
|
|
|
28
27
|
private
|
|
29
28
|
|
|
30
|
-
def ensure_valid_callback_name!
|
|
31
|
-
unless FactoryBot.callback_names.include?(name)
|
|
32
|
-
raise InvalidCallbackNameError, "#{name} is not a valid callback name. " +
|
|
33
|
-
"Valid callback names are #{FactoryBot.callback_names.inspect}"
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
|
|
37
29
|
def syntax_runner
|
|
38
30
|
@syntax_runner ||= SyntaxRunner.new
|
|
39
31
|
end
|
|
@@ -7,16 +7,16 @@ module FactoryBot
|
|
|
7
7
|
:inline_sequences,
|
|
8
8
|
:sequences,
|
|
9
9
|
:strategies,
|
|
10
|
-
:traits
|
|
10
|
+
:traits
|
|
11
11
|
)
|
|
12
12
|
|
|
13
13
|
def initialize
|
|
14
|
-
@factories
|
|
15
|
-
@sequences
|
|
16
|
-
@traits
|
|
17
|
-
@strategies
|
|
14
|
+
@factories = Decorator::DisallowsDuplicatesRegistry.new(Registry.new("Factory"))
|
|
15
|
+
@sequences = Decorator::DisallowsDuplicatesRegistry.new(Registry.new("Sequence"))
|
|
16
|
+
@traits = Decorator::DisallowsDuplicatesRegistry.new(Registry.new("Trait"))
|
|
17
|
+
@strategies = Registry.new("Strategy")
|
|
18
18
|
@callback_names = Set.new
|
|
19
|
-
@definition
|
|
19
|
+
@definition = Definition.new(:configuration)
|
|
20
20
|
@inline_sequences = []
|
|
21
21
|
|
|
22
22
|
to_create(&:save!)
|
|
@@ -6,6 +6,7 @@ module FactoryBot
|
|
|
6
6
|
super(name, false)
|
|
7
7
|
@options = options.dup
|
|
8
8
|
@overrides = options.extract_options!
|
|
9
|
+
@factory_name = @overrides.delete(:factory) || name
|
|
9
10
|
@traits = options
|
|
10
11
|
end
|
|
11
12
|
|
|
@@ -21,9 +22,36 @@ module FactoryBot
|
|
|
21
22
|
|
|
22
23
|
private
|
|
23
24
|
|
|
25
|
+
attr_reader :factory_name, :overrides, :traits
|
|
26
|
+
|
|
24
27
|
def build
|
|
25
|
-
|
|
26
|
-
|
|
28
|
+
raise_if_arguments_are_declarations!
|
|
29
|
+
|
|
30
|
+
[
|
|
31
|
+
Attribute::Association.new(
|
|
32
|
+
name,
|
|
33
|
+
factory_name,
|
|
34
|
+
[traits, overrides].flatten
|
|
35
|
+
)
|
|
36
|
+
]
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def raise_if_arguments_are_declarations!
|
|
40
|
+
if factory_name.is_a?(Declaration)
|
|
41
|
+
raise ArgumentError.new(<<~MSG)
|
|
42
|
+
Association '#{name}' received an invalid factory argument.
|
|
43
|
+
Did you mean? 'factory: :#{factory_name.name}'
|
|
44
|
+
MSG
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
overrides.each do |attribute, value|
|
|
48
|
+
if value.is_a?(Declaration)
|
|
49
|
+
raise ArgumentError.new(<<~MSG)
|
|
50
|
+
Association '#{name}' received an invalid attribute override.
|
|
51
|
+
Did you mean? '#{attribute}: :#{value.name}'
|
|
52
|
+
MSG
|
|
53
|
+
end
|
|
54
|
+
end
|
|
27
55
|
end
|
|
28
56
|
end
|
|
29
57
|
end
|
|
@@ -23,8 +23,11 @@ module FactoryBot
|
|
|
23
23
|
def build
|
|
24
24
|
if FactoryBot.factories.registered?(name)
|
|
25
25
|
[Attribute::Association.new(name, name, {})]
|
|
26
|
-
elsif FactoryBot.sequences.registered?(name)
|
|
26
|
+
elsif FactoryBot::Internal.sequences.registered?(name)
|
|
27
27
|
[Attribute::Sequence.new(name, name, @ignored)]
|
|
28
|
+
elsif @factory.name.to_s == name.to_s
|
|
29
|
+
message = "Self-referencing trait '#{@name}'"
|
|
30
|
+
raise TraitDefinitionError, message
|
|
28
31
|
else
|
|
29
32
|
@factory.inherit_traits([name])
|
|
30
33
|
[]
|
|
@@ -6,10 +6,11 @@ module FactoryBot
|
|
|
6
6
|
@invoked_methods = []
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
-
def method_missing(name, *args, &block) # rubocop:disable Style/
|
|
9
|
+
def method_missing(name, *args, &block) # rubocop:disable Style/MissingRespondToMissing
|
|
10
10
|
@invoked_methods << name
|
|
11
11
|
super
|
|
12
12
|
end
|
|
13
|
+
ruby2_keywords :method_missing if respond_to?(:ruby2_keywords, true)
|
|
13
14
|
|
|
14
15
|
def __invoked_methods__
|
|
15
16
|
@invoked_methods.uniq
|
|
@@ -6,18 +6,30 @@ module FactoryBot
|
|
|
6
6
|
@component = component
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
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
|
|
23
|
+
|
|
24
|
+
def send(symbol, *args, &block)
|
|
25
|
+
__send__(symbol, *args, &block)
|
|
26
|
+
end
|
|
11
27
|
end
|
|
12
28
|
|
|
13
29
|
def respond_to_missing?(name, include_private = false)
|
|
14
30
|
@component.respond_to?(name, true) || super
|
|
15
31
|
end
|
|
16
32
|
|
|
17
|
-
def send(symbol, *args, &block)
|
|
18
|
-
__send__(symbol, *args, &block)
|
|
19
|
-
end
|
|
20
|
-
|
|
21
33
|
def self.const_missing(name)
|
|
22
34
|
::Object.const_get(name)
|
|
23
35
|
end
|
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
module FactoryBot
|
|
2
2
|
# @api private
|
|
3
3
|
class Definition
|
|
4
|
-
attr_reader :defined_traits, :declarations, :name
|
|
4
|
+
attr_reader :defined_traits, :declarations, :name, :registered_enums
|
|
5
5
|
|
|
6
6
|
def initialize(name, base_traits = [])
|
|
7
|
-
@name
|
|
8
|
-
@declarations
|
|
9
|
-
@callbacks
|
|
10
|
-
@defined_traits
|
|
11
|
-
@
|
|
12
|
-
@
|
|
7
|
+
@name = name
|
|
8
|
+
@declarations = DeclarationList.new(name)
|
|
9
|
+
@callbacks = []
|
|
10
|
+
@defined_traits = Set.new
|
|
11
|
+
@registered_enums = []
|
|
12
|
+
@to_create = nil
|
|
13
|
+
@base_traits = base_traits
|
|
13
14
|
@additional_traits = []
|
|
14
|
-
@constructor
|
|
15
|
-
@attributes
|
|
16
|
-
@compiled
|
|
15
|
+
@constructor = nil
|
|
16
|
+
@attributes = nil
|
|
17
|
+
@compiled = false
|
|
18
|
+
@expanded_enum_traits = false
|
|
17
19
|
end
|
|
18
20
|
|
|
19
21
|
delegate :declare_attribute, to: :declarations
|
|
@@ -28,7 +30,7 @@ module FactoryBot
|
|
|
28
30
|
end
|
|
29
31
|
|
|
30
32
|
def to_create(&block)
|
|
31
|
-
if
|
|
33
|
+
if block
|
|
32
34
|
@to_create = block
|
|
33
35
|
else
|
|
34
36
|
aggregate_from_traits_and_self(:to_create) { @to_create }.last
|
|
@@ -43,13 +45,15 @@ module FactoryBot
|
|
|
43
45
|
aggregate_from_traits_and_self(:callbacks) { @callbacks }
|
|
44
46
|
end
|
|
45
47
|
|
|
46
|
-
def compile
|
|
48
|
+
def compile(klass = nil)
|
|
47
49
|
unless @compiled
|
|
50
|
+
expand_enum_traits(klass) unless klass.nil?
|
|
51
|
+
|
|
48
52
|
declarations.attributes
|
|
49
53
|
|
|
50
54
|
defined_traits.each do |defined_trait|
|
|
51
|
-
base_traits.each
|
|
52
|
-
additional_traits.each { |
|
|
55
|
+
base_traits.each { |bt| bt.define_trait defined_trait }
|
|
56
|
+
additional_traits.each { |at| at.define_trait defined_trait }
|
|
53
57
|
end
|
|
54
58
|
|
|
55
59
|
@compiled = true
|
|
@@ -81,6 +85,10 @@ module FactoryBot
|
|
|
81
85
|
@defined_traits.add(trait)
|
|
82
86
|
end
|
|
83
87
|
|
|
88
|
+
def register_enum(enum)
|
|
89
|
+
@registered_enums << enum
|
|
90
|
+
end
|
|
91
|
+
|
|
84
92
|
def define_constructor(&block)
|
|
85
93
|
@constructor = block
|
|
86
94
|
end
|
|
@@ -95,7 +103,6 @@ module FactoryBot
|
|
|
95
103
|
|
|
96
104
|
def callback(*names, &block)
|
|
97
105
|
names.each do |name|
|
|
98
|
-
FactoryBot.register_callback(name)
|
|
99
106
|
add_callback(Callback.new(name, block))
|
|
100
107
|
end
|
|
101
108
|
end
|
|
@@ -104,6 +111,20 @@ module FactoryBot
|
|
|
104
111
|
|
|
105
112
|
def base_traits
|
|
106
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
|
|
107
128
|
end
|
|
108
129
|
|
|
109
130
|
def additional_traits
|
|
@@ -111,17 +132,19 @@ module FactoryBot
|
|
|
111
132
|
end
|
|
112
133
|
|
|
113
134
|
def trait_by_name(name)
|
|
114
|
-
trait_for(name) ||
|
|
135
|
+
trait_for(name) || Internal.trait_by_name(name)
|
|
115
136
|
end
|
|
116
137
|
|
|
117
138
|
def trait_for(name)
|
|
118
|
-
defined_traits.
|
|
139
|
+
@defined_traits_by_name ||= defined_traits.each_with_object({}) { |t, memo| memo[t.name] ||= t }
|
|
140
|
+
@defined_traits_by_name[name.to_s]
|
|
119
141
|
end
|
|
120
142
|
|
|
121
143
|
def initialize_copy(source)
|
|
122
144
|
super
|
|
123
145
|
@attributes = nil
|
|
124
|
-
@compiled
|
|
146
|
+
@compiled = false
|
|
147
|
+
@defined_traits_by_name = nil
|
|
125
148
|
end
|
|
126
149
|
|
|
127
150
|
def aggregate_from_traits_and_self(method_name, &block)
|
|
@@ -130,8 +153,32 @@ module FactoryBot
|
|
|
130
153
|
[
|
|
131
154
|
base_traits.map(&method_name),
|
|
132
155
|
instance_exec(&block),
|
|
133
|
-
additional_traits.map(&method_name)
|
|
156
|
+
additional_traits.map(&method_name)
|
|
134
157
|
].flatten.compact
|
|
135
158
|
end
|
|
159
|
+
|
|
160
|
+
def expand_enum_traits(klass)
|
|
161
|
+
return if @expanded_enum_traits
|
|
162
|
+
|
|
163
|
+
if automatically_register_defined_enums?(klass)
|
|
164
|
+
automatically_register_defined_enums(klass)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
registered_enums.each do |enum|
|
|
168
|
+
traits = enum.build_traits(klass)
|
|
169
|
+
traits.each { |trait| define_trait(trait) }
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
@expanded_enum_traits = true
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def automatically_register_defined_enums(klass)
|
|
176
|
+
klass.defined_enums.each_key { |name| register_enum(Enum.new(name)) }
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def automatically_register_defined_enums?(klass)
|
|
180
|
+
FactoryBot.automatically_define_enum_traits &&
|
|
181
|
+
klass.respond_to?(:defined_enums)
|
|
182
|
+
end
|
|
136
183
|
end
|
|
137
184
|
end
|
|
@@ -1,16 +1,6 @@
|
|
|
1
1
|
module FactoryBot
|
|
2
2
|
class DefinitionHierarchy
|
|
3
|
-
|
|
4
|
-
FactoryBot.callbacks
|
|
5
|
-
end
|
|
6
|
-
|
|
7
|
-
def constructor
|
|
8
|
-
FactoryBot.constructor
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def to_create
|
|
12
|
-
FactoryBot.to_create
|
|
13
|
-
end
|
|
3
|
+
delegate :callbacks, :constructor, :to_create, to: Internal
|
|
14
4
|
|
|
15
5
|
def self.build_from_definition(definition)
|
|
16
6
|
build_to_create(&definition.to_create)
|