factory_bot 4.11.0 → 5.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.
- checksums.yaml +4 -4
 - data/.yardopts +6 -0
 - data/GETTING_STARTED.md +121 -37
 - data/LICENSE +1 -1
 - data/NEWS.md +351 -0
 - data/README.md +21 -25
 - data/lib/factory_bot/aliases.rb +1 -1
 - data/lib/factory_bot/attribute/dynamic.rb +1 -0
 - data/lib/factory_bot/attribute.rb +4 -39
 - data/lib/factory_bot/attribute_assigner.rb +21 -6
 - data/lib/factory_bot/attribute_list.rb +2 -1
 - data/lib/factory_bot/callback.rb +3 -2
 - data/lib/factory_bot/configuration.rb +16 -20
 - 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.rb +4 -4
 - data/lib/factory_bot/declaration_list.rb +1 -1
 - data/lib/factory_bot/decorator/attribute_hash.rb +1 -1
 - data/lib/factory_bot/decorator/invocation_tracker.rb +1 -1
 - data/lib/factory_bot/decorator.rb +5 -1
 - data/lib/factory_bot/definition.rb +10 -7
 - data/lib/factory_bot/definition_hierarchy.rb +1 -11
 - data/lib/factory_bot/definition_proxy.rb +59 -62
 - data/lib/factory_bot/errors.rb +7 -4
 - data/lib/factory_bot/evaluation.rb +1 -1
 - data/lib/factory_bot/evaluator.rb +5 -5
 - data/lib/factory_bot/factory.rb +8 -8
 - data/lib/factory_bot/factory_runner.rb +3 -3
 - data/lib/factory_bot/find_definitions.rb +1 -1
 - data/lib/factory_bot/internal.rb +104 -0
 - data/lib/factory_bot/linter.rb +36 -19
 - data/lib/factory_bot/null_factory.rb +4 -1
 - data/lib/factory_bot/null_object.rb +2 -2
 - data/lib/factory_bot/registry.rb +15 -6
 - data/lib/factory_bot/reload.rb +3 -3
 - data/lib/factory_bot/sequence.rb +0 -1
 - data/lib/factory_bot/strategy/null.rb +2 -4
 - data/lib/factory_bot/strategy/stub.rb +32 -31
 - 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/default.rb +12 -24
 - data/lib/factory_bot/syntax/methods.rb +32 -9
 - data/lib/factory_bot/syntax.rb +2 -2
 - data/lib/factory_bot/trait.rb +6 -3
 - data/lib/factory_bot/version.rb +1 -1
 - data/lib/factory_bot.rb +103 -138
 - metadata +73 -32
 - data/NEWS +0 -303
 - 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
 
| 
         @@ -1,6 +1,19 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module FactoryBot
         
     | 
| 
       2 
2 
     | 
    
         
             
              class DefinitionProxy
         
     | 
| 
       3 
     | 
    
         
            -
                UNPROXIED_METHODS = %w( 
     | 
| 
      
 3 
     | 
    
         
            +
                UNPROXIED_METHODS = %w(
         
     | 
| 
      
 4 
     | 
    
         
            +
                  __send__
         
     | 
| 
      
 5 
     | 
    
         
            +
                  __id__
         
     | 
| 
      
 6 
     | 
    
         
            +
                  nil?
         
     | 
| 
      
 7 
     | 
    
         
            +
                  send
         
     | 
| 
      
 8 
     | 
    
         
            +
                  object_id
         
     | 
| 
      
 9 
     | 
    
         
            +
                  extend
         
     | 
| 
      
 10 
     | 
    
         
            +
                  instance_eval
         
     | 
| 
      
 11 
     | 
    
         
            +
                  initialize
         
     | 
| 
      
 12 
     | 
    
         
            +
                  block_given?
         
     | 
| 
      
 13 
     | 
    
         
            +
                  raise
         
     | 
| 
      
 14 
     | 
    
         
            +
                  caller
         
     | 
| 
      
 15 
     | 
    
         
            +
                  method
         
     | 
| 
      
 16 
     | 
    
         
            +
                ).freeze
         
     | 
| 
       4 
17 
     | 
    
         | 
| 
       5 
18 
     | 
    
         
             
                (instance_methods + private_instance_methods).each do |method|
         
     | 
| 
       6 
19 
     | 
    
         
             
                  undef_method(method) unless UNPROXIED_METHODS.include?(method.to_s)
         
     | 
| 
         @@ -21,43 +34,21 @@ module FactoryBot 
     | 
|
| 
       21 
34 
     | 
    
         
             
                  raise FactoryBot::MethodDefinitionError, message
         
     | 
| 
       22 
35 
     | 
    
         
             
                end
         
     | 
| 
       23 
36 
     | 
    
         | 
| 
       24 
     | 
    
         
            -
                # Adds an attribute  
     | 
| 
       25 
     | 
    
         
            -
                #  
     | 
| 
       26 
     | 
    
         
            -
                #
         
     | 
| 
       27 
     | 
    
         
            -
                #  
     | 
| 
       28 
     | 
    
         
            -
                # called with a block, the attribute will be generated "lazily," whenever an
         
     | 
| 
       29 
     | 
    
         
            -
                # instance is generated. Lazy attribute blocks will not be called if that
         
     | 
| 
      
 37 
     | 
    
         
            +
                # Adds an attribute to the factory.
         
     | 
| 
      
 38 
     | 
    
         
            +
                # The attribute value will be generated "lazily"
         
     | 
| 
      
 39 
     | 
    
         
            +
                # by calling the block whenever an instance is generated.
         
     | 
| 
      
 40 
     | 
    
         
            +
                # The block will not be called if the
         
     | 
| 
       30 
41 
     | 
    
         
             
                # attribute is overridden for a specific instance.
         
     | 
| 
       31 
42 
     | 
    
         
             
                #
         
     | 
| 
       32 
     | 
    
         
            -
                # When defining lazy attributes, an instance of FactoryBot::Strategy will
         
     | 
| 
       33 
     | 
    
         
            -
                # be yielded, allowing associations to be built using the correct build
         
     | 
| 
       34 
     | 
    
         
            -
                # strategy.
         
     | 
| 
       35 
     | 
    
         
            -
                #
         
     | 
| 
       36 
43 
     | 
    
         
             
                # Arguments:
         
     | 
| 
       37 
44 
     | 
    
         
             
                # * name: +Symbol+ or +String+
         
     | 
| 
       38 
45 
     | 
    
         
             
                #   The name of this attribute. This will be assigned using "name=" for
         
     | 
| 
       39 
46 
     | 
    
         
             
                #   generated instances.
         
     | 
| 
       40 
     | 
    
         
            -
                 
     | 
| 
       41 
     | 
    
         
            -
             
     | 
| 
       42 
     | 
    
         
            -
                def add_attribute(name, value = nil, &block)
         
     | 
| 
       43 
     | 
    
         
            -
                  raise AttributeDefinitionError, 'Both value and block given' if value && block_given?
         
     | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
       45 
     | 
    
         
            -
                  declaration = if block_given?
         
     | 
| 
       46 
     | 
    
         
            -
                    Declaration::Dynamic.new(name, @ignore, block)
         
     | 
| 
       47 
     | 
    
         
            -
                  else
         
     | 
| 
       48 
     | 
    
         
            -
                    warn_static_attribute_deprecation(name, value)
         
     | 
| 
       49 
     | 
    
         
            -
                    Declaration::Static.new(name, value, @ignore)
         
     | 
| 
       50 
     | 
    
         
            -
                  end
         
     | 
| 
       51 
     | 
    
         
            -
             
     | 
| 
      
 47 
     | 
    
         
            +
                def add_attribute(name, &block)
         
     | 
| 
      
 48 
     | 
    
         
            +
                  declaration = Declaration::Dynamic.new(name, @ignore, block)
         
     | 
| 
       52 
49 
     | 
    
         
             
                  @definition.declare_attribute(declaration)
         
     | 
| 
       53 
50 
     | 
    
         
             
                end
         
     | 
| 
       54 
51 
     | 
    
         | 
| 
       55 
     | 
    
         
            -
                def ignore(&block)
         
     | 
| 
       56 
     | 
    
         
            -
                  ActiveSupport::Deprecation.warn "`#ignore` is deprecated and will be "\
         
     | 
| 
       57 
     | 
    
         
            -
                    "removed in 5.0. Please use `#transient` instead."
         
     | 
| 
       58 
     | 
    
         
            -
                  transient(&block)
         
     | 
| 
       59 
     | 
    
         
            -
                end
         
     | 
| 
       60 
     | 
    
         
            -
             
     | 
| 
       61 
52 
     | 
    
         
             
                def transient(&block)
         
     | 
| 
       62 
53 
     | 
    
         
             
                  proxy = DefinitionProxy.new(@definition, true)
         
     | 
| 
       63 
54 
     | 
    
         
             
                  proxy.instance_eval(&block)
         
     | 
| 
         @@ -67,40 +58,48 @@ module FactoryBot 
     | 
|
| 
       67 
58 
     | 
    
         
             
                # attribute, so that:
         
     | 
| 
       68 
59 
     | 
    
         
             
                #
         
     | 
| 
       69 
60 
     | 
    
         
             
                #   factory :user do
         
     | 
| 
       70 
     | 
    
         
            -
                #     name 'Billy Idol'
         
     | 
| 
      
 61 
     | 
    
         
            +
                #     name { 'Billy Idol' }
         
     | 
| 
       71 
62 
     | 
    
         
             
                #   end
         
     | 
| 
       72 
63 
     | 
    
         
             
                #
         
     | 
| 
       73 
64 
     | 
    
         
             
                # and:
         
     | 
| 
       74 
65 
     | 
    
         
             
                #
         
     | 
| 
       75 
66 
     | 
    
         
             
                #   factory :user do
         
     | 
| 
       76 
     | 
    
         
            -
                #     add_attribute 
     | 
| 
      
 67 
     | 
    
         
            +
                #     add_attribute(:name) { 'Billy Idol' }
         
     | 
| 
       77 
68 
     | 
    
         
             
                #   end
         
     | 
| 
       78 
69 
     | 
    
         
             
                #
         
     | 
| 
       79 
70 
     | 
    
         
             
                # are equivalent.
         
     | 
| 
       80 
71 
     | 
    
         
             
                #
         
     | 
| 
       81 
     | 
    
         
            -
                # If no argument or block is given, factory_bot will look for  
     | 
| 
       82 
     | 
    
         
            -
                #  
     | 
| 
      
 72 
     | 
    
         
            +
                # If no argument or block is given, factory_bot will first look for an
         
     | 
| 
      
 73 
     | 
    
         
            +
                # association, then for a sequence, and finally for a trait with the same
         
     | 
| 
      
 74 
     | 
    
         
            +
                # name. This means that given an "admin" trait, an "email" sequence, and an
         
     | 
| 
      
 75 
     | 
    
         
            +
                # "account" factory:
         
     | 
| 
       83 
76 
     | 
    
         
             
                #
         
     | 
| 
       84 
     | 
    
         
            -
                #   factory :user do
         
     | 
| 
       85 
     | 
    
         
            -
                #     email {  
     | 
| 
      
 77 
     | 
    
         
            +
                #   factory :user, traits: [:admin] do
         
     | 
| 
      
 78 
     | 
    
         
            +
                #     email { generate(:email) }
         
     | 
| 
       86 
79 
     | 
    
         
             
                #     association :account
         
     | 
| 
       87 
80 
     | 
    
         
             
                #   end
         
     | 
| 
       88 
81 
     | 
    
         
             
                #
         
     | 
| 
       89 
82 
     | 
    
         
             
                # and:
         
     | 
| 
       90 
83 
     | 
    
         
             
                #
         
     | 
| 
       91 
84 
     | 
    
         
             
                #   factory :user do
         
     | 
| 
      
 85 
     | 
    
         
            +
                #     admin
         
     | 
| 
       92 
86 
     | 
    
         
             
                #     email
         
     | 
| 
       93 
87 
     | 
    
         
             
                #     account
         
     | 
| 
       94 
88 
     | 
    
         
             
                #   end
         
     | 
| 
       95 
89 
     | 
    
         
             
                #
         
     | 
| 
       96 
90 
     | 
    
         
             
                # are equivalent.
         
     | 
| 
       97 
     | 
    
         
            -
                def method_missing(name, *args, &block)
         
     | 
| 
       98 
     | 
    
         
            -
                   
     | 
| 
       99 
     | 
    
         
            -
             
     | 
| 
       100 
     | 
    
         
            -
                   
     | 
| 
       101 
     | 
    
         
            -
                     
     | 
| 
      
 91 
     | 
    
         
            +
                def method_missing(name, *args, &block) # rubocop:disable Style/MissingRespondToMissing, Style/MethodMissingSuper
         
     | 
| 
      
 92 
     | 
    
         
            +
                  association_options = args.first
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
                  if association_options.nil?
         
     | 
| 
      
 95 
     | 
    
         
            +
                    __declare_attribute__(name, block)
         
     | 
| 
      
 96 
     | 
    
         
            +
                  elsif __valid_association_options?(association_options)
         
     | 
| 
      
 97 
     | 
    
         
            +
                    association(name, association_options)
         
     | 
| 
       102 
98 
     | 
    
         
             
                  else
         
     | 
| 
       103 
     | 
    
         
            -
                     
     | 
| 
      
 99 
     | 
    
         
            +
                    raise NoMethodError.new(<<~MSG)
         
     | 
| 
      
 100 
     | 
    
         
            +
                      undefined method '#{name}' in '#{@definition.name}' factory
         
     | 
| 
      
 101 
     | 
    
         
            +
                      Did you mean? '#{name} { #{association_options.inspect} }'
         
     | 
| 
      
 102 
     | 
    
         
            +
                    MSG
         
     | 
| 
       104 
103 
     | 
    
         
             
                  end
         
     | 
| 
       105 
104 
     | 
    
         
             
                end
         
     | 
| 
       106 
105 
     | 
    
         | 
| 
         @@ -122,6 +121,7 @@ module FactoryBot 
     | 
|
| 
       122 
121 
     | 
    
         
             
                # Except that no globally available sequence will be defined.
         
     | 
| 
       123 
122 
     | 
    
         
             
                def sequence(name, *args, &block)
         
     | 
| 
       124 
123 
     | 
    
         
             
                  sequence = Sequence.new(name, *args, &block)
         
     | 
| 
      
 124 
     | 
    
         
            +
                  FactoryBot::Internal.register_inline_sequence(sequence)
         
     | 
| 
       125 
125 
     | 
    
         
             
                  add_attribute(name) { increment_sequence(sequence) }
         
     | 
| 
       126 
126 
     | 
    
         
             
                end
         
     | 
| 
       127 
127 
     | 
    
         | 
| 
         @@ -149,7 +149,15 @@ module FactoryBot 
     | 
|
| 
       149 
149 
     | 
    
         
             
                #    name of the factory. For example, a "user" association will by
         
     | 
| 
       150 
150 
     | 
    
         
             
                #    default use the "user" factory.
         
     | 
| 
       151 
151 
     | 
    
         
             
                def association(name, *options)
         
     | 
| 
       152 
     | 
    
         
            -
                   
     | 
| 
      
 152 
     | 
    
         
            +
                  if block_given?
         
     | 
| 
      
 153 
     | 
    
         
            +
                    raise AssociationDefinitionError.new(
         
     | 
| 
      
 154 
     | 
    
         
            +
                      "Unexpected block passed to '#{name}' association "\
         
     | 
| 
      
 155 
     | 
    
         
            +
                      "in '#{@definition.name}' factory",
         
     | 
| 
      
 156 
     | 
    
         
            +
                    )
         
     | 
| 
      
 157 
     | 
    
         
            +
                  else
         
     | 
| 
      
 158 
     | 
    
         
            +
                    declaration = Declaration::Association.new(name, *options)
         
     | 
| 
      
 159 
     | 
    
         
            +
                    @definition.declare_attribute(declaration)
         
     | 
| 
      
 160 
     | 
    
         
            +
                  end
         
     | 
| 
       153 
161 
     | 
    
         
             
                end
         
     | 
| 
       154 
162 
     | 
    
         | 
| 
       155 
163 
     | 
    
         
             
                def to_create(&block)
         
     | 
| 
         @@ -174,28 +182,17 @@ module FactoryBot 
     | 
|
| 
       174 
182 
     | 
    
         | 
| 
       175 
183 
     | 
    
         
             
                private
         
     | 
| 
       176 
184 
     | 
    
         | 
| 
       177 
     | 
    
         
            -
                def  
     | 
| 
       178 
     | 
    
         
            -
                   
     | 
| 
       179 
     | 
    
         
            -
             
     | 
| 
       180 
     | 
    
         
            -
             
     | 
| 
       181 
     | 
    
         
            -
             
     | 
| 
      
 185 
     | 
    
         
            +
                def __declare_attribute__(name, block)
         
     | 
| 
      
 186 
     | 
    
         
            +
                  if block.nil?
         
     | 
| 
      
 187 
     | 
    
         
            +
                    declaration = Declaration::Implicit.new(name, @definition, @ignore)
         
     | 
| 
      
 188 
     | 
    
         
            +
                    @definition.declare_attribute(declaration)
         
     | 
| 
      
 189 
     | 
    
         
            +
                  else
         
     | 
| 
      
 190 
     | 
    
         
            +
                    add_attribute(name, &block)
         
     | 
| 
       182 
191 
     | 
    
         
             
                  end
         
     | 
| 
      
 192 
     | 
    
         
            +
                end
         
     | 
| 
       183 
193 
     | 
    
         | 
| 
       184 
     | 
    
         
            -
             
     | 
| 
       185 
     | 
    
         
            -
             
     | 
| 
       186 
     | 
    
         
            -
            attributes instead by wrapping the attribute value in a block:
         
     | 
| 
       187 
     | 
    
         
            -
             
     | 
| 
       188 
     | 
    
         
            -
            #{name} { #{value.inspect} }
         
     | 
| 
       189 
     | 
    
         
            -
             
     | 
| 
       190 
     | 
    
         
            -
            To automatically update from static attributes to dynamic ones,
         
     | 
| 
       191 
     | 
    
         
            -
            install rubocop-rspec and run:
         
     | 
| 
       192 
     | 
    
         
            -
             
     | 
| 
       193 
     | 
    
         
            -
            rubocop \\
         
     | 
| 
       194 
     | 
    
         
            -
              --require rubocop-rspec \\
         
     | 
| 
       195 
     | 
    
         
            -
              --only FactoryBot/AttributeDefinedStatically \\
         
     | 
| 
       196 
     | 
    
         
            -
              --auto-correct
         
     | 
| 
       197 
     | 
    
         
            -
             
     | 
| 
       198 
     | 
    
         
            -
                  MSG
         
     | 
| 
      
 194 
     | 
    
         
            +
                def __valid_association_options?(options)
         
     | 
| 
      
 195 
     | 
    
         
            +
                  options.respond_to?(:has_key?) && options.has_key?(:factory)
         
     | 
| 
       199 
196 
     | 
    
         
             
                end
         
     | 
| 
       200 
197 
     | 
    
         
             
              end
         
     | 
| 
       201 
198 
     | 
    
         
             
            end
         
     | 
    
        data/lib/factory_bot/errors.rb
    CHANGED
    
    | 
         @@ -2,6 +2,9 @@ module FactoryBot 
     | 
|
| 
       2 
2 
     | 
    
         
             
              # Raised when a factory is defined that attempts to instantiate itself.
         
     | 
| 
       3 
3 
     | 
    
         
             
              class AssociationDefinitionError < RuntimeError; end
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
      
 5 
     | 
    
         
            +
              # Raised when a trait is defined that references itself.
         
     | 
| 
      
 6 
     | 
    
         
            +
              class TraitDefinitionError < RuntimeError; end
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
       5 
8 
     | 
    
         
             
              # Raised when a callback is defined that has an invalid name
         
     | 
| 
       6 
9 
     | 
    
         
             
              class InvalidCallbackNameError < RuntimeError; end
         
     | 
| 
       7 
10 
     | 
    
         | 
| 
         @@ -11,12 +14,12 @@ module FactoryBot 
     | 
|
| 
       11 
14 
     | 
    
         
             
              # Raised when attempting to register a sequence from a dynamic attribute block
         
     | 
| 
       12 
15 
     | 
    
         
             
              class SequenceAbuseError < RuntimeError; end
         
     | 
| 
       13 
16 
     | 
    
         | 
| 
       14 
     | 
    
         
            -
              # Raised when defining an  
     | 
| 
       15 
     | 
    
         
            -
              # * Defining an attribute which has a name ending in "="
         
     | 
| 
       16 
     | 
    
         
            -
              # * Defining an attribute with both a static and lazy value
         
     | 
| 
       17 
     | 
    
         
            -
              # * Defining an attribute twice in the same factory
         
     | 
| 
      
 17 
     | 
    
         
            +
              # Raised when defining an attribute twice in the same factory
         
     | 
| 
       18 
18 
     | 
    
         
             
              class AttributeDefinitionError < RuntimeError; end
         
     | 
| 
       19 
19 
     | 
    
         | 
| 
      
 20 
     | 
    
         
            +
              # Raised when attempting to pass a block to an association definition
         
     | 
| 
      
 21 
     | 
    
         
            +
              class AssociationDefinitionError < RuntimeError; end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
       20 
23 
     | 
    
         
             
              # Raised when a method is defined in a factory or trait with arguments
         
     | 
| 
       21 
24 
     | 
    
         
             
              class MethodDefinitionError < RuntimeError; end
         
     | 
| 
       22 
25 
     | 
    
         | 
| 
         @@ -1,5 +1,5 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require  
     | 
| 
       2 
     | 
    
         
            -
            require  
     | 
| 
      
 1 
     | 
    
         
            +
            require "active_support/core_ext/hash/except"
         
     | 
| 
      
 2 
     | 
    
         
            +
            require "active_support/core_ext/class/attribute"
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
4 
     | 
    
         
             
            module FactoryBot
         
     | 
| 
       5 
5 
     | 
    
         
             
              # @api private
         
     | 
| 
         @@ -37,7 +37,7 @@ module FactoryBot 
     | 
|
| 
       37 
37 
     | 
    
         
             
                  @instance = object_instance
         
     | 
| 
       38 
38 
     | 
    
         
             
                end
         
     | 
| 
       39 
39 
     | 
    
         | 
| 
       40 
     | 
    
         
            -
                def method_missing(method_name, *args, &block)
         
     | 
| 
      
 40 
     | 
    
         
            +
                def method_missing(method_name, *args, &block) # rubocop:disable Style/MethodMissingSuper
         
     | 
| 
       41 
41 
     | 
    
         
             
                  if @instance.respond_to?(method_name)
         
     | 
| 
       42 
42 
     | 
    
         
             
                    @instance.send(method_name, *args, &block)
         
     | 
| 
       43 
43 
     | 
    
         
             
                  else
         
     | 
| 
         @@ -45,7 +45,7 @@ module FactoryBot 
     | 
|
| 
       45 
45 
     | 
    
         
             
                  end
         
     | 
| 
       46 
46 
     | 
    
         
             
                end
         
     | 
| 
       47 
47 
     | 
    
         | 
| 
       48 
     | 
    
         
            -
                def respond_to_missing?(method_name,  
     | 
| 
      
 48 
     | 
    
         
            +
                def respond_to_missing?(method_name, _include_private = false)
         
     | 
| 
       49 
49 
     | 
    
         
             
                  @instance.respond_to?(method_name) || SyntaxRunner.new.respond_to?(method_name)
         
     | 
| 
       50 
50 
     | 
    
         
             
                end
         
     | 
| 
       51 
51 
     | 
    
         | 
| 
         @@ -66,7 +66,7 @@ module FactoryBot 
     | 
|
| 
       66 
66 
     | 
    
         
             
                end
         
     | 
| 
       67 
67 
     | 
    
         | 
| 
       68 
68 
     | 
    
         
             
                def self.define_attribute(name, &block)
         
     | 
| 
       69 
     | 
    
         
            -
                  if  
     | 
| 
      
 69 
     | 
    
         
            +
                  if instance_methods(false).include?(name) || private_instance_methods(false).include?(name)
         
     | 
| 
       70 
70 
     | 
    
         
             
                    undef_method(name)
         
     | 
| 
       71 
71 
     | 
    
         
             
                  end
         
     | 
| 
       72 
72 
     | 
    
         | 
    
        data/lib/factory_bot/factory.rb
    CHANGED
    
    | 
         @@ -1,5 +1,5 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require  
     | 
| 
       2 
     | 
    
         
            -
            require  
     | 
| 
      
 1 
     | 
    
         
            +
            require "active_support/core_ext/hash/keys"
         
     | 
| 
      
 2 
     | 
    
         
            +
            require "active_support/inflector"
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
4 
     | 
    
         
             
            module FactoryBot
         
     | 
| 
       5 
5 
     | 
    
         
             
              # @api private
         
     | 
| 
         @@ -21,10 +21,10 @@ module FactoryBot 
     | 
|
| 
       21 
21 
     | 
    
         | 
| 
       22 
22 
     | 
    
         
             
                def build_class
         
     | 
| 
       23 
23 
     | 
    
         
             
                  @build_class ||= if class_name.is_a? Class
         
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
       25 
     | 
    
         
            -
             
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
      
 24 
     | 
    
         
            +
                                     class_name
         
     | 
| 
      
 25 
     | 
    
         
            +
                                   else
         
     | 
| 
      
 26 
     | 
    
         
            +
                                     class_name.to_s.camelize.constantize
         
     | 
| 
      
 27 
     | 
    
         
            +
                                   end
         
     | 
| 
       28 
28 
     | 
    
         
             
                end
         
     | 
| 
       29 
29 
     | 
    
         | 
| 
       30 
30 
     | 
    
         
             
                def run(build_strategy, overrides, &block)
         
     | 
| 
         @@ -91,7 +91,7 @@ module FactoryBot 
     | 
|
| 
       91 
91 
     | 
    
         
             
                end
         
     | 
| 
       92 
92 
     | 
    
         | 
| 
       93 
93 
     | 
    
         
             
                def with_traits(traits)
         
     | 
| 
       94 
     | 
    
         
            -
                   
     | 
| 
      
 94 
     | 
    
         
            +
                  clone.tap do |factory_with_traits|
         
     | 
| 
       95 
95 
     | 
    
         
             
                    factory_with_traits.append_traits traits
         
     | 
| 
       96 
96 
     | 
    
         
             
                  end
         
     | 
| 
       97 
97 
     | 
    
         
             
                end
         
     | 
| 
         @@ -145,7 +145,7 @@ module FactoryBot 
     | 
|
| 
       145 
145 
     | 
    
         | 
| 
       146 
146 
     | 
    
         
             
                def parent
         
     | 
| 
       147 
147 
     | 
    
         
             
                  if @parent
         
     | 
| 
       148 
     | 
    
         
            -
                    FactoryBot.factory_by_name(@parent)
         
     | 
| 
      
 148 
     | 
    
         
            +
                    FactoryBot::Internal.factory_by_name(@parent)
         
     | 
| 
       149 
149 
     | 
    
         
             
                  else
         
     | 
| 
       150 
150 
     | 
    
         
             
                    NullFactory.new
         
     | 
| 
       151 
151 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -9,7 +9,7 @@ module FactoryBot 
     | 
|
| 
       9 
9 
     | 
    
         
             
                end
         
     | 
| 
       10 
10 
     | 
    
         | 
| 
       11 
11 
     | 
    
         
             
                def run(runner_strategy = @strategy, &block)
         
     | 
| 
       12 
     | 
    
         
            -
                  factory = FactoryBot.factory_by_name(@name)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  factory = FactoryBot::Internal.factory_by_name(@name)
         
     | 
| 
       13 
13 
     | 
    
         | 
| 
       14 
14 
     | 
    
         
             
                  factory.compile
         
     | 
| 
       15 
15 
     | 
    
         | 
| 
         @@ -22,10 +22,10 @@ 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 
     | 
    
         
            -
                  ActiveSupport::Notifications.instrument( 
     | 
| 
      
 28 
     | 
    
         
            +
                  ActiveSupport::Notifications.instrument("factory_bot.run_factory", instrumentation_payload) do
         
     | 
| 
       29 
29 
     | 
    
         
             
                    factory.run(runner_strategy, @overrides, &block)
         
     | 
| 
       30 
30 
     | 
    
         
             
                  end
         
     | 
| 
       31 
31 
     | 
    
         
             
                end
         
     | 
| 
         @@ -0,0 +1,104 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module FactoryBot
         
     | 
| 
      
 2 
     | 
    
         
            +
              # @api private
         
     | 
| 
      
 3 
     | 
    
         
            +
              module Internal
         
     | 
| 
      
 4 
     | 
    
         
            +
                class << self
         
     | 
| 
      
 5 
     | 
    
         
            +
                  delegate :after,
         
     | 
| 
      
 6 
     | 
    
         
            +
                           :before,
         
     | 
| 
      
 7 
     | 
    
         
            +
                           :callback_names,
         
     | 
| 
      
 8 
     | 
    
         
            +
                           :callbacks,
         
     | 
| 
      
 9 
     | 
    
         
            +
                           :constructor,
         
     | 
| 
      
 10 
     | 
    
         
            +
                           :factories,
         
     | 
| 
      
 11 
     | 
    
         
            +
                           :initialize_with,
         
     | 
| 
      
 12 
     | 
    
         
            +
                           :inline_sequences,
         
     | 
| 
      
 13 
     | 
    
         
            +
                           :sequences,
         
     | 
| 
      
 14 
     | 
    
         
            +
                           :skip_create,
         
     | 
| 
      
 15 
     | 
    
         
            +
                           :strategies,
         
     | 
| 
      
 16 
     | 
    
         
            +
                           :to_create,
         
     | 
| 
      
 17 
     | 
    
         
            +
                           :traits,
         
     | 
| 
      
 18 
     | 
    
         
            +
                           to: :configuration
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                  def configuration
         
     | 
| 
      
 21 
     | 
    
         
            +
                    @configuration ||= Configuration.new
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                  def reset_configuration
         
     | 
| 
      
 25 
     | 
    
         
            +
                    @configuration = nil
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                  def register_inline_sequence(sequence)
         
     | 
| 
      
 29 
     | 
    
         
            +
                    inline_sequences.push(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)
         
     | 
| 
      
 44 
     | 
    
         
            +
                    traits.find(name)
         
     | 
| 
      
 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 register_factory(factory)
         
     | 
| 
      
 64 
     | 
    
         
            +
                    factory.names.each do |name|
         
     | 
| 
      
 65 
     | 
    
         
            +
                      factories.register(name, factory)
         
     | 
| 
      
 66 
     | 
    
         
            +
                    end
         
     | 
| 
      
 67 
     | 
    
         
            +
                    factory
         
     | 
| 
      
 68 
     | 
    
         
            +
                  end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                  def factory_by_name(name)
         
     | 
| 
      
 71 
     | 
    
         
            +
                    factories.find(name)
         
     | 
| 
      
 72 
     | 
    
         
            +
                  end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                  def register_strategy(strategy_name, strategy_class)
         
     | 
| 
      
 75 
     | 
    
         
            +
                    strategies.register(strategy_name, strategy_class)
         
     | 
| 
      
 76 
     | 
    
         
            +
                    StrategySyntaxMethodRegistrar.new(strategy_name).define_strategy_methods
         
     | 
| 
      
 77 
     | 
    
         
            +
                  end
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                  def strategy_by_name(name)
         
     | 
| 
      
 80 
     | 
    
         
            +
                    strategies.find(name)
         
     | 
| 
      
 81 
     | 
    
         
            +
                  end
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
                  def register_default_strategies
         
     | 
| 
      
 84 
     | 
    
         
            +
                    register_strategy(:build, FactoryBot::Strategy::Build)
         
     | 
| 
      
 85 
     | 
    
         
            +
                    register_strategy(:create, FactoryBot::Strategy::Create)
         
     | 
| 
      
 86 
     | 
    
         
            +
                    register_strategy(:attributes_for, FactoryBot::Strategy::AttributesFor)
         
     | 
| 
      
 87 
     | 
    
         
            +
                    register_strategy(:build_stubbed, FactoryBot::Strategy::Stub)
         
     | 
| 
      
 88 
     | 
    
         
            +
                    register_strategy(:null, FactoryBot::Strategy::Null)
         
     | 
| 
      
 89 
     | 
    
         
            +
                  end
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
                  def register_default_callbacks
         
     | 
| 
      
 92 
     | 
    
         
            +
                    register_callback(:after_create)
         
     | 
| 
      
 93 
     | 
    
         
            +
                    register_callback(:after_build)
         
     | 
| 
      
 94 
     | 
    
         
            +
                    register_callback(:after_stub)
         
     | 
| 
      
 95 
     | 
    
         
            +
                    register_callback(:before_create)
         
     | 
| 
      
 96 
     | 
    
         
            +
                  end
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
                  def register_callback(name)
         
     | 
| 
      
 99 
     | 
    
         
            +
                    name = name.to_sym
         
     | 
| 
      
 100 
     | 
    
         
            +
                    callback_names << name
         
     | 
| 
      
 101 
     | 
    
         
            +
                  end
         
     | 
| 
      
 102 
     | 
    
         
            +
                end
         
     | 
| 
      
 103 
     | 
    
         
            +
              end
         
     | 
| 
      
 104 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/factory_bot/linter.rb
    CHANGED
    
    | 
         @@ -1,10 +1,10 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module FactoryBot
         
     | 
| 
       2 
2 
     | 
    
         
             
              class Linter
         
     | 
| 
       3 
     | 
    
         
            -
             
     | 
| 
       4 
     | 
    
         
            -
                def initialize(factories, linting_strategy, factory_strategy = :create)
         
     | 
| 
      
 3 
     | 
    
         
            +
                def initialize(factories, strategy: :create, traits: false, verbose: false)
         
     | 
| 
       5 
4 
     | 
    
         
             
                  @factories_to_lint = factories
         
     | 
| 
       6 
     | 
    
         
            -
                  @ 
     | 
| 
       7 
     | 
    
         
            -
                  @ 
     | 
| 
      
 5 
     | 
    
         
            +
                  @factory_strategy = strategy
         
     | 
| 
      
 6 
     | 
    
         
            +
                  @traits = traits
         
     | 
| 
      
 7 
     | 
    
         
            +
                  @verbose = verbose
         
     | 
| 
       8 
8 
     | 
    
         
             
                  @invalid_factories = calculate_invalid_factories
         
     | 
| 
       9 
9 
     | 
    
         
             
                end
         
     | 
| 
       10 
10 
     | 
    
         | 
| 
         @@ -20,7 +20,7 @@ module FactoryBot 
     | 
|
| 
       20 
20 
     | 
    
         | 
| 
       21 
21 
     | 
    
         
             
                def calculate_invalid_factories
         
     | 
| 
       22 
22 
     | 
    
         
             
                  factories_to_lint.reduce(Hash.new([])) do |result, factory|
         
     | 
| 
       23 
     | 
    
         
            -
                    errors =  
     | 
| 
      
 23 
     | 
    
         
            +
                    errors = lint(factory)
         
     | 
| 
       24 
24 
     | 
    
         
             
                    result[factory] |= errors unless errors.empty?
         
     | 
| 
       25 
25 
     | 
    
         
             
                    result
         
     | 
| 
       26 
26 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -37,6 +37,13 @@ module FactoryBot 
     | 
|
| 
       37 
37 
     | 
    
         
             
                    "* #{location} - #{message} (#{@wrapped_error.class.name})"
         
     | 
| 
       38 
38 
     | 
    
         
             
                  end
         
     | 
| 
       39 
39 
     | 
    
         | 
| 
      
 40 
     | 
    
         
            +
                  def verbose_message
         
     | 
| 
      
 41 
     | 
    
         
            +
                    <<~MESSAGE
         
     | 
| 
      
 42 
     | 
    
         
            +
                      #{message}
         
     | 
| 
      
 43 
     | 
    
         
            +
                        #{@wrapped_error.backtrace.join("\n  ")}
         
     | 
| 
      
 44 
     | 
    
         
            +
                    MESSAGE
         
     | 
| 
      
 45 
     | 
    
         
            +
                  end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
       40 
47 
     | 
    
         
             
                  def location
         
     | 
| 
       41 
48 
     | 
    
         
             
                    @factory.name
         
     | 
| 
       42 
49 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -53,12 +60,20 @@ module FactoryBot 
     | 
|
| 
       53 
60 
     | 
    
         
             
                  end
         
     | 
| 
       54 
61 
     | 
    
         
             
                end
         
     | 
| 
       55 
62 
     | 
    
         | 
| 
      
 63 
     | 
    
         
            +
                def lint(factory)
         
     | 
| 
      
 64 
     | 
    
         
            +
                  if @traits
         
     | 
| 
      
 65 
     | 
    
         
            +
                    lint_factory(factory) + lint_traits(factory)
         
     | 
| 
      
 66 
     | 
    
         
            +
                  else
         
     | 
| 
      
 67 
     | 
    
         
            +
                    lint_factory(factory)
         
     | 
| 
      
 68 
     | 
    
         
            +
                  end
         
     | 
| 
      
 69 
     | 
    
         
            +
                end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
       56 
71 
     | 
    
         
             
                def lint_factory(factory)
         
     | 
| 
       57 
72 
     | 
    
         
             
                  result = []
         
     | 
| 
       58 
73 
     | 
    
         
             
                  begin
         
     | 
| 
       59 
74 
     | 
    
         
             
                    FactoryBot.public_send(factory_strategy, factory.name)
         
     | 
| 
       60 
     | 
    
         
            -
                  rescue =>  
     | 
| 
       61 
     | 
    
         
            -
                    result |= [FactoryError.new( 
     | 
| 
      
 75 
     | 
    
         
            +
                  rescue StandardError => e
         
     | 
| 
      
 76 
     | 
    
         
            +
                    result |= [FactoryError.new(e, factory)]
         
     | 
| 
       62 
77 
     | 
    
         
             
                  end
         
     | 
| 
       63 
78 
     | 
    
         
             
                  result
         
     | 
| 
       64 
79 
     | 
    
         
             
                end
         
     | 
| 
         @@ -68,30 +83,32 @@ module FactoryBot 
     | 
|
| 
       68 
83 
     | 
    
         
             
                  factory.definition.defined_traits.map(&:name).each do |trait_name|
         
     | 
| 
       69 
84 
     | 
    
         
             
                    begin
         
     | 
| 
       70 
85 
     | 
    
         
             
                      FactoryBot.public_send(factory_strategy, factory.name, trait_name)
         
     | 
| 
       71 
     | 
    
         
            -
                    rescue =>  
     | 
| 
      
 86 
     | 
    
         
            +
                    rescue StandardError => e
         
     | 
| 
       72 
87 
     | 
    
         
             
                      result |=
         
     | 
| 
       73 
     | 
    
         
            -
             
     | 
| 
      
 88 
     | 
    
         
            +
                        [FactoryTraitError.new(e, factory, trait_name)]
         
     | 
| 
       74 
89 
     | 
    
         
             
                    end
         
     | 
| 
       75 
90 
     | 
    
         
             
                  end
         
     | 
| 
       76 
91 
     | 
    
         
             
                  result
         
     | 
| 
       77 
92 
     | 
    
         
             
                end
         
     | 
| 
       78 
93 
     | 
    
         | 
| 
       79 
     | 
    
         
            -
                def lint_factory_and_traits(factory)
         
     | 
| 
       80 
     | 
    
         
            -
                  errors = lint_factory(factory)
         
     | 
| 
       81 
     | 
    
         
            -
                  errors |= lint_traits(factory)
         
     | 
| 
       82 
     | 
    
         
            -
                  errors
         
     | 
| 
       83 
     | 
    
         
            -
                end
         
     | 
| 
       84 
     | 
    
         
            -
             
     | 
| 
       85 
94 
     | 
    
         
             
                def error_message
         
     | 
| 
       86 
95 
     | 
    
         
             
                  lines = invalid_factories.map do |_factory, exceptions|
         
     | 
| 
       87 
     | 
    
         
            -
                    exceptions.map( 
     | 
| 
      
 96 
     | 
    
         
            +
                    exceptions.map(&error_message_type)
         
     | 
| 
       88 
97 
     | 
    
         
             
                  end.flatten
         
     | 
| 
       89 
98 
     | 
    
         | 
| 
       90 
     | 
    
         
            -
                   
     | 
| 
       91 
     | 
    
         
            -
            The following factories are invalid:
         
     | 
| 
      
 99 
     | 
    
         
            +
                  <<~ERROR_MESSAGE.strip
         
     | 
| 
      
 100 
     | 
    
         
            +
                    The following factories are invalid:
         
     | 
| 
       92 
101 
     | 
    
         | 
| 
       93 
     | 
    
         
            -
            #{lines.join("\n")}
         
     | 
| 
      
 102 
     | 
    
         
            +
                    #{lines.join("\n")}
         
     | 
| 
       94 
103 
     | 
    
         
             
                  ERROR_MESSAGE
         
     | 
| 
       95 
104 
     | 
    
         
             
                end
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
                def error_message_type
         
     | 
| 
      
 107 
     | 
    
         
            +
                  if @verbose
         
     | 
| 
      
 108 
     | 
    
         
            +
                    :verbose_message
         
     | 
| 
      
 109 
     | 
    
         
            +
                  else
         
     | 
| 
      
 110 
     | 
    
         
            +
                    :message
         
     | 
| 
      
 111 
     | 
    
         
            +
                  end
         
     | 
| 
      
 112 
     | 
    
         
            +
                end
         
     | 
| 
       96 
113 
     | 
    
         
             
              end
         
     | 
| 
       97 
114 
     | 
    
         
             
            end
         
     | 
| 
         @@ -8,11 +8,14 @@ module FactoryBot 
     | 
|
| 
       8 
8 
     | 
    
         
             
                end
         
     | 
| 
       9 
9 
     | 
    
         | 
| 
       10 
10 
     | 
    
         
             
                delegate :defined_traits, :callbacks, :attributes, :constructor,
         
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
      
 11 
     | 
    
         
            +
                         :to_create, to: :definition
         
     | 
| 
       12 
12 
     | 
    
         | 
| 
       13 
13 
     | 
    
         
             
                def compile; end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
       14 
15 
     | 
    
         
             
                def class_name; end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
       15 
17 
     | 
    
         
             
                def evaluator_class; FactoryBot::Evaluator; end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
       16 
19 
     | 
    
         
             
                def hierarchy_class; FactoryBot::DefinitionHierarchy; end
         
     | 
| 
       17 
20 
     | 
    
         
             
              end
         
     | 
| 
       18 
21 
     | 
    
         
             
            end
         
     | 
| 
         @@ -13,11 +13,11 @@ module FactoryBot 
     | 
|
| 
       13 
13 
     | 
    
         
             
                  end
         
     | 
| 
       14 
14 
     | 
    
         
             
                end
         
     | 
| 
       15 
15 
     | 
    
         | 
| 
       16 
     | 
    
         
            -
                def respond_to?(method,  
     | 
| 
      
 16 
     | 
    
         
            +
                def respond_to?(method, _include_private = false)
         
     | 
| 
       17 
17 
     | 
    
         
             
                  @methods_to_respond_to.include? method.to_s
         
     | 
| 
       18 
18 
     | 
    
         
             
                end
         
     | 
| 
       19 
19 
     | 
    
         | 
| 
       20 
     | 
    
         
            -
                def respond_to_missing?(* 
     | 
| 
      
 20 
     | 
    
         
            +
                def respond_to_missing?(*)
         
     | 
| 
       21 
21 
     | 
    
         
             
                  false
         
     | 
| 
       22 
22 
     | 
    
         
             
                end
         
     | 
| 
       23 
23 
     | 
    
         
             
              end
         
     | 
    
        data/lib/factory_bot/registry.rb
    CHANGED
    
    | 
         @@ -1,3 +1,5 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "active_support/core_ext/hash/indifferent_access"
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
       1 
3 
     | 
    
         
             
            module FactoryBot
         
     | 
| 
       2 
4 
     | 
    
         
             
              class Registry
         
     | 
| 
       3 
5 
     | 
    
         
             
                include Enumerable
         
     | 
| 
         @@ -6,7 +8,7 @@ module FactoryBot 
     | 
|
| 
       6 
8 
     | 
    
         | 
| 
       7 
9 
     | 
    
         
             
                def initialize(name)
         
     | 
| 
       8 
10 
     | 
    
         
             
                  @name  = name
         
     | 
| 
       9 
     | 
    
         
            -
                  @items =  
     | 
| 
      
 11 
     | 
    
         
            +
                  @items = ActiveSupport::HashWithIndifferentAccess.new
         
     | 
| 
       10 
12 
     | 
    
         
             
                end
         
     | 
| 
       11 
13 
     | 
    
         | 
| 
       12 
14 
     | 
    
         
             
                def clear
         
     | 
| 
         @@ -18,11 +20,9 @@ module FactoryBot 
     | 
|
| 
       18 
20 
     | 
    
         
             
                end
         
     | 
| 
       19 
21 
     | 
    
         | 
| 
       20 
22 
     | 
    
         
             
                def find(name)
         
     | 
| 
       21 
     | 
    
         
            -
                   
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
       23 
     | 
    
         
            -
                   
     | 
| 
       24 
     | 
    
         
            -
                    raise ArgumentError, "#{@name} not registered: #{name}"
         
     | 
| 
       25 
     | 
    
         
            -
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
                  @items.fetch(name)
         
     | 
| 
      
 24 
     | 
    
         
            +
                rescue KeyError => e
         
     | 
| 
      
 25 
     | 
    
         
            +
                  raise key_error_with_custom_message(e)
         
     | 
| 
       26 
26 
     | 
    
         
             
                end
         
     | 
| 
       27 
27 
     | 
    
         | 
| 
       28 
28 
     | 
    
         
             
                alias :[] :find
         
     | 
| 
         @@ -34,5 +34,14 @@ module FactoryBot 
     | 
|
| 
       34 
34 
     | 
    
         
             
                def registered?(name)
         
     | 
| 
       35 
35 
     | 
    
         
             
                  @items.key?(name)
         
     | 
| 
       36 
36 
     | 
    
         
             
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                private
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                def key_error_with_custom_message(key_error)
         
     | 
| 
      
 41 
     | 
    
         
            +
                  message = key_error.message.sub("key not found", "#{@name} not registered")
         
     | 
| 
      
 42 
     | 
    
         
            +
                  error = KeyError.new(message)
         
     | 
| 
      
 43 
     | 
    
         
            +
                  error.set_backtrace(key_error.backtrace)
         
     | 
| 
      
 44 
     | 
    
         
            +
                  error
         
     | 
| 
      
 45 
     | 
    
         
            +
                end
         
     | 
| 
       37 
46 
     | 
    
         
             
              end
         
     | 
| 
       38 
47 
     | 
    
         
             
            end
         
     | 
    
        data/lib/factory_bot/reload.rb
    CHANGED
    
    
    
        data/lib/factory_bot/sequence.rb
    CHANGED