factory_bot 5.1.0 → 6.2.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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +58 -13
  3. data/GETTING_STARTED.md +695 -139
  4. data/NEWS.md +40 -1
  5. data/README.md +8 -14
  6. data/lib/factory_bot.rb +21 -55
  7. data/lib/factory_bot/aliases.rb +3 -3
  8. data/lib/factory_bot/attribute/association.rb +2 -2
  9. data/lib/factory_bot/attribute/dynamic.rb +3 -2
  10. data/lib/factory_bot/attribute_assigner.rb +9 -10
  11. data/lib/factory_bot/attribute_list.rb +1 -1
  12. data/lib/factory_bot/callback.rb +3 -11
  13. data/lib/factory_bot/configuration.rb +6 -6
  14. data/lib/factory_bot/declaration.rb +1 -1
  15. data/lib/factory_bot/declaration/association.rb +23 -6
  16. data/lib/factory_bot/declaration_list.rb +2 -2
  17. data/lib/factory_bot/decorator.rb +18 -6
  18. data/lib/factory_bot/decorator/invocation_tracker.rb +2 -1
  19. data/lib/factory_bot/definition.rb +65 -18
  20. data/lib/factory_bot/definition_hierarchy.rb +1 -11
  21. data/lib/factory_bot/definition_proxy.rb +64 -6
  22. data/lib/factory_bot/enum.rb +27 -0
  23. data/lib/factory_bot/evaluator.rb +6 -7
  24. data/lib/factory_bot/evaluator_class_definer.rb +1 -1
  25. data/lib/factory_bot/factory.rb +12 -12
  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/internal.rb +18 -29
  29. data/lib/factory_bot/linter.rb +9 -13
  30. data/lib/factory_bot/null_factory.rb +10 -4
  31. data/lib/factory_bot/null_object.rb +2 -6
  32. data/lib/factory_bot/registry.rb +4 -4
  33. data/lib/factory_bot/reload.rb +0 -1
  34. data/lib/factory_bot/sequence.rb +5 -5
  35. data/lib/factory_bot/strategy/null.rb +4 -2
  36. data/lib/factory_bot/strategy/stub.rb +6 -2
  37. data/lib/factory_bot/strategy_syntax_method_registrar.rb +12 -1
  38. data/lib/factory_bot/syntax/default.rb +8 -20
  39. data/lib/factory_bot/trait.rb +2 -2
  40. data/lib/factory_bot/version.rb +1 -1
  41. metadata +12 -25
@@ -1,11 +1,11 @@
1
1
  module FactoryBot
2
2
  class FactoryRunner
3
3
  def initialize(name, strategy, traits_and_overrides)
4
- @name = name
4
+ @name = name
5
5
  @strategy = strategy
6
6
 
7
7
  @overrides = traits_and_overrides.extract_options!
8
- @traits = traits_and_overrides
8
+ @traits = traits_and_overrides
9
9
  end
10
10
 
11
11
  def run(runner_strategy = @strategy, &block)
@@ -22,7 +22,7 @@ module FactoryBot
22
22
  strategy: runner_strategy,
23
23
  traits: @traits,
24
24
  overrides: @overrides,
25
- factory: factory,
25
+ factory: factory
26
26
  }
27
27
 
28
28
  ActiveSupport::Notifications.instrument("factory_bot.run_factory", instrumentation_payload) do
@@ -7,7 +7,7 @@ module FactoryBot
7
7
  attr_accessor :definition_file_paths
8
8
  end
9
9
 
10
- self.definition_file_paths = %w(factories test/factories spec/factories)
10
+ self.definition_file_paths = %w[factories test/factories spec/factories]
11
11
 
12
12
  def self.find_definitions
13
13
  absolute_definition_file_paths = definition_file_paths.map { |path| File.expand_path(path) }
@@ -1,26 +1,20 @@
1
1
  module FactoryBot
2
2
  # @api private
3
3
  module Internal
4
- DEFAULT_STRATEGIES = {
5
- build: FactoryBot::Strategy::Build,
6
- create: FactoryBot::Strategy::Create,
7
- attributes_for: FactoryBot::Strategy::AttributesFor,
8
- build_stubbed: FactoryBot::Strategy::Stub,
9
- null: FactoryBot::Strategy::Null,
10
- }.freeze
11
-
12
- DEFAULT_CALLBACKS = [
13
- :after_create, :after_build, :after_stub, :after_create
14
- ].freeze
15
-
16
4
  class << self
17
- delegate :callback_names,
18
- :factories,
19
- :inline_sequences,
20
- :sequences,
21
- :strategies,
22
- :traits,
23
- to: :configuration
5
+ delegate :after,
6
+ :before,
7
+ :callbacks,
8
+ :constructor,
9
+ :factories,
10
+ :initialize_with,
11
+ :inline_sequences,
12
+ :sequences,
13
+ :skip_create,
14
+ :strategies,
15
+ :to_create,
16
+ :traits,
17
+ to: :configuration
24
18
 
25
19
  def configuration
26
20
  @configuration ||= Configuration.new
@@ -86,16 +80,11 @@ module FactoryBot
86
80
  end
87
81
 
88
82
  def register_default_strategies
89
- DEFAULT_STRATEGIES.each(&method(:register_strategy))
90
- end
91
-
92
- def register_default_callbacks
93
- DEFAULT_CALLBACKS.each(&method(:register_callback))
94
- end
95
-
96
- def register_callback(name)
97
- name = name.to_sym
98
- callback_names << name
83
+ register_strategy(:build, FactoryBot::Strategy::Build)
84
+ register_strategy(:create, FactoryBot::Strategy::Create)
85
+ register_strategy(:attributes_for, FactoryBot::Strategy::AttributesFor)
86
+ register_strategy(:build_stubbed, FactoryBot::Strategy::Stub)
87
+ register_strategy(:null, FactoryBot::Strategy::Null)
99
88
  end
100
89
  end
101
90
  end
@@ -19,17 +19,16 @@ module FactoryBot
19
19
  attr_reader :factories_to_lint, :invalid_factories, :factory_strategy
20
20
 
21
21
  def calculate_invalid_factories
22
- factories_to_lint.reduce(Hash.new([])) do |result, factory|
22
+ factories_to_lint.each_with_object(Hash.new([])) do |factory, result|
23
23
  errors = lint(factory)
24
24
  result[factory] |= errors unless errors.empty?
25
- result
26
25
  end
27
26
  end
28
27
 
29
28
  class FactoryError
30
29
  def initialize(wrapped_error, factory)
31
30
  @wrapped_error = wrapped_error
32
- @factory = factory
31
+ @factory = factory
33
32
  end
34
33
 
35
34
  def message
@@ -72,8 +71,8 @@ module FactoryBot
72
71
  result = []
73
72
  begin
74
73
  FactoryBot.public_send(factory_strategy, factory.name)
75
- rescue StandardError => error
76
- result |= [FactoryError.new(error, factory)]
74
+ rescue => e
75
+ result |= [FactoryError.new(e, factory)]
77
76
  end
78
77
  result
79
78
  end
@@ -81,20 +80,17 @@ module FactoryBot
81
80
  def lint_traits(factory)
82
81
  result = []
83
82
  factory.definition.defined_traits.map(&:name).each do |trait_name|
84
- begin
85
- FactoryBot.public_send(factory_strategy, factory.name, trait_name)
86
- rescue StandardError => error
87
- result |=
88
- [FactoryTraitError.new(error, factory, trait_name)]
89
- end
83
+ FactoryBot.public_send(factory_strategy, factory.name, trait_name)
84
+ rescue => e
85
+ result |= [FactoryTraitError.new(e, factory, trait_name)]
90
86
  end
91
87
  result
92
88
  end
93
89
 
94
90
  def error_message
95
- lines = invalid_factories.map do |_factory, exceptions|
91
+ lines = invalid_factories.map { |_factory, exceptions|
96
92
  exceptions.map(&error_message_type)
97
- end.flatten
93
+ }.flatten
98
94
 
99
95
  <<~ERROR_MESSAGE.strip
100
96
  The following factories are invalid:
@@ -10,12 +10,18 @@ module FactoryBot
10
10
  delegate :defined_traits, :callbacks, :attributes, :constructor,
11
11
  :to_create, to: :definition
12
12
 
13
- def compile; end
13
+ def compile
14
+ end
14
15
 
15
- def class_name; end
16
+ def class_name
17
+ end
16
18
 
17
- def evaluator_class; FactoryBot::Evaluator; end
19
+ def evaluator_class
20
+ FactoryBot::Evaluator
21
+ end
18
22
 
19
- def hierarchy_class; FactoryBot::DefinitionHierarchy; end
23
+ def hierarchy_class
24
+ FactoryBot::DefinitionHierarchy
25
+ end
20
26
  end
21
27
  end
@@ -5,7 +5,7 @@ module FactoryBot
5
5
  @methods_to_respond_to = methods_to_respond_to.map(&:to_s)
6
6
  end
7
7
 
8
- def method_missing(name, *args, &block)
8
+ def method_missing(name, *args, &block) # rubocop:disable Style/MissingRespondToMissing
9
9
  if respond_to?(name)
10
10
  nil
11
11
  else
@@ -13,12 +13,8 @@ module FactoryBot
13
13
  end
14
14
  end
15
15
 
16
- def respond_to?(method, _include_private = false)
16
+ def respond_to?(method)
17
17
  @methods_to_respond_to.include? method.to_s
18
18
  end
19
-
20
- def respond_to_missing?(*)
21
- false
22
- end
23
19
  end
24
20
  end
@@ -7,7 +7,7 @@ module FactoryBot
7
7
  attr_reader :name
8
8
 
9
9
  def initialize(name)
10
- @name = name
10
+ @name = name
11
11
  @items = ActiveSupport::HashWithIndifferentAccess.new
12
12
  end
13
13
 
@@ -21,11 +21,11 @@ module FactoryBot
21
21
 
22
22
  def find(name)
23
23
  @items.fetch(name)
24
- rescue KeyError => key_error
25
- raise key_error_with_custom_message(key_error)
24
+ rescue KeyError => e
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
@@ -2,7 +2,6 @@ module FactoryBot
2
2
  def self.reload
3
3
  Internal.reset_configuration
4
4
  Internal.register_default_strategies
5
- Internal.register_default_callbacks
6
5
  find_definitions
7
6
  end
8
7
  end
@@ -6,14 +6,14 @@ module FactoryBot
6
6
  attr_reader :name
7
7
 
8
8
  def initialize(name, *args, &proc)
9
- @name = name
10
- @proc = proc
9
+ @name = name
10
+ @proc = proc
11
11
 
12
- options = args.extract_options!
13
- @value = args.first || 1
12
+ options = args.extract_options!
13
+ @value = args.first || 1
14
14
  @aliases = options.fetch(:aliases) { [] }
15
15
 
16
- if !@value.respond_to?(:peek)
16
+ unless @value.respond_to?(:peek)
17
17
  @value = EnumeratorAdapter.new(@value)
18
18
  end
19
19
  end
@@ -1,9 +1,11 @@
1
1
  module FactoryBot
2
2
  module Strategy
3
3
  class Null
4
- def association(runner); end
4
+ def association(runner)
5
+ end
5
6
 
6
- def result(evaluation); end
7
+ def result(evaluation)
8
+ end
7
9
  end
8
10
  end
9
11
  end
@@ -21,9 +21,13 @@ module FactoryBot
21
21
  :update_attributes!,
22
22
  :update_attributes,
23
23
  :update_column,
24
- :update_columns,
24
+ :update_columns
25
25
  ].freeze
26
26
 
27
+ def self.next_id=(id)
28
+ @@next_id = id
29
+ end
30
+
27
31
  def association(runner)
28
32
  runner.run(:build_stubbed)
29
33
  end
@@ -64,7 +68,7 @@ module FactoryBot
64
68
  DISABLED_PERSISTENCE_METHODS.each do |write_method|
65
69
  define_singleton_method(write_method) do |*args|
66
70
  raise "stubbed models are not allowed to access the database - "\
67
- "#{self.class}##{write_method}(#{args.join(',')})"
71
+ "#{self.class}##{write_method}(#{args.join(",")})"
68
72
  end
69
73
  end
70
74
  end
@@ -11,6 +11,14 @@ module FactoryBot
11
11
  define_pair_strategy_method
12
12
  end
13
13
 
14
+ def self.with_index(block, index)
15
+ if block&.arity == 2
16
+ ->(instance) { block.call(instance, index) }
17
+ else
18
+ block
19
+ end
20
+ end
21
+
14
22
  private
15
23
 
16
24
  def define_singular_strategy_method
@@ -29,7 +37,10 @@ module FactoryBot
29
37
  raise ArgumentError, "count missing for #{strategy_name}_list"
30
38
  end
31
39
 
32
- Array.new(amount) { send(strategy_name, name, *traits_and_overrides, &block) }
40
+ Array.new(amount) do |i|
41
+ block_with_index = StrategySyntaxMethodRegistrar.with_index(block, i)
42
+ send(strategy_name, name, *traits_and_overrides, &block_with_index)
43
+ end
33
44
  end
34
45
  end
35
46
 
@@ -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
 
@@ -33,29 +33,17 @@ module FactoryBot
33
33
  Internal.register_trait(Trait.new(name, &block))
34
34
  end
35
35
 
36
- def to_create(&block)
37
- FactoryBot.to_create(&block)
38
- end
39
-
40
- def skip_create
41
- FactoryBot.skip_create
42
- end
43
-
44
- def initialize_with(&block)
45
- FactoryBot.initialize_with(&block)
46
- end
47
-
48
36
  def self.run(block)
49
37
  new.instance_eval(&block)
50
38
  end
51
39
 
52
- delegate :before, :after, :callback, to: :configuration
53
-
54
- private
55
-
56
- def configuration
57
- Internal.configuration
58
- end
40
+ delegate :after,
41
+ :before,
42
+ :callback,
43
+ :initialize_with,
44
+ :skip_create,
45
+ :to_create,
46
+ to: FactoryBot::Internal
59
47
  end
60
48
 
61
49
  class ModifyDSL
@@ -9,13 +9,13 @@ 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
16
16
 
17
17
  delegate :add_callback, :declare_attribute, :to_create, :define_trait, :constructor,
18
- :callbacks, :attributes, to: :@definition
18
+ :callbacks, :attributes, to: :@definition
19
19
 
20
20
  def names
21
21
  [@name]
@@ -1,3 +1,3 @@
1
1
  module FactoryBot
2
- VERSION = "5.1.0".freeze
2
+ VERSION = "6.2.0".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: 5.1.0
4
+ version: 6.2.0
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: 2019-09-21 00:00:00.000000000 Z
12
+ date: 2021-05-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -17,14 +17,14 @@ dependencies:
17
17
  requirements:
18
18
  - - ">="
19
19
  - !ruby/object:Gem::Version
20
- version: 4.2.0
20
+ version: 5.0.0
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
25
  - - ">="
26
26
  - !ruby/object:Gem::Version
27
- version: 4.2.0
27
+ version: 5.0.0
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: activerecord
30
30
  requirement: !ruby/object:Gem::Requirement
@@ -124,21 +124,7 @@ dependencies:
124
124
  - !ruby/object:Gem::Version
125
125
  version: '0'
126
126
  - !ruby/object:Gem::Dependency
127
- name: rubocop
128
- requirement: !ruby/object:Gem::Requirement
129
- requirements:
130
- - - '='
131
- - !ruby/object:Gem::Version
132
- version: '0.54'
133
- type: :development
134
- prerelease: false
135
- version_requirements: !ruby/object:Gem::Requirement
136
- requirements:
137
- - - '='
138
- - !ruby/object:Gem::Version
139
- version: '0.54'
140
- - !ruby/object:Gem::Dependency
141
- name: simplecov
127
+ name: standard
142
128
  requirement: !ruby/object:Gem::Requirement
143
129
  requirements:
144
130
  - - ">="
@@ -152,7 +138,7 @@ dependencies:
152
138
  - !ruby/object:Gem::Version
153
139
  version: '0'
154
140
  - !ruby/object:Gem::Dependency
155
- name: sqlite3
141
+ name: simplecov
156
142
  requirement: !ruby/object:Gem::Requirement
157
143
  requirements:
158
144
  - - ">="
@@ -219,6 +205,7 @@ files:
219
205
  - lib/factory_bot/definition.rb
220
206
  - lib/factory_bot/definition_hierarchy.rb
221
207
  - lib/factory_bot/definition_proxy.rb
208
+ - lib/factory_bot/enum.rb
222
209
  - lib/factory_bot/errors.rb
223
210
  - lib/factory_bot/evaluation.rb
224
211
  - lib/factory_bot/evaluator.rb
@@ -250,7 +237,7 @@ homepage: https://github.com/thoughtbot/factory_bot
250
237
  licenses:
251
238
  - MIT
252
239
  metadata: {}
253
- post_install_message:
240
+ post_install_message:
254
241
  rdoc_options: []
255
242
  require_paths:
256
243
  - lib
@@ -258,15 +245,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
258
245
  requirements:
259
246
  - - ">="
260
247
  - !ruby/object:Gem::Version
261
- version: 2.3.0
248
+ version: 2.5.0
262
249
  required_rubygems_version: !ruby/object:Gem::Requirement
263
250
  requirements:
264
251
  - - ">="
265
252
  - !ruby/object:Gem::Version
266
253
  version: '0'
267
254
  requirements: []
268
- rubygems_version: 3.0.3
269
- signing_key:
255
+ rubygems_version: 3.2.16
256
+ signing_key:
270
257
  specification_version: 4
271
258
  summary: factory_bot provides a framework and DSL for defining and using model instance
272
259
  factories.