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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +58 -13
  3. data/GETTING_STARTED.md +745 -149
  4. data/NEWS.md +53 -0
  5. data/README.md +19 -18
  6. data/lib/factory_bot/aliases.rb +4 -4
  7. data/lib/factory_bot/attribute/association.rb +2 -2
  8. data/lib/factory_bot/attribute/dynamic.rb +3 -2
  9. data/lib/factory_bot/attribute_assigner.rb +10 -10
  10. data/lib/factory_bot/attribute_list.rb +1 -1
  11. data/lib/factory_bot/callback.rb +3 -11
  12. data/lib/factory_bot/configuration.rb +6 -6
  13. data/lib/factory_bot/declaration/association.rb +30 -2
  14. data/lib/factory_bot/declaration/implicit.rb +4 -1
  15. data/lib/factory_bot/declaration.rb +1 -1
  16. data/lib/factory_bot/declaration_list.rb +2 -2
  17. data/lib/factory_bot/decorator/invocation_tracker.rb +2 -1
  18. data/lib/factory_bot/decorator.rb +18 -6
  19. data/lib/factory_bot/definition.rb +66 -19
  20. data/lib/factory_bot/definition_hierarchy.rb +1 -11
  21. data/lib/factory_bot/definition_proxy.rb +77 -12
  22. data/lib/factory_bot/enum.rb +27 -0
  23. data/lib/factory_bot/errors.rb +3 -0
  24. data/lib/factory_bot/evaluator.rb +8 -9
  25. data/lib/factory_bot/evaluator_class_definer.rb +1 -1
  26. data/lib/factory_bot/factory.rb +13 -13
  27. data/lib/factory_bot/factory_runner.rb +4 -4
  28. data/lib/factory_bot/find_definitions.rb +1 -1
  29. data/lib/factory_bot/internal.rb +68 -1
  30. data/lib/factory_bot/linter.rb +9 -13
  31. data/lib/factory_bot/null_factory.rb +10 -4
  32. data/lib/factory_bot/null_object.rb +2 -6
  33. data/lib/factory_bot/registry.rb +4 -4
  34. data/lib/factory_bot/reload.rb +1 -2
  35. data/lib/factory_bot/sequence.rb +5 -5
  36. data/lib/factory_bot/strategy/attributes_for.rb +4 -0
  37. data/lib/factory_bot/strategy/build.rb +4 -0
  38. data/lib/factory_bot/strategy/create.rb +4 -0
  39. data/lib/factory_bot/strategy/null.rb +8 -2
  40. data/lib/factory_bot/strategy/stub.rb +20 -5
  41. data/lib/factory_bot/strategy_calculator.rb +1 -1
  42. data/lib/factory_bot/strategy_syntax_method_registrar.rb +12 -1
  43. data/lib/factory_bot/syntax/default.rb +12 -24
  44. data/lib/factory_bot/syntax/methods.rb +3 -3
  45. data/lib/factory_bot/trait.rb +5 -3
  46. data/lib/factory_bot/version.rb +1 -1
  47. data/lib/factory_bot.rb +21 -93
  48. metadata +12 -39
@@ -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
@@ -37,6 +41,10 @@ module FactoryBot
37
41
  end
38
42
  end
39
43
 
44
+ def to_sym
45
+ :stub
46
+ end
47
+
40
48
  private
41
49
 
42
50
  def next_id
@@ -44,15 +52,17 @@ module FactoryBot
44
52
  end
45
53
 
46
54
  def stub_database_interaction_on_result(result_instance)
47
- result_instance.id ||= next_id
55
+ if has_settable_id?(result_instance)
56
+ result_instance.id ||= next_id
57
+ end
48
58
 
49
59
  result_instance.instance_eval do
50
60
  def persisted?
51
- !new_record?
61
+ true
52
62
  end
53
63
 
54
64
  def new_record?
55
- id.nil?
65
+ false
56
66
  end
57
67
 
58
68
  def destroyed?
@@ -62,12 +72,17 @@ module FactoryBot
62
72
  DISABLED_PERSISTENCE_METHODS.each do |write_method|
63
73
  define_singleton_method(write_method) do |*args|
64
74
  raise "stubbed models are not allowed to access the database - "\
65
- "#{self.class}##{write_method}(#{args.join(',')})"
75
+ "#{self.class}##{write_method}(#{args.join(",")})"
66
76
  end
67
77
  end
68
78
  end
69
79
  end
70
80
 
81
+ def has_settable_id?(result_instance)
82
+ !result_instance.class.respond_to?(:primary_key) ||
83
+ result_instance.class.primary_key
84
+ end
85
+
71
86
  def clear_changes_information(result_instance)
72
87
  if result_instance.respond_to?(:clear_changes_information)
73
88
  result_instance.clear_changes_information
@@ -20,7 +20,7 @@ module FactoryBot
20
20
  end
21
21
 
22
22
  def strategy_name_to_object
23
- FactoryBot.strategy_by_name(@name_or_object)
23
+ FactoryBot::Internal.strategy_by_name(@name_or_object)
24
24
  end
25
25
  end
26
26
  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,9 +15,9 @@ 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
- FactoryBot.register_factory(factory)
20
+ Internal.register_factory(factory)
21
21
 
22
22
  proxy.child_factories.each do |(child_name, child_options, child_block)|
23
23
  parent_factory = child_options.delete(:parent) || name
@@ -26,41 +26,29 @@ module FactoryBot
26
26
  end
27
27
 
28
28
  def sequence(name, *args, &block)
29
- FactoryBot.register_sequence(Sequence.new(name, *args, &block))
29
+ Internal.register_sequence(Sequence.new(name, *args, &block))
30
30
  end
31
31
 
32
32
  def trait(name, &block)
33
- FactoryBot.register_trait(Trait.new(name, &block))
34
- end
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)
33
+ Internal.register_trait(Trait.new(name, &block))
46
34
  end
47
35
 
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
- FactoryBot::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
62
50
  def factory(name, _options = {}, &block)
63
- factory = FactoryBot.factory_by_name(name)
51
+ factory = Internal.factory_by_name(name)
64
52
  proxy = FactoryBot::DefinitionProxy.new(factory.definition.overridable)
65
53
  proxy.instance_eval(&block)
66
54
  end
@@ -30,7 +30,7 @@ module FactoryBot
30
30
  ## # factory with traits and attribute override
31
31
  ## build_stubbed_list(:user, 15, :admin, :male, name: "John Doe")
32
32
  module Methods
33
- # @!parse FactoryBot.register_default_strategies
33
+ # @!parse FactoryBot::Internal.register_default_strategies
34
34
  # @!method build(name, *traits_and_overrides, &block)
35
35
  # (see #strategy_method)
36
36
  # Builds a registered factory by name.
@@ -111,7 +111,7 @@ module FactoryBot
111
111
  # Returns:
112
112
  # The next value in the sequence. (Object)
113
113
  def generate(name)
114
- FactoryBot.sequence_by_name(name).next
114
+ Internal.sequence_by_name(name).next
115
115
  end
116
116
 
117
117
  # Generates and returns the list of values in a sequence.
@@ -126,7 +126,7 @@ module FactoryBot
126
126
  # The next value in the sequence. (Object)
127
127
  def generate_list(name, count)
128
128
  (1..count).map do
129
- FactoryBot.sequence_by_name(name).next
129
+ Internal.sequence_by_name(name).next
130
130
  end
131
131
  end
132
132
  end
@@ -7,13 +7,15 @@ module FactoryBot
7
7
  @name = name.to_s
8
8
  @block = block
9
9
  @definition = Definition.new(@name)
10
-
11
10
  proxy = FactoryBot::DefinitionProxy.new(@definition)
12
- proxy.instance_eval(&@block) if block_given?
11
+
12
+ if block
13
+ proxy.instance_eval(&@block)
14
+ end
13
15
  end
14
16
 
15
17
  delegate :add_callback, :declare_attribute, :to_create, :define_trait, :constructor,
16
- :callbacks, :attributes, to: :@definition
18
+ :callbacks, :attributes, to: :@definition
17
19
 
18
20
  def names
19
21
  [@name]
@@ -1,3 +1,3 @@
1
1
  module FactoryBot
2
- VERSION = "5.0.2".freeze
2
+ VERSION = "6.2.1".freeze
3
3
  end
data/lib/factory_bot.rb CHANGED
@@ -4,6 +4,7 @@ require "active_support/core_ext/module/attribute_accessors"
4
4
  require "active_support/deprecation"
5
5
  require "active_support/notifications"
6
6
 
7
+ require "factory_bot/internal"
7
8
  require "factory_bot/definition_hierarchy"
8
9
  require "factory_bot/configuration"
9
10
  require "factory_bot/errors"
@@ -31,6 +32,7 @@ require "factory_bot/declaration"
31
32
  require "factory_bot/sequence"
32
33
  require "factory_bot/attribute_list"
33
34
  require "factory_bot/trait"
35
+ require "factory_bot/enum"
34
36
  require "factory_bot/aliases"
35
37
  require "factory_bot/definition"
36
38
  require "factory_bot/definition_proxy"
@@ -45,22 +47,16 @@ require "factory_bot/decorator/invocation_tracker"
45
47
  require "factory_bot/decorator/new_constructor"
46
48
  require "factory_bot/linter"
47
49
  require "factory_bot/version"
48
- require "factory_bot/internal"
49
50
 
50
51
  module FactoryBot
51
- DEPRECATOR = ActiveSupport::Deprecation.new("6.0", "factory_bot")
52
-
53
- def self.configuration
54
- Internal.configuration
55
- end
56
-
57
- def self.reset_configuration
58
- Internal.reset_configuration
59
- end
52
+ Deprecation = ActiveSupport::Deprecation.new("7.0", "factory_bot")
60
53
 
61
54
  mattr_accessor :use_parent_strategy, instance_accessor: false
62
55
  self.use_parent_strategy = true
63
56
 
57
+ mattr_accessor :automatically_define_enum_traits, instance_accessor: false
58
+ self.automatically_define_enum_traits = true
59
+
64
60
  # Look for errors in factories and (optionally) their traits.
65
61
  # Parameters:
66
62
  # factories - which factories to lint; omit for all factories
@@ -71,93 +67,25 @@ module FactoryBot
71
67
  def self.lint(*args)
72
68
  options = args.extract_options!
73
69
  factories_to_lint = args[0] || FactoryBot.factories
74
- Linter.new(factories_to_lint, options).lint!
75
- end
76
-
77
- class << self
78
- delegate :factories,
79
- :sequences,
80
- :traits,
81
- :callbacks,
82
- :strategies,
83
- :callback_names,
84
- :to_create,
85
- :skip_create,
86
- :initialize_with,
87
- :constructor,
88
- to: :configuration
89
-
90
- attr_accessor :allow_class_lookup
91
- deprecate :allow_class_lookup, :allow_class_lookup=, deprecator: DEPRECATOR
92
- end
93
-
94
- def self.register_factory(factory)
95
- factory.names.each do |name|
96
- factories.register(name, factory)
97
- end
98
- factory
99
- end
100
-
101
- def self.factory_by_name(name)
102
- factories.find(name)
103
- end
104
-
105
- def self.register_sequence(sequence)
106
- sequence.names.each do |name|
107
- sequences.register(name, sequence)
108
- end
109
- sequence
110
- end
111
-
112
- def self.sequence_by_name(name)
113
- sequences.find(name)
114
- end
115
-
116
- def self.rewind_sequences
117
- sequences.each(&:rewind)
118
- Internal.rewind_inline_sequences
119
- end
120
-
121
- def self.register_trait(trait)
122
- trait.names.each do |name|
123
- traits.register(name, trait)
124
- end
125
- trait
126
- end
127
-
128
- def self.trait_by_name(name)
129
- traits.find(name)
70
+ Linter.new(factories_to_lint, **options).lint!
130
71
  end
131
72
 
132
- def self.register_strategy(strategy_name, strategy_class)
133
- strategies.register(strategy_name, strategy_class)
134
- StrategySyntaxMethodRegistrar.new(strategy_name).define_strategy_methods
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
135
80
  end
136
81
 
137
- def self.strategy_by_name(name)
138
- strategies.find(name)
139
- end
140
-
141
- def self.register_default_strategies
142
- register_strategy(:build, FactoryBot::Strategy::Build)
143
- register_strategy(:create, FactoryBot::Strategy::Create)
144
- register_strategy(:attributes_for, FactoryBot::Strategy::AttributesFor)
145
- register_strategy(:build_stubbed, FactoryBot::Strategy::Stub)
146
- register_strategy(:null, FactoryBot::Strategy::Null)
147
- end
148
-
149
- def self.register_default_callbacks
150
- register_callback(:after_build)
151
- register_callback(:after_create)
152
- register_callback(:after_stub)
153
- register_callback(:before_create)
154
- end
155
-
156
- def self.register_callback(name)
157
- name = name.to_sym
158
- callback_names << name
82
+ class << self
83
+ delegate :factories,
84
+ :register_strategy,
85
+ :rewind_sequences,
86
+ :strategy_by_name,
87
+ to: Internal
159
88
  end
160
89
  end
161
90
 
162
- FactoryBot.register_default_strategies
163
- FactoryBot.register_default_callbacks
91
+ FactoryBot::Internal.register_default_strategies
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.0.2
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: 2019-02-22 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
@@ -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,35 +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
142
- requirement: !ruby/object:Gem::Requirement
143
- requirements:
144
- - - ">="
145
- - !ruby/object:Gem::Version
146
- version: '0'
147
- type: :development
148
- prerelease: false
149
- version_requirements: !ruby/object:Gem::Requirement
150
- requirements:
151
- - - ">="
152
- - !ruby/object:Gem::Version
153
- version: '0'
154
- - !ruby/object:Gem::Dependency
155
- name: sqlite3
127
+ name: standard
156
128
  requirement: !ruby/object:Gem::Requirement
157
129
  requirements:
158
130
  - - ">="
@@ -166,7 +138,7 @@ dependencies:
166
138
  - !ruby/object:Gem::Version
167
139
  version: '0'
168
140
  - !ruby/object:Gem::Dependency
169
- name: timecop
141
+ name: simplecov
170
142
  requirement: !ruby/object:Gem::Requirement
171
143
  requirements:
172
144
  - - ">="
@@ -233,6 +205,7 @@ files:
233
205
  - lib/factory_bot/definition.rb
234
206
  - lib/factory_bot/definition_hierarchy.rb
235
207
  - lib/factory_bot/definition_proxy.rb
208
+ - lib/factory_bot/enum.rb
236
209
  - lib/factory_bot/errors.rb
237
210
  - lib/factory_bot/evaluation.rb
238
211
  - lib/factory_bot/evaluator.rb
@@ -264,7 +237,7 @@ homepage: https://github.com/thoughtbot/factory_bot
264
237
  licenses:
265
238
  - MIT
266
239
  metadata: {}
267
- post_install_message:
240
+ post_install_message:
268
241
  rdoc_options: []
269
242
  require_paths:
270
243
  - lib
@@ -272,15 +245,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
272
245
  requirements:
273
246
  - - ">="
274
247
  - !ruby/object:Gem::Version
275
- version: 2.3.0
248
+ version: 2.5.0
276
249
  required_rubygems_version: !ruby/object:Gem::Requirement
277
250
  requirements:
278
251
  - - ">="
279
252
  - !ruby/object:Gem::Version
280
253
  version: '0'
281
254
  requirements: []
282
- rubygems_version: 3.0.1
283
- signing_key:
255
+ rubygems_version: 3.1.6
256
+ signing_key:
284
257
  specification_version: 4
285
258
  summary: factory_bot provides a framework and DSL for defining and using model instance
286
259
  factories.