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,99 @@
1
+ # factory_bot
2
+
3
+ [![Build Status][ci-image]][ci] [![Gem Version][version-image]][version]
4
+
5
+ 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.
6
+
7
+ If you want to use factory_bot with Rails, see
8
+ [factory_bot_rails](https://github.com/thoughtbot/factory_bot_rails).
9
+
10
+ Interested in the history of the project name? You can find the history [here](https://github.com/thoughtbot/factory_bot/blob/main/NAME.md)
11
+
12
+ Transitioning from factory\_girl? Check out the [upgrade guide](https://github.com/thoughtbot/factory_bot/blob/v4.9.0/UPGRADE_FROM_FACTORY_GIRL.md).
13
+
14
+ ## Documentation
15
+
16
+ See our extensive reference, guides, and cookbook in [the factory_bot book][].
17
+
18
+ For information on integrations with third party libraries, such as RSpec or
19
+ Rails, see [the factory_bot wiki][].
20
+
21
+ We also have [a detailed introductory video][], available for free on Upcase.
22
+
23
+ [a detailed introductory video]: https://upcase.com/videos/factory-bot?utm_source=github&utm_medium=open-source&utm_campaign=factory-girl
24
+ [the factory_bot book]: https://thoughtbot.github.io/factory_bot
25
+ [the factory_bot wiki]: https://github.com/thoughtbot/factory_bot/wiki
26
+
27
+ ## Install
28
+
29
+ Run:
30
+
31
+ ```ruby
32
+ bundle add factory_bot
33
+ ```
34
+
35
+ To install the gem manually from your shell, run:
36
+
37
+ ```shell
38
+ gem install factory_bot
39
+ ```
40
+
41
+ ## Supported Ruby versions
42
+
43
+ Supported Ruby versions are listed in `.github/workflows/build.yml` ([source](https://github.com/thoughtbot/factory_bot/blob/main/.github/workflows/build.yml))
44
+
45
+ ## More Information
46
+
47
+ * [Rubygems](https://rubygems.org/gems/factory_bot)
48
+ * [Stack Overflow](https://stackoverflow.com/questions/tagged/factory-bot)
49
+ * [Issues](https://github.com/thoughtbot/factory_bot/issues)
50
+ * [GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS](https://robots.thoughtbot.com/)
51
+
52
+ [GETTING_STARTED]: https://github.com/thoughtbot/factory_bot/blob/main/GETTING_STARTED.md
53
+
54
+ ## Useful Tools
55
+
56
+ * [FactoryTrace](https://github.com/djezzzl/factory_trace) - helps to find unused factories and traits.
57
+ * [ruby-lsp-factory_bot](https://github.com/donny741/ruby-lsp-factory_bot) / [ruby-lsp-rails-factory-bot](https://github.com/johansenja/ruby-lsp-rails-factory-bot) - integration with [ruby-lsp](https://github.com/Shopify/ruby-lsp) to provide intellisense
58
+
59
+ Contributing
60
+ ------------
61
+
62
+ Please see [CONTRIBUTING.md](https://github.com/thoughtbot/factory_bot/blob/main/CONTRIBUTING.md).
63
+
64
+ factory_bot was originally written by Joe Ferris and is maintained by thoughtbot.
65
+ Many improvements and bugfixes were contributed by the [open source
66
+ community](https://github.com/thoughtbot/factory_bot/graphs/contributors).
67
+
68
+ License
69
+ -------
70
+
71
+ factory_bot is Copyright © 2008 Joe Ferris and thoughtbot. It is free
72
+ software, and may be redistributed under the terms specified in the
73
+ [LICENSE] file.
74
+
75
+ [LICENSE]: https://github.com/thoughtbot/factory_bot/blob/main/LICENSE
76
+
77
+ <!-- START /templates/footer.md -->
78
+ ## About thoughtbot
79
+
80
+ ![thoughtbot](https://thoughtbot.com/thoughtbot-logo-for-readmes.svg)
81
+
82
+ This repo is maintained and funded by thoughtbot, inc.
83
+ The names and logos for thoughtbot are trademarks of thoughtbot, inc.
84
+
85
+ We love open source software!
86
+ See [our other projects][community].
87
+ We are [available for hire][hire].
88
+
89
+ [community]: https://thoughtbot.com/community?utm_source=github
90
+ [hire]: https://thoughtbot.com/hire-us?utm_source=github
91
+
92
+ <!-- END /templates/footer.md -->
93
+
94
+ [ci-image]: https://github.com/thoughtbot/factory_bot/actions/workflows/build.yml/badge.svg?branch=main
95
+ [ci]: https://github.com/thoughtbot/factory_bot/actions?query=workflow%3ABuild+branch%3Amain
96
+ [version-image]: https://badge.fury.io/rb/factory_bot.svg
97
+ [version]: https://badge.fury.io/rb/factory_bot
98
+ [hound-badge-image]: https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg
99
+ [hound]: https://houndci.com
@@ -0,0 +1,18 @@
1
+ module FactoryBot
2
+ class << self
3
+ attr_accessor :aliases
4
+ end
5
+
6
+ self.aliases = [
7
+ [/(.+)_id/, '\1'],
8
+ [/(.*)/, '\1_id']
9
+ ]
10
+
11
+ def self.aliases_for(attribute)
12
+ aliases.map { |(pattern, replace)|
13
+ if pattern.match?(attribute)
14
+ attribute.to_s.sub(pattern, replace).to_sym
15
+ end
16
+ }.compact << attribute
17
+ end
18
+ end
@@ -0,0 +1,27 @@
1
+ module FactoryBot
2
+ class Attribute
3
+ # @api private
4
+ class Association < Attribute
5
+ attr_reader :factory
6
+
7
+ def initialize(name, factory, overrides)
8
+ super(name, false)
9
+ @factory = factory
10
+ @overrides = overrides
11
+ end
12
+
13
+ def to_proc
14
+ factory = @factory
15
+ overrides = @overrides
16
+ traits_and_overrides = [factory, overrides].flatten
17
+ factory_name = traits_and_overrides.shift
18
+
19
+ -> { association(factory_name, *traits_and_overrides) }
20
+ end
21
+
22
+ def association?
23
+ true
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,25 @@
1
+ module FactoryBot
2
+ class Attribute
3
+ # @api private
4
+ class Dynamic < Attribute
5
+ def initialize(name, ignored, block)
6
+ super(name, ignored)
7
+ @block = block
8
+ end
9
+
10
+ def to_proc
11
+ block = @block
12
+
13
+ -> {
14
+ value = case block.arity
15
+ when 1, -1, -2 then instance_exec(self, &block)
16
+ else instance_exec(&block)
17
+ end
18
+ raise SequenceAbuseError if FactoryBot::Sequence === value
19
+
20
+ value
21
+ }
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,16 @@
1
+ module FactoryBot
2
+ class Attribute
3
+ # @api private
4
+ class Sequence < Attribute
5
+ def initialize(name, sequence, ignored)
6
+ super(name, ignored)
7
+ @sequence = sequence
8
+ end
9
+
10
+ def to_proc
11
+ sequence = @sequence
12
+ -> { FactoryBot.generate(sequence) }
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,27 @@
1
+ require "factory_bot/attribute/dynamic"
2
+ require "factory_bot/attribute/association"
3
+ require "factory_bot/attribute/sequence"
4
+
5
+ module FactoryBot
6
+ # @api private
7
+ class Attribute
8
+ attr_reader :name, :ignored
9
+
10
+ def initialize(name, ignored)
11
+ @name = name.to_sym
12
+ @ignored = ignored
13
+ end
14
+
15
+ def to_proc
16
+ -> {}
17
+ end
18
+
19
+ def association?
20
+ false
21
+ end
22
+
23
+ def alias_for?(attr)
24
+ FactoryBot.aliases_for(attr).include?(name)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,168 @@
1
+ module FactoryBot
2
+ # @api private
3
+ class AttributeAssigner
4
+ def initialize(evaluator, build_class, &instance_builder)
5
+ @build_class = build_class
6
+ @instance_builder = instance_builder
7
+ @evaluator = evaluator
8
+ @attribute_list = evaluator.class.attribute_list
9
+ @attribute_names_assigned = []
10
+ end
11
+
12
+ # constructs an object-based factory product
13
+ def object
14
+ @evaluator.instance = build_class_instance
15
+ build_class_instance.tap do |instance|
16
+ attributes_to_set_on_instance.each do |attribute|
17
+ instance.public_send(:"#{attribute}=", get(attribute))
18
+ @attribute_names_assigned << attribute
19
+ end
20
+ end
21
+ end
22
+
23
+ # constructs a Hash-based factory product
24
+ def hash
25
+ @evaluator.instance = build_hash
26
+
27
+ attributes_to_set_on_hash.each_with_object({}) do |attribute, result|
28
+ result[attribute] = get(attribute)
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ # Track evaluation of methods on the evaluator to prevent the duplicate
35
+ # assignment of attributes accessed and via `initialize_with` syntax
36
+ def method_tracking_evaluator
37
+ @method_tracking_evaluator ||= Decorator::AttributeHash.new(
38
+ decorated_evaluator,
39
+ attribute_names_to_assign
40
+ )
41
+ end
42
+
43
+ def decorated_evaluator
44
+ Decorator::NewConstructor.new(
45
+ Decorator::InvocationTracker.new(@evaluator),
46
+ @build_class
47
+ )
48
+ end
49
+
50
+ def methods_invoked_on_evaluator
51
+ method_tracking_evaluator.__invoked_methods__
52
+ end
53
+
54
+ def build_class_instance
55
+ @build_class_instance ||= method_tracking_evaluator.instance_exec(&@instance_builder)
56
+ end
57
+
58
+ def build_hash
59
+ @build_hash ||= NullObject.new(hash_instance_methods_to_respond_to)
60
+ end
61
+
62
+ def get(attribute_name)
63
+ @evaluator.send(attribute_name)
64
+ end
65
+
66
+ def attributes_to_set_on_instance
67
+ (attribute_names_to_assign - @attribute_names_assigned - methods_invoked_on_evaluator).uniq
68
+ end
69
+
70
+ def attributes_to_set_on_hash
71
+ attribute_names_to_assign - association_names
72
+ end
73
+
74
+ # Builds a list of attributes names that should be assigned to the factory product
75
+ def attribute_names_to_assign
76
+ @attribute_names_to_assign ||= begin
77
+ # start a list of candidates containing non-transient attributes and overrides
78
+ assignment_candidates = non_ignored_attribute_names + override_names
79
+ # then remove any transient attributes (potentially reintroduced by the overrides),
80
+ # and remove ignorable aliased attributes from the candidate list
81
+ assignment_candidates - ignored_attribute_names - attribute_names_overriden_by_alias
82
+ end
83
+ end
84
+
85
+ def non_ignored_attribute_names
86
+ @attribute_list.non_ignored.names
87
+ end
88
+
89
+ def ignored_attribute_names
90
+ @attribute_list.ignored.names
91
+ end
92
+
93
+ def association_names
94
+ @attribute_list.associations.names
95
+ end
96
+
97
+ def override_names
98
+ @evaluator.__override_names__
99
+ end
100
+
101
+ def attribute_names
102
+ @attribute_list.names
103
+ end
104
+
105
+ def hash_instance_methods_to_respond_to
106
+ attribute_names + override_names + @build_class.instance_methods
107
+ end
108
+
109
+ # Builds a list of attribute names which are slated to be interrupted by an override.
110
+ def attribute_names_overriden_by_alias
111
+ @attribute_list
112
+ .non_ignored
113
+ .flat_map { |attribute|
114
+ override_names.map do |override|
115
+ attribute.name if ignorable_alias?(attribute, override)
116
+ end
117
+ }
118
+ .compact
119
+ end
120
+
121
+ # Is the attribute an ignorable alias of the override?
122
+ # An attribute is ignorable when it is an alias of the override AND it is
123
+ # either interrupting an assocciation OR is not the name of another attribute
124
+ #
125
+ # @note An "alias" is currently an overloaded term for two distinct cases:
126
+ # (1) attributes which are aliases and reference the same value
127
+ # (2) a logical grouping of a foreign key and an associated object
128
+ def ignorable_alias?(attribute, override)
129
+ return false unless attribute.alias_for?(override)
130
+
131
+ # The attribute alias should be ignored when the override interrupts an association
132
+ return true if override_interrupts_association?(attribute, override)
133
+
134
+ # Remaining aliases should be ignored when the override does not match a declared attribute.
135
+ # An override which is an alias to a declared attribute should not interrupt the aliased
136
+ # attribute and interrupt only the attribute with a matching name. This workaround allows a
137
+ # factory to declare both <attribute> and <attribute>_id as separate and distinct attributes.
138
+ !override_matches_declared_attribute?(override)
139
+ end
140
+
141
+ # Does this override interrupt an association?
142
+ # When true, this indicates the aliased attribute is related to a declared association and the
143
+ # override does not match the attribute name.
144
+ #
145
+ # @note Association overrides should take precedence over a declared foreign key attribute.
146
+ #
147
+ # @note An override may interrupt an association by providing the associated object or
148
+ # by providing the foreign key.
149
+ #
150
+ # @param [FactoryBot::Attribute] aliased_attribute
151
+ # @param [Symbol] override name of an override which is an alias to the attribute name
152
+ def override_interrupts_association?(aliased_attribute, override)
153
+ (aliased_attribute.association? || association_names.include?(override)) &&
154
+ aliased_attribute.name != override
155
+ end
156
+
157
+ # Does this override match the name of any declared attribute?
158
+ #
159
+ # @note Checking against the names of all attributes, resolves any issues with having both
160
+ # <attribute> and <attribute>_id in the same factory. This also takes into account ignored
161
+ # attributes that should not be assigned (aka transient attributes)
162
+ #
163
+ # @param [Symbol] override the name of an override
164
+ def override_matches_declared_attribute?(override)
165
+ attribute_names.include?(override)
166
+ end
167
+ end
168
+ end
@@ -0,0 +1,68 @@
1
+ module FactoryBot
2
+ # @api private
3
+ class AttributeList
4
+ include Enumerable
5
+
6
+ def initialize(name = nil, attributes = [])
7
+ @name = name
8
+ @attributes = attributes
9
+ end
10
+
11
+ def define_attribute(attribute)
12
+ ensure_attribute_not_self_referencing! attribute
13
+ ensure_attribute_not_defined! attribute
14
+
15
+ add_attribute attribute
16
+ end
17
+
18
+ def each(&block)
19
+ @attributes.each(&block)
20
+ end
21
+
22
+ def names
23
+ map(&:name)
24
+ end
25
+
26
+ def associations
27
+ AttributeList.new(@name, select(&:association?))
28
+ end
29
+
30
+ def ignored
31
+ AttributeList.new(@name, select(&:ignored))
32
+ end
33
+
34
+ def non_ignored
35
+ AttributeList.new(@name, reject(&:ignored))
36
+ end
37
+
38
+ def apply_attributes(attributes_to_apply)
39
+ attributes_to_apply.each { |attribute| add_attribute(attribute) }
40
+ end
41
+
42
+ private
43
+
44
+ def add_attribute(attribute)
45
+ @attributes << attribute
46
+ attribute
47
+ end
48
+
49
+ def ensure_attribute_not_defined!(attribute)
50
+ if attribute_defined?(attribute.name)
51
+ raise AttributeDefinitionError, "Attribute already defined: #{attribute.name}"
52
+ end
53
+ end
54
+
55
+ def ensure_attribute_not_self_referencing!(attribute)
56
+ if attribute.respond_to?(:factory) && attribute.factory == @name
57
+ message = "Self-referencing association '#{attribute.name}' in '#{attribute.factory}'"
58
+ raise AssociationDefinitionError, message
59
+ end
60
+ end
61
+
62
+ def attribute_defined?(attribute_name)
63
+ @attributes.any? do |attribute|
64
+ attribute.name == attribute_name
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,33 @@
1
+ module FactoryBot
2
+ class Callback
3
+ attr_reader :name
4
+
5
+ def initialize(name, block)
6
+ @name = name.to_sym
7
+ @block = block
8
+ end
9
+
10
+ def run(instance, evaluator)
11
+ case block.arity
12
+ when 1, -1, -2 then syntax_runner.instance_exec(instance, &block)
13
+ when 2 then syntax_runner.instance_exec(instance, evaluator, &block)
14
+ else syntax_runner.instance_exec(&block)
15
+ end
16
+ end
17
+
18
+ def ==(other)
19
+ name == other.name &&
20
+ block == other.block
21
+ end
22
+
23
+ protected
24
+
25
+ attr_reader :block
26
+
27
+ private
28
+
29
+ def syntax_runner
30
+ @syntax_runner ||= SyntaxRunner.new
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,39 @@
1
+ module FactoryBot
2
+ # @api private
3
+ class CallbacksObserver
4
+ def initialize(callbacks, evaluator)
5
+ @callbacks = callbacks
6
+ @evaluator = evaluator
7
+ @completed = []
8
+ end
9
+
10
+ def update(name, result_instance)
11
+ callbacks_by_name(name).each do |callback|
12
+ if !completed?(result_instance, callback)
13
+ callback.run(result_instance, @evaluator)
14
+ record_completion!(result_instance, callback)
15
+ end
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def callbacks_by_name(name)
22
+ @callbacks.select { |callback| callback.name == name }
23
+ end
24
+
25
+ def completed?(instance, callback)
26
+ key = completion_key_for(instance, callback)
27
+ @completed.include?(key)
28
+ end
29
+
30
+ def record_completion!(instance, callback)
31
+ key = completion_key_for(instance, callback)
32
+ @completed << key
33
+ end
34
+
35
+ def completion_key_for(instance, callback)
36
+ "#{instance.object_id}-#{callback.object_id}"
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,33 @@
1
+ module FactoryBot
2
+ # @api private
3
+ class Configuration
4
+ attr_reader(
5
+ :callback_names,
6
+ :factories,
7
+ :inline_sequences,
8
+ :sequences,
9
+ :strategies,
10
+ :traits
11
+ )
12
+
13
+ def initialize
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
+ @callback_names = Set.new
19
+ @definition = Definition.new(:configuration)
20
+ @inline_sequences = []
21
+
22
+ to_create(&:save!)
23
+ initialize_with { new }
24
+ end
25
+
26
+ delegate :to_create, :skip_create, :constructor, :before, :after,
27
+ :callback, :callbacks, to: :@definition
28
+
29
+ def initialize_with(&block)
30
+ @definition.define_constructor(&block)
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,58 @@
1
+ module FactoryBot
2
+ class Declaration
3
+ # @api private
4
+ class Association < Declaration
5
+ def initialize(name, *options)
6
+ super(name, false)
7
+ @options = options.dup
8
+ @overrides = options.extract_options!
9
+ @factory_name = @overrides.delete(:factory) || name
10
+ @traits = options
11
+ end
12
+
13
+ def ==(other)
14
+ self.class == other.class &&
15
+ name == other.name &&
16
+ options == other.options
17
+ end
18
+
19
+ protected
20
+
21
+ attr_reader :options
22
+
23
+ private
24
+
25
+ attr_reader :factory_name, :overrides, :traits
26
+
27
+ def build
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
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,28 @@
1
+ module FactoryBot
2
+ class Declaration
3
+ # @api private
4
+ class Dynamic < Declaration
5
+ def initialize(name, ignored = false, block = nil)
6
+ super(name, ignored)
7
+ @block = block
8
+ end
9
+
10
+ def ==(other)
11
+ self.class == other.class &&
12
+ name == other.name &&
13
+ ignored == other.ignored &&
14
+ block == other.block
15
+ end
16
+
17
+ protected
18
+
19
+ attr_reader :block
20
+
21
+ private
22
+
23
+ def build
24
+ [Attribute::Dynamic.new(name, @ignored, @block)]
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,38 @@
1
+ module FactoryBot
2
+ class Declaration
3
+ # @api private
4
+ class Implicit < Declaration
5
+ def initialize(name, factory = nil, ignored = false)
6
+ super(name, ignored)
7
+ @factory = factory
8
+ end
9
+
10
+ def ==(other)
11
+ self.class == other.class &&
12
+ name == other.name &&
13
+ factory == other.factory &&
14
+ ignored == other.ignored
15
+ end
16
+
17
+ protected
18
+
19
+ attr_reader :factory
20
+
21
+ private
22
+
23
+ def build
24
+ if FactoryBot.factories.registered?(name)
25
+ [Attribute::Association.new(name, name, {})]
26
+ elsif FactoryBot::Internal.sequences.registered?(name)
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
31
+ else
32
+ @factory.inherit_traits([name])
33
+ []
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end