factory_bot 4.10.0 → 6.0.0
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/.yardopts +1 -0
- data/CONTRIBUTING.md +52 -13
- data/GETTING_STARTED.md +613 -182
- data/LICENSE +1 -1
- data/NEWS.md +358 -0
- data/README.md +30 -26
- data/lib/factory_bot.rb +71 -140
- data/lib/factory_bot/aliases.rb +2 -2
- data/lib/factory_bot/attribute.rb +4 -39
- data/lib/factory_bot/attribute/association.rb +2 -2
- data/lib/factory_bot/attribute/dynamic.rb +2 -1
- data/lib/factory_bot/attribute_assigner.rb +24 -10
- data/lib/factory_bot/attribute_list.rb +3 -2
- data/lib/factory_bot/callback.rb +3 -10
- data/lib/factory_bot/configuration.rb +15 -19
- data/lib/factory_bot/declaration.rb +5 -5
- data/lib/factory_bot/declaration/association.rb +14 -1
- data/lib/factory_bot/declaration/dynamic.rb +3 -1
- data/lib/factory_bot/declaration/implicit.rb +7 -2
- data/lib/factory_bot/declaration_list.rb +3 -3
- data/lib/factory_bot/decorator.rb +5 -5
- data/lib/factory_bot/decorator/attribute_hash.rb +1 -1
- data/lib/factory_bot/decorator/invocation_tracker.rb +1 -1
- data/lib/factory_bot/definition.rb +49 -20
- data/lib/factory_bot/definition_hierarchy.rb +1 -11
- data/lib/factory_bot/definition_proxy.rb +125 -43
- data/lib/factory_bot/enum.rb +27 -0
- data/lib/factory_bot/errors.rb +7 -4
- data/lib/factory_bot/evaluation.rb +1 -1
- data/lib/factory_bot/evaluator.rb +9 -11
- data/lib/factory_bot/evaluator_class_definer.rb +1 -1
- data/lib/factory_bot/factory.rb +12 -12
- data/lib/factory_bot/factory_runner.rb +4 -4
- data/lib/factory_bot/find_definitions.rb +2 -2
- data/lib/factory_bot/internal.rb +91 -0
- data/lib/factory_bot/linter.rb +41 -28
- data/lib/factory_bot/null_factory.rb +13 -4
- data/lib/factory_bot/null_object.rb +2 -6
- data/lib/factory_bot/registry.rb +17 -8
- data/lib/factory_bot/reload.rb +2 -3
- data/lib/factory_bot/sequence.rb +5 -6
- data/lib/factory_bot/strategy/stub.rb +37 -37
- data/lib/factory_bot/strategy_calculator.rb +1 -1
- data/lib/factory_bot/strategy_syntax_method_registrar.rb +13 -2
- data/lib/factory_bot/syntax.rb +2 -2
- data/lib/factory_bot/syntax/default.rb +12 -24
- data/lib/factory_bot/syntax/methods.rb +32 -9
- data/lib/factory_bot/trait.rb +7 -4
- data/lib/factory_bot/version.rb +1 -1
- metadata +50 -65
- data/.autotest +0 -9
- data/.gitignore +0 -10
- data/.rspec +0 -3
- data/.simplecov +0 -4
- data/.travis.yml +0 -58
- data/Appraisals +0 -23
- data/Gemfile +0 -8
- data/Gemfile.lock +0 -103
- data/NEWS +0 -298
- data/Rakefile +0 -36
- data/cucumber.yml +0 -1
- data/factory_bot.gemspec +0 -36
- data/factory_girl.gemspec +0 -40
- data/gemfiles/3.2.gemfile +0 -10
- data/gemfiles/3.2.gemfile.lock +0 -107
- data/gemfiles/4.0.gemfile +0 -10
- data/gemfiles/4.0.gemfile.lock +0 -107
- data/gemfiles/4.1.gemfile +0 -10
- data/gemfiles/4.1.gemfile.lock +0 -106
- data/gemfiles/4.2.gemfile +0 -10
- data/gemfiles/4.2.gemfile.lock +0 -106
- data/gemfiles/5.0.gemfile +0 -10
- data/gemfiles/5.0.gemfile.lock +0 -104
- data/gemfiles/5.1.gemfile +0 -10
- data/gemfiles/5.1.gemfile.lock +0 -104
- data/lib/factory_bot/attribute/static.rb +0 -16
- data/lib/factory_bot/declaration/static.rb +0 -26
- data/lib/factory_bot/decorator/class_key_hash.rb +0 -28
- data/lib/factory_girl.rb +0 -5
data/lib/factory_bot.rb
CHANGED
@@ -1,59 +1,61 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
5
|
-
|
6
|
-
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
11
|
-
require
|
12
|
-
require
|
13
|
-
require
|
14
|
-
require
|
15
|
-
require
|
16
|
-
require
|
17
|
-
require
|
18
|
-
require
|
19
|
-
require
|
20
|
-
require
|
21
|
-
require
|
22
|
-
require
|
23
|
-
require
|
24
|
-
require
|
25
|
-
require
|
26
|
-
require
|
27
|
-
require
|
28
|
-
require
|
29
|
-
require
|
30
|
-
require
|
31
|
-
require
|
32
|
-
require
|
33
|
-
require
|
34
|
-
require
|
35
|
-
require
|
36
|
-
require
|
37
|
-
require
|
38
|
-
require
|
39
|
-
require
|
40
|
-
require
|
41
|
-
require
|
42
|
-
require
|
43
|
-
require
|
44
|
-
require
|
45
|
-
require
|
46
|
-
require
|
47
|
-
require
|
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/internal"
|
8
|
+
require "factory_bot/definition_hierarchy"
|
9
|
+
require "factory_bot/configuration"
|
10
|
+
require "factory_bot/errors"
|
11
|
+
require "factory_bot/factory_runner"
|
12
|
+
require "factory_bot/strategy_syntax_method_registrar"
|
13
|
+
require "factory_bot/strategy_calculator"
|
14
|
+
require "factory_bot/strategy/build"
|
15
|
+
require "factory_bot/strategy/create"
|
16
|
+
require "factory_bot/strategy/attributes_for"
|
17
|
+
require "factory_bot/strategy/stub"
|
18
|
+
require "factory_bot/strategy/null"
|
19
|
+
require "factory_bot/registry"
|
20
|
+
require "factory_bot/null_factory"
|
21
|
+
require "factory_bot/null_object"
|
22
|
+
require "factory_bot/evaluation"
|
23
|
+
require "factory_bot/factory"
|
24
|
+
require "factory_bot/attribute_assigner"
|
25
|
+
require "factory_bot/evaluator"
|
26
|
+
require "factory_bot/evaluator_class_definer"
|
27
|
+
require "factory_bot/attribute"
|
28
|
+
require "factory_bot/callback"
|
29
|
+
require "factory_bot/callbacks_observer"
|
30
|
+
require "factory_bot/declaration_list"
|
31
|
+
require "factory_bot/declaration"
|
32
|
+
require "factory_bot/sequence"
|
33
|
+
require "factory_bot/attribute_list"
|
34
|
+
require "factory_bot/trait"
|
35
|
+
require "factory_bot/enum"
|
36
|
+
require "factory_bot/aliases"
|
37
|
+
require "factory_bot/definition"
|
38
|
+
require "factory_bot/definition_proxy"
|
39
|
+
require "factory_bot/syntax"
|
40
|
+
require "factory_bot/syntax_runner"
|
41
|
+
require "factory_bot/find_definitions"
|
42
|
+
require "factory_bot/reload"
|
43
|
+
require "factory_bot/decorator"
|
44
|
+
require "factory_bot/decorator/attribute_hash"
|
45
|
+
require "factory_bot/decorator/disallows_duplicates_registry"
|
46
|
+
require "factory_bot/decorator/invocation_tracker"
|
47
|
+
require "factory_bot/decorator/new_constructor"
|
48
|
+
require "factory_bot/linter"
|
49
|
+
require "factory_bot/version"
|
48
50
|
|
49
51
|
module FactoryBot
|
50
|
-
|
51
|
-
@configuration ||= Configuration.new
|
52
|
-
end
|
52
|
+
Deprecation = ActiveSupport::Deprecation.new("7.0", "factory_bot")
|
53
53
|
|
54
|
-
|
55
|
-
|
56
|
-
|
54
|
+
mattr_accessor :use_parent_strategy, instance_accessor: false
|
55
|
+
self.use_parent_strategy = true
|
56
|
+
|
57
|
+
mattr_accessor :automatically_define_enum_traits, instance_accessor: false
|
58
|
+
self.automatically_define_enum_traits = true
|
57
59
|
|
58
60
|
# Look for errors in factories and (optionally) their traits.
|
59
61
|
# Parameters:
|
@@ -61,100 +63,29 @@ module FactoryBot
|
|
61
63
|
# options:
|
62
64
|
# traits: true - to lint traits as well as factories
|
63
65
|
# strategy: :create - to specify the strategy for linting
|
66
|
+
# verbose: true - to include full backtraces for each linting error
|
64
67
|
def self.lint(*args)
|
65
68
|
options = args.extract_options!
|
66
69
|
factories_to_lint = args[0] || FactoryBot.factories
|
67
|
-
|
68
|
-
factory_strategy = options[:strategy] || :create
|
69
|
-
Linter.new(factories_to_lint, linting_strategy, factory_strategy).lint!
|
70
|
-
end
|
71
|
-
|
72
|
-
class << self
|
73
|
-
delegate :factories,
|
74
|
-
:sequences,
|
75
|
-
:traits,
|
76
|
-
:callbacks,
|
77
|
-
:strategies,
|
78
|
-
:callback_names,
|
79
|
-
:to_create,
|
80
|
-
:skip_create,
|
81
|
-
:initialize_with,
|
82
|
-
: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
|
-
to: :configuration
|
90
|
-
end
|
91
|
-
|
92
|
-
def self.register_factory(factory)
|
93
|
-
factory.names.each do |name|
|
94
|
-
factories.register(name, factory)
|
95
|
-
end
|
96
|
-
factory
|
97
|
-
end
|
98
|
-
|
99
|
-
def self.factory_by_name(name)
|
100
|
-
factories.find(name)
|
101
|
-
end
|
102
|
-
|
103
|
-
def self.register_sequence(sequence)
|
104
|
-
sequence.names.each do |name|
|
105
|
-
sequences.register(name, sequence)
|
106
|
-
end
|
107
|
-
sequence
|
108
|
-
end
|
109
|
-
|
110
|
-
def self.sequence_by_name(name)
|
111
|
-
sequences.find(name)
|
112
|
-
end
|
113
|
-
|
114
|
-
def self.rewind_sequences
|
115
|
-
sequences.each(&:rewind)
|
116
|
-
end
|
117
|
-
|
118
|
-
def self.register_trait(trait)
|
119
|
-
trait.names.each do |name|
|
120
|
-
traits.register(name, trait)
|
121
|
-
end
|
122
|
-
trait
|
123
|
-
end
|
124
|
-
|
125
|
-
def self.trait_by_name(name)
|
126
|
-
traits.find(name)
|
70
|
+
Linter.new(factories_to_lint, **options).lint!
|
127
71
|
end
|
128
72
|
|
129
|
-
|
130
|
-
|
131
|
-
|
73
|
+
# Set the starting value for ids when using the build_stubbed strategy
|
74
|
+
#
|
75
|
+
# Arguments:
|
76
|
+
# * starting_id +Integer+
|
77
|
+
# The new starting id value.
|
78
|
+
def self.build_stubbed_starting_id=(starting_id)
|
79
|
+
Strategy::Stub.next_id = starting_id - 1
|
132
80
|
end
|
133
81
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
register_strategy(:create, FactoryBot::Strategy::Create)
|
141
|
-
register_strategy(:attributes_for, FactoryBot::Strategy::AttributesFor)
|
142
|
-
register_strategy(:build_stubbed, FactoryBot::Strategy::Stub)
|
143
|
-
register_strategy(:null, FactoryBot::Strategy::Null)
|
144
|
-
end
|
145
|
-
|
146
|
-
def self.register_default_callbacks
|
147
|
-
register_callback(:after_build)
|
148
|
-
register_callback(:after_create)
|
149
|
-
register_callback(:after_stub)
|
150
|
-
register_callback(:before_create)
|
151
|
-
end
|
152
|
-
|
153
|
-
def self.register_callback(name)
|
154
|
-
name = name.to_sym
|
155
|
-
callback_names << name
|
82
|
+
class << self
|
83
|
+
delegate :factories,
|
84
|
+
:register_strategy,
|
85
|
+
:rewind_sequences,
|
86
|
+
:strategy_by_name,
|
87
|
+
to: Internal
|
156
88
|
end
|
157
89
|
end
|
158
90
|
|
159
|
-
FactoryBot.register_default_strategies
|
160
|
-
FactoryBot.register_default_callbacks
|
91
|
+
FactoryBot::Internal.register_default_strategies
|
data/lib/factory_bot/aliases.rb
CHANGED
@@ -9,10 +9,10 @@ module FactoryBot
|
|
9
9
|
]
|
10
10
|
|
11
11
|
def self.aliases_for(attribute)
|
12
|
-
aliases.map
|
12
|
+
aliases.map { |(pattern, replace)|
|
13
13
|
if pattern.match(attribute.to_s)
|
14
14
|
attribute.to_s.sub(pattern, replace).to_sym
|
15
15
|
end
|
16
|
-
|
16
|
+
}.compact << attribute
|
17
17
|
end
|
18
18
|
end
|
@@ -1,7 +1,6 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require 'factory_bot/attribute/sequence'
|
1
|
+
require "factory_bot/attribute/dynamic"
|
2
|
+
require "factory_bot/attribute/association"
|
3
|
+
require "factory_bot/attribute/sequence"
|
5
4
|
|
6
5
|
module FactoryBot
|
7
6
|
# @api private
|
@@ -11,11 +10,10 @@ module FactoryBot
|
|
11
10
|
def initialize(name, ignored)
|
12
11
|
@name = name.to_sym
|
13
12
|
@ignored = ignored
|
14
|
-
ensure_non_attribute_writer!
|
15
13
|
end
|
16
14
|
|
17
15
|
def to_proc
|
18
|
-
-> {
|
16
|
+
-> {}
|
19
17
|
end
|
20
18
|
|
21
19
|
def association?
|
@@ -25,38 +23,5 @@ module FactoryBot
|
|
25
23
|
def alias_for?(attr)
|
26
24
|
FactoryBot.aliases_for(attr).include?(name)
|
27
25
|
end
|
28
|
-
|
29
|
-
private
|
30
|
-
|
31
|
-
def ensure_non_attribute_writer!
|
32
|
-
NonAttributeWriterValidator.new(@name).validate!
|
33
|
-
end
|
34
|
-
|
35
|
-
class NonAttributeWriterValidator
|
36
|
-
def initialize(method_name)
|
37
|
-
@method_name = method_name.to_s
|
38
|
-
@method_name_setter_match = @method_name.match(/(.*)=$/)
|
39
|
-
end
|
40
|
-
|
41
|
-
def validate!
|
42
|
-
if method_is_writer?
|
43
|
-
raise AttributeDefinitionError, error_message
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
private
|
48
|
-
|
49
|
-
def method_is_writer?
|
50
|
-
!!@method_name_setter_match
|
51
|
-
end
|
52
|
-
|
53
|
-
def attribute_name
|
54
|
-
@method_name_setter_match[1]
|
55
|
-
end
|
56
|
-
|
57
|
-
def error_message
|
58
|
-
"factory_bot uses '#{attribute_name} value' syntax rather than '#{attribute_name} = value'"
|
59
|
-
end
|
60
|
-
end
|
61
26
|
end
|
62
27
|
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
|
@@ -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,16 +22,18 @@ 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
|
|
31
30
|
private
|
32
31
|
|
33
32
|
def method_tracking_evaluator
|
34
|
-
@method_tracking_evaluator ||= Decorator::AttributeHash.new(
|
33
|
+
@method_tracking_evaluator ||= Decorator::AttributeHash.new(
|
34
|
+
decorated_evaluator,
|
35
|
+
attribute_names_to_assign
|
36
|
+
)
|
35
37
|
end
|
36
38
|
|
37
39
|
def decorated_evaluator
|
@@ -65,7 +67,11 @@ module FactoryBot
|
|
65
67
|
end
|
66
68
|
|
67
69
|
def attribute_names_to_assign
|
68
|
-
@attribute_names_to_assign ||=
|
70
|
+
@attribute_names_to_assign ||=
|
71
|
+
non_ignored_attribute_names +
|
72
|
+
override_names -
|
73
|
+
ignored_attribute_names -
|
74
|
+
alias_names_to_ignore
|
69
75
|
end
|
70
76
|
|
71
77
|
def non_ignored_attribute_names
|
@@ -89,9 +95,17 @@ module FactoryBot
|
|
89
95
|
end
|
90
96
|
|
91
97
|
def alias_names_to_ignore
|
92
|
-
@attribute_list.non_ignored.flat_map
|
93
|
-
override_names.map
|
94
|
-
|
98
|
+
@attribute_list.non_ignored.flat_map { |attribute|
|
99
|
+
override_names.map do |override|
|
100
|
+
attribute.name if ignorable_alias?(attribute, override)
|
101
|
+
end
|
102
|
+
}.compact
|
103
|
+
end
|
104
|
+
|
105
|
+
def ignorable_alias?(attribute, override)
|
106
|
+
attribute.alias_for?(override) &&
|
107
|
+
attribute.name != override &&
|
108
|
+
!ignored_attribute_names.include?(override)
|
95
109
|
end
|
96
110
|
end
|
97
111
|
end
|
@@ -4,7 +4,7 @@ module FactoryBot
|
|
4
4
|
include Enumerable
|
5
5
|
|
6
6
|
def initialize(name = nil, attributes = [])
|
7
|
-
@name
|
7
|
+
@name = name
|
8
8
|
@attributes = attributes
|
9
9
|
end
|
10
10
|
|
@@ -54,7 +54,8 @@ module FactoryBot
|
|
54
54
|
|
55
55
|
def ensure_attribute_not_self_referencing!(attribute)
|
56
56
|
if attribute.respond_to?(:factory) && attribute.factory == @name
|
57
|
-
|
57
|
+
message = "Self-referencing association '#{attribute.name}' in '#{attribute.factory}'"
|
58
|
+
raise AssociationDefinitionError, message
|
58
59
|
end
|
59
60
|
end
|
60
61
|
|
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
12
|
when 1, -1 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
|
|
@@ -22,17 +21,11 @@ module FactoryBot
|
|
22
21
|
end
|
23
22
|
|
24
23
|
protected
|
24
|
+
|
25
25
|
attr_reader :block
|
26
26
|
|
27
27
|
private
|
28
28
|
|
29
|
-
def ensure_valid_callback_name!
|
30
|
-
unless FactoryBot.callback_names.include?(name)
|
31
|
-
raise InvalidCallbackNameError, "#{name} is not a valid callback name. " +
|
32
|
-
"Valid callback names are #{FactoryBot.callback_names.inspect}"
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
29
|
def syntax_runner
|
37
30
|
@syntax_runner ||= SyntaxRunner.new
|
38
31
|
end
|