tiny-lite-mod 0.0.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 (62) hide show
  1. checksums.yaml +7 -0
  2. data/factory_bot-6.6.0/CONTRIBUTING.md +105 -0
  3. data/factory_bot-6.6.0/GETTING_STARTED.md +2203 -0
  4. data/factory_bot-6.6.0/LICENSE +19 -0
  5. data/factory_bot-6.6.0/NAME.md +18 -0
  6. data/factory_bot-6.6.0/NEWS.md +607 -0
  7. data/factory_bot-6.6.0/README.md +99 -0
  8. data/factory_bot-6.6.0/lib/factory_bot/aliases.rb +18 -0
  9. data/factory_bot-6.6.0/lib/factory_bot/attribute/association.rb +27 -0
  10. data/factory_bot-6.6.0/lib/factory_bot/attribute/dynamic.rb +25 -0
  11. data/factory_bot-6.6.0/lib/factory_bot/attribute/sequence.rb +16 -0
  12. data/factory_bot-6.6.0/lib/factory_bot/attribute.rb +27 -0
  13. data/factory_bot-6.6.0/lib/factory_bot/attribute_assigner.rb +168 -0
  14. data/factory_bot-6.6.0/lib/factory_bot/attribute_list.rb +68 -0
  15. data/factory_bot-6.6.0/lib/factory_bot/callback.rb +33 -0
  16. data/factory_bot-6.6.0/lib/factory_bot/callbacks_observer.rb +39 -0
  17. data/factory_bot-6.6.0/lib/factory_bot/configuration.rb +33 -0
  18. data/factory_bot-6.6.0/lib/factory_bot/declaration/association.rb +58 -0
  19. data/factory_bot-6.6.0/lib/factory_bot/declaration/dynamic.rb +28 -0
  20. data/factory_bot-6.6.0/lib/factory_bot/declaration/implicit.rb +38 -0
  21. data/factory_bot-6.6.0/lib/factory_bot/declaration.rb +23 -0
  22. data/factory_bot-6.6.0/lib/factory_bot/declaration_list.rb +49 -0
  23. data/factory_bot-6.6.0/lib/factory_bot/decorator/attribute_hash.rb +16 -0
  24. data/factory_bot-6.6.0/lib/factory_bot/decorator/disallows_duplicates_registry.rb +13 -0
  25. data/factory_bot-6.6.0/lib/factory_bot/decorator/invocation_tracker.rb +20 -0
  26. data/factory_bot-6.6.0/lib/factory_bot/decorator/new_constructor.rb +12 -0
  27. data/factory_bot-6.6.0/lib/factory_bot/decorator.rb +25 -0
  28. data/factory_bot-6.6.0/lib/factory_bot/definition.rb +210 -0
  29. data/factory_bot-6.6.0/lib/factory_bot/definition_hierarchy.rb +38 -0
  30. data/factory_bot-6.6.0/lib/factory_bot/definition_proxy.rb +269 -0
  31. data/factory_bot-6.6.0/lib/factory_bot/enum.rb +27 -0
  32. data/factory_bot-6.6.0/lib/factory_bot/errors.rb +28 -0
  33. data/factory_bot-6.6.0/lib/factory_bot/evaluation.rb +23 -0
  34. data/factory_bot-6.6.0/lib/factory_bot/evaluator.rb +86 -0
  35. data/factory_bot-6.6.0/lib/factory_bot/evaluator_class_definer.rb +20 -0
  36. data/factory_bot-6.6.0/lib/factory_bot/factory.rb +178 -0
  37. data/factory_bot-6.6.0/lib/factory_bot/factory_runner.rb +35 -0
  38. data/factory_bot-6.6.0/lib/factory_bot/find_definitions.rb +25 -0
  39. data/factory_bot-6.6.0/lib/factory_bot/internal.rb +124 -0
  40. data/factory_bot-6.6.0/lib/factory_bot/linter.rb +121 -0
  41. data/factory_bot-6.6.0/lib/factory_bot/null_factory.rb +27 -0
  42. data/factory_bot-6.6.0/lib/factory_bot/null_object.rb +20 -0
  43. data/factory_bot-6.6.0/lib/factory_bot/registry.rb +59 -0
  44. data/factory_bot-6.6.0/lib/factory_bot/reload.rb +7 -0
  45. data/factory_bot-6.6.0/lib/factory_bot/sequence.rb +197 -0
  46. data/factory_bot-6.6.0/lib/factory_bot/strategy/attributes_for.rb +17 -0
  47. data/factory_bot-6.6.0/lib/factory_bot/strategy/build.rb +21 -0
  48. data/factory_bot-6.6.0/lib/factory_bot/strategy/create.rb +24 -0
  49. data/factory_bot-6.6.0/lib/factory_bot/strategy/null.rb +15 -0
  50. data/factory_bot-6.6.0/lib/factory_bot/strategy/stub.rb +129 -0
  51. data/factory_bot-6.6.0/lib/factory_bot/strategy.rb +15 -0
  52. data/factory_bot-6.6.0/lib/factory_bot/strategy_syntax_method_registrar.rb +65 -0
  53. data/factory_bot-6.6.0/lib/factory_bot/syntax/default.rb +64 -0
  54. data/factory_bot-6.6.0/lib/factory_bot/syntax/methods.rb +181 -0
  55. data/factory_bot-6.6.0/lib/factory_bot/syntax.rb +7 -0
  56. data/factory_bot-6.6.0/lib/factory_bot/syntax_runner.rb +6 -0
  57. data/factory_bot-6.6.0/lib/factory_bot/trait.rb +39 -0
  58. data/factory_bot-6.6.0/lib/factory_bot/uri_manager.rb +63 -0
  59. data/factory_bot-6.6.0/lib/factory_bot/version.rb +3 -0
  60. data/factory_bot-6.6.0/lib/factory_bot.rb +117 -0
  61. data/tiny-lite-mod.gemspec +12 -0
  62. metadata +101 -0
@@ -0,0 +1,28 @@
1
+ module FactoryBot
2
+ # Raised when a factory is defined that attempts to instantiate itself.
3
+ class AssociationDefinitionError < RuntimeError; end
4
+
5
+ # Raised when a trait is defined that references itself.
6
+ class TraitDefinitionError < RuntimeError; end
7
+
8
+ # Raised when a callback is defined that has an invalid name
9
+ class InvalidCallbackNameError < RuntimeError; end
10
+
11
+ # Raised when a factory is defined with the same name as a previously-defined factory.
12
+ class DuplicateDefinitionError < RuntimeError; end
13
+
14
+ # Raised when attempting to register a sequence from a dynamic attribute block
15
+ class SequenceAbuseError < RuntimeError; end
16
+
17
+ # Raised when defining an attribute twice in the same factory
18
+ class AttributeDefinitionError < RuntimeError; end
19
+
20
+ # Raised when attempting to pass a block to an association definition
21
+ class AssociationDefinitionError < RuntimeError; end
22
+
23
+ # Raised when a method is defined in a factory or trait with arguments
24
+ class MethodDefinitionError < RuntimeError; end
25
+
26
+ # Raised when any factory is considered invalid
27
+ class InvalidFactoryError < RuntimeError; end
28
+ end
@@ -0,0 +1,23 @@
1
+ module FactoryBot
2
+ class Evaluation
3
+ def initialize(evaluator, attribute_assigner, to_create, observer)
4
+ @evaluator = evaluator
5
+ @attribute_assigner = attribute_assigner
6
+ @to_create = to_create
7
+ @observer = observer
8
+ end
9
+
10
+ delegate :object, :hash, to: :@attribute_assigner
11
+
12
+ def create(result_instance)
13
+ case @to_create.arity
14
+ when 2 then @to_create[result_instance, @evaluator]
15
+ else @to_create[result_instance]
16
+ end
17
+ end
18
+
19
+ def notify(name, result_instance)
20
+ @observer.update(name, result_instance)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,86 @@
1
+ require "active_support/core_ext/class/attribute"
2
+
3
+ module FactoryBot
4
+ # @api private
5
+ class Evaluator
6
+ class_attribute :attribute_lists
7
+
8
+ private_instance_methods.each do |method|
9
+ undef_method(method) unless method.match?(/^__|initialize/)
10
+ end
11
+
12
+ def initialize(build_strategy, overrides = {})
13
+ @build_strategy = build_strategy
14
+ @overrides = overrides
15
+ @cached_attributes = overrides
16
+ @instance = nil
17
+
18
+ @overrides.each do |name, value|
19
+ singleton_class.define_attribute(name) { value }
20
+ end
21
+ end
22
+
23
+ def association(factory_name, *traits_and_overrides)
24
+ overrides = traits_and_overrides.extract_options!
25
+ strategy_override = overrides.fetch(:strategy) {
26
+ FactoryBot.use_parent_strategy ? @build_strategy.to_sym : :create
27
+ }
28
+
29
+ traits_and_overrides += [overrides.except(:strategy)]
30
+
31
+ runner = FactoryRunner.new(factory_name, strategy_override, traits_and_overrides)
32
+ @build_strategy.association(runner)
33
+ end
34
+
35
+ attr_accessor :instance
36
+
37
+ def method_missing(method_name, ...)
38
+ if @instance.respond_to?(method_name)
39
+ @instance.send(method_name, ...)
40
+ else
41
+ SyntaxRunner.new.send(method_name, ...)
42
+ end
43
+ end
44
+
45
+ def respond_to_missing?(method_name, _include_private = false)
46
+ @instance.respond_to?(method_name) || SyntaxRunner.new.respond_to?(method_name)
47
+ end
48
+
49
+ def __override_names__
50
+ @overrides.keys
51
+ end
52
+
53
+ def increment_sequence(sequence, scope: self)
54
+ value = sequence.next(scope)
55
+
56
+ raise if value.respond_to?(:start_with?) && value.start_with?("#<FactoryBot::Declaration")
57
+
58
+ value
59
+ rescue
60
+ raise ArgumentError, "Sequence '#{sequence.uri_manager.first}' failed to " \
61
+ "return a value. Perhaps it needs a scope to operate? (scope: <object>)"
62
+ end
63
+
64
+ def self.attribute_list
65
+ AttributeList.new.tap do |list|
66
+ attribute_lists.each do |attribute_list|
67
+ list.apply_attributes attribute_list.to_a
68
+ end
69
+ end
70
+ end
71
+
72
+ def self.define_attribute(name, &block)
73
+ if instance_methods(false).include?(name) || private_instance_methods(false).include?(name)
74
+ undef_method(name)
75
+ end
76
+
77
+ define_method(name) do
78
+ if @cached_attributes.key?(name)
79
+ @cached_attributes[name]
80
+ else
81
+ @cached_attributes[name] = instance_exec(&block)
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,20 @@
1
+ module FactoryBot
2
+ # @api private
3
+ class EvaluatorClassDefiner
4
+ def initialize(attributes, parent_class)
5
+ @parent_class = parent_class
6
+ @attributes = attributes
7
+
8
+ attributes.each do |attribute|
9
+ evaluator_class.define_attribute(attribute.name, &attribute.to_proc)
10
+ end
11
+ end
12
+
13
+ def evaluator_class
14
+ @evaluator_class ||= Class.new(@parent_class).tap do |klass|
15
+ klass.attribute_lists ||= []
16
+ klass.attribute_lists += [@attributes]
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,178 @@
1
+ require "active_support/core_ext/hash/keys"
2
+ require "active_support/inflector"
3
+
4
+ module FactoryBot
5
+ # @api private
6
+ class Factory
7
+ attr_reader :name, :definition
8
+
9
+ def initialize(name, options = {})
10
+ assert_valid_options(options)
11
+ @name = name.respond_to?(:to_sym) ? name.to_sym : name.to_s.underscore.to_sym
12
+ @parent = options[:parent]
13
+ @aliases = options[:aliases] || []
14
+ @class_name = options[:class]
15
+ @uri_manager = FactoryBot::UriManager.new(names)
16
+ @definition = Definition.new(@name, options[:traits] || [], uri_manager: @uri_manager)
17
+ @compiled = false
18
+ end
19
+
20
+ delegate :add_callback, :declare_attribute, :to_create, :define_trait, :constructor,
21
+ :defined_traits, :defined_traits_names, :inherit_traits, :append_traits,
22
+ to: :@definition
23
+
24
+ def build_class
25
+ @build_class ||= if class_name.is_a? Class
26
+ class_name
27
+ elsif class_name.to_s.safe_constantize
28
+ class_name.to_s.safe_constantize
29
+ else
30
+ class_name.to_s.camelize.constantize
31
+ end
32
+ end
33
+
34
+ def run(build_strategy, overrides, &block)
35
+ block ||= ->(result) { result }
36
+
37
+ compile
38
+
39
+ strategy = Strategy.lookup_strategy(build_strategy).new
40
+
41
+ evaluator = evaluator_class.new(strategy, overrides.symbolize_keys)
42
+ attribute_assigner = AttributeAssigner.new(evaluator, build_class, &compiled_constructor)
43
+
44
+ observer = CallbacksObserver.new(callbacks, evaluator)
45
+ evaluation = Evaluation.new(evaluator, attribute_assigner, compiled_to_create, observer)
46
+
47
+ evaluation.notify(:before_all, nil)
48
+ instance = strategy.result(evaluation).tap(&block)
49
+ evaluation.notify(:after_all, instance)
50
+
51
+ instance
52
+ end
53
+
54
+ def human_names
55
+ names.map { |name| name.to_s.humanize.downcase }
56
+ end
57
+
58
+ def associations
59
+ evaluator_class.attribute_list.associations
60
+ end
61
+
62
+ # Names for this factory, including aliases.
63
+ #
64
+ # Example:
65
+ #
66
+ # factory :user, aliases: [:author] do
67
+ # # ...
68
+ # end
69
+ #
70
+ # FactoryBot.create(:author).class
71
+ # # => User
72
+ #
73
+ # Because an attribute defined without a value or block will build an
74
+ # association with the same name, this allows associations to be defined
75
+ # without factories, such as:
76
+ #
77
+ # factory :user, aliases: [:author] do
78
+ # # ...
79
+ # end
80
+ #
81
+ # factory :post do
82
+ # author
83
+ # end
84
+ #
85
+ # FactoryBot.create(:post).author.class
86
+ # # => User
87
+ def names
88
+ [name] + @aliases
89
+ end
90
+
91
+ def compile
92
+ unless @compiled
93
+ parent.compile
94
+ inherit_parent_traits
95
+ @definition.compile(build_class)
96
+ build_hierarchy
97
+ @compiled = true
98
+ end
99
+ end
100
+
101
+ def with_traits(traits)
102
+ clone.tap do |factory_with_traits|
103
+ factory_with_traits.append_traits traits
104
+ end
105
+ end
106
+
107
+ protected
108
+
109
+ def class_name
110
+ @class_name || parent.class_name || name
111
+ end
112
+
113
+ def evaluator_class
114
+ @evaluator_class ||= EvaluatorClassDefiner.new(attributes, parent.evaluator_class).evaluator_class
115
+ end
116
+
117
+ def attributes
118
+ compile
119
+ AttributeList.new(@name).tap do |list|
120
+ list.apply_attributes definition.attributes
121
+ end
122
+ end
123
+
124
+ def hierarchy_class
125
+ @hierarchy_class ||= Class.new(parent.hierarchy_class)
126
+ end
127
+
128
+ def hierarchy_instance
129
+ @hierarchy_instance ||= hierarchy_class.new
130
+ end
131
+
132
+ def build_hierarchy
133
+ hierarchy_class.build_from_definition definition
134
+ end
135
+
136
+ def callbacks
137
+ hierarchy_instance.callbacks
138
+ end
139
+
140
+ def compiled_to_create
141
+ hierarchy_instance.to_create
142
+ end
143
+
144
+ def compiled_constructor
145
+ hierarchy_instance.constructor
146
+ end
147
+
148
+ private
149
+
150
+ def assert_valid_options(options)
151
+ options.assert_valid_keys(:class, :parent, :aliases, :traits)
152
+ end
153
+
154
+ def parent
155
+ if @parent
156
+ FactoryBot::Internal.factory_by_name(@parent)
157
+ else
158
+ NullFactory.new
159
+ end
160
+ end
161
+
162
+ def inherit_parent_traits
163
+ parent.defined_traits.each do |trait|
164
+ next if defined_traits_names.include?(trait.name)
165
+ define_trait(trait.clone)
166
+ end
167
+ end
168
+
169
+ def initialize_copy(source)
170
+ super
171
+ @definition = @definition.clone
172
+ @evaluator_class = nil
173
+ @hierarchy_class = nil
174
+ @hierarchy_instance = nil
175
+ @compiled = false
176
+ end
177
+ end
178
+ end
@@ -0,0 +1,35 @@
1
+ module FactoryBot
2
+ class FactoryRunner
3
+ def initialize(name, strategy, traits_and_overrides)
4
+ @name = name
5
+ @strategy = strategy
6
+
7
+ @overrides = traits_and_overrides.extract_options!
8
+ @traits = traits_and_overrides
9
+ end
10
+
11
+ def run(runner_strategy = @strategy, &block)
12
+ factory = FactoryBot::Internal.factory_by_name(@name)
13
+
14
+ factory.compile
15
+
16
+ if @traits.any?
17
+ factory = factory.with_traits(@traits)
18
+ end
19
+
20
+ instrumentation_payload = {
21
+ name: @name,
22
+ strategy: runner_strategy,
23
+ traits: @traits,
24
+ overrides: @overrides,
25
+ factory: factory
26
+ }
27
+
28
+ ActiveSupport::Notifications.instrument("factory_bot.before_run_factory", instrumentation_payload)
29
+
30
+ ActiveSupport::Notifications.instrument("factory_bot.run_factory", instrumentation_payload) do
31
+ factory.run(runner_strategy, @overrides, &block)
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,25 @@
1
+ module FactoryBot
2
+ class << self
3
+ # An Array of strings specifying locations that should be searched for
4
+ # factory definitions. By default, factory_bot will attempt to require
5
+ # "factories.rb", "factories/**/*.rb", "test/factories.rb",
6
+ # "test/factories/**.rb", "spec/factories.rb", and "spec/factories/**.rb".
7
+ attr_accessor :definition_file_paths
8
+ end
9
+
10
+ self.definition_file_paths = %w[factories test/factories spec/factories]
11
+
12
+ def self.find_definitions
13
+ absolute_definition_file_paths = definition_file_paths.map { |path| File.expand_path(path) }
14
+
15
+ absolute_definition_file_paths.uniq.each do |path|
16
+ load("#{path}.rb") if File.exist?("#{path}.rb")
17
+
18
+ if File.directory? path
19
+ Dir[File.join(path, "**", "*.rb")].sort.each do |file|
20
+ load file
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,124 @@
1
+ module FactoryBot
2
+ # @api private
3
+ module Internal
4
+ class << self
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
18
+
19
+ def configuration
20
+ @configuration ||= Configuration.new
21
+ end
22
+
23
+ def reset_configuration
24
+ @configuration = nil
25
+ end
26
+
27
+ def register_inline_sequence(sequence)
28
+ inline_sequences.push(sequence)
29
+ sequence
30
+ end
31
+
32
+ def rewind_inline_sequences
33
+ inline_sequences.each(&:rewind)
34
+ end
35
+
36
+ def register_trait(trait)
37
+ trait.names.each do |name|
38
+ traits.register(name, trait)
39
+ end
40
+ trait
41
+ end
42
+
43
+ def trait_by_name(name, klass)
44
+ traits.find(name).tap { |t| t.klass = klass }
45
+ end
46
+
47
+ def register_sequence(sequence)
48
+ sequence.names.each do |name|
49
+ sequences.register(name, sequence)
50
+ end
51
+ sequence
52
+ end
53
+
54
+ def sequence_by_name(name)
55
+ sequences.find(name)
56
+ end
57
+
58
+ def rewind_sequences
59
+ sequences.each(&:rewind)
60
+ rewind_inline_sequences
61
+ end
62
+
63
+ def rewind_sequence(*uri_parts)
64
+ fail_argument_count(0, "1+") if uri_parts.empty?
65
+
66
+ uri = build_uri(uri_parts)
67
+ sequence = Sequence.find_by_uri(uri) || fail_unregistered_sequence(uri)
68
+
69
+ sequence.rewind
70
+ end
71
+
72
+ def set_sequence(*uri_parts, value)
73
+ uri = build_uri(uri_parts) || fail_argument_count(uri_parts.size, "2+")
74
+ sequence = Sequence.find(*uri) || fail_unregistered_sequence(uri)
75
+
76
+ sequence.set_value(value)
77
+ end
78
+
79
+ def register_factory(factory)
80
+ factory.names.each do |name|
81
+ factories.register(name, factory)
82
+ end
83
+ factory
84
+ end
85
+
86
+ def factory_by_name(name)
87
+ factories.find(name)
88
+ end
89
+
90
+ def register_strategy(strategy_name, strategy_class)
91
+ strategies.register(strategy_name, strategy_class)
92
+ StrategySyntaxMethodRegistrar.new(strategy_name).define_strategy_methods
93
+ end
94
+
95
+ def strategy_by_name(name)
96
+ strategies.find(name)
97
+ end
98
+
99
+ def register_default_strategies
100
+ register_strategy(:build, FactoryBot::Strategy::Build)
101
+ register_strategy(:create, FactoryBot::Strategy::Create)
102
+ register_strategy(:attributes_for, FactoryBot::Strategy::AttributesFor)
103
+ register_strategy(:build_stubbed, FactoryBot::Strategy::Stub)
104
+ register_strategy(:null, FactoryBot::Strategy::Null)
105
+ end
106
+
107
+ private
108
+
109
+ def build_uri(...)
110
+ FactoryBot::UriManager.build_uri(...)
111
+ end
112
+
113
+ def fail_argument_count(received, expected)
114
+ fail ArgumentError,
115
+ "wrong number of arguments (given #{received}, expected #{expected})"
116
+ end
117
+
118
+ def fail_unregistered_sequence(uri)
119
+ fail KeyError,
120
+ "Sequence not registered: '#{uri}'."
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,121 @@
1
+ module FactoryBot
2
+ class Linter
3
+ def initialize(factories, strategy: :create, traits: false, verbose: false)
4
+ @factories_to_lint = factories
5
+ @factory_strategy = strategy
6
+ @traits = traits
7
+ @verbose = verbose
8
+ @invalid_factories = calculate_invalid_factories
9
+ end
10
+
11
+ def lint!
12
+ if invalid_factories.any?
13
+ raise InvalidFactoryError, error_message
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ attr_reader :factories_to_lint, :invalid_factories, :factory_strategy
20
+
21
+ def calculate_invalid_factories
22
+ factories_to_lint.each_with_object(Hash.new([])) do |factory, result|
23
+ errors = lint(factory)
24
+ result[factory] |= errors unless errors.empty?
25
+ end
26
+ end
27
+
28
+ class FactoryError
29
+ def initialize(wrapped_error, factory)
30
+ @wrapped_error = wrapped_error
31
+ @factory = factory
32
+ end
33
+
34
+ def message
35
+ message = @wrapped_error.message
36
+ "* #{location} - #{message} (#{@wrapped_error.class.name})"
37
+ end
38
+
39
+ def verbose_message
40
+ <<~MESSAGE
41
+ #{message}
42
+ #{@wrapped_error.backtrace.join("\n ")}
43
+ MESSAGE
44
+ end
45
+
46
+ def location
47
+ @factory.name
48
+ end
49
+ end
50
+
51
+ class FactoryTraitError < FactoryError
52
+ def initialize(wrapped_error, factory, trait_name)
53
+ super(wrapped_error, factory)
54
+ @trait_name = trait_name
55
+ end
56
+
57
+ def location
58
+ "#{@factory.name}+#{@trait_name}"
59
+ end
60
+ end
61
+
62
+ def lint(factory)
63
+ if @traits
64
+ lint_factory(factory) + lint_traits(factory)
65
+ else
66
+ lint_factory(factory)
67
+ end
68
+ end
69
+
70
+ def lint_factory(factory)
71
+ result = []
72
+ begin
73
+ in_transaction { FactoryBot.public_send(factory_strategy, factory.name) }
74
+ rescue => e
75
+ result |= [FactoryError.new(e, factory)]
76
+ end
77
+ result
78
+ end
79
+
80
+ def lint_traits(factory)
81
+ result = []
82
+ factory.definition.defined_traits.map(&:name).each do |trait_name|
83
+ in_transaction { FactoryBot.public_send(factory_strategy, factory.name, trait_name) }
84
+ rescue => e
85
+ result |= [FactoryTraitError.new(e, factory, trait_name)]
86
+ end
87
+ result
88
+ end
89
+
90
+ def error_message
91
+ lines = invalid_factories.map { |_factory, exceptions|
92
+ exceptions.map(&error_message_type)
93
+ }.flatten
94
+
95
+ <<~ERROR_MESSAGE.strip
96
+ The following factories are invalid:
97
+
98
+ #{lines.join("\n")}
99
+ ERROR_MESSAGE
100
+ end
101
+
102
+ def error_message_type
103
+ if @verbose
104
+ :verbose_message
105
+ else
106
+ :message
107
+ end
108
+ end
109
+
110
+ def in_transaction
111
+ if defined?(ActiveRecord::Base)
112
+ ActiveRecord::Base.transaction(joinable: false) do
113
+ yield
114
+ raise ActiveRecord::Rollback
115
+ end
116
+ else
117
+ yield
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,27 @@
1
+ module FactoryBot
2
+ # @api private
3
+ class NullFactory
4
+ attr_reader :definition
5
+
6
+ def initialize
7
+ @definition = Definition.new(:null_factory)
8
+ end
9
+
10
+ delegate :defined_traits, :callbacks, :attributes, :constructor,
11
+ :to_create, to: :definition
12
+
13
+ def compile
14
+ end
15
+
16
+ def class_name
17
+ end
18
+
19
+ def evaluator_class
20
+ FactoryBot::Evaluator
21
+ end
22
+
23
+ def hierarchy_class
24
+ FactoryBot::DefinitionHierarchy
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,20 @@
1
+ module FactoryBot
2
+ # @api private
3
+ class NullObject < ::BasicObject
4
+ def initialize(methods_to_respond_to)
5
+ @methods_to_respond_to = methods_to_respond_to.map(&:to_s)
6
+ end
7
+
8
+ def method_missing(name, *args, &block) # rubocop:disable Style/MissingRespondToMissing
9
+ if respond_to?(name)
10
+ nil
11
+ else
12
+ super
13
+ end
14
+ end
15
+
16
+ def respond_to?(method)
17
+ @methods_to_respond_to.include? method.to_s
18
+ end
19
+ end
20
+ end