class FactoryManager

A factory manager of factory bots.

Public Class Methods

build(&block) click to toggle source

Initializes and builds a new factory.

@yield Invokes the block to build the factory.

# File lib/factory_manager.rb, line 16
def self.build(&block)
  instance = new(strategy: :build)
  instance.generate(&block)
end
create(&block) click to toggle source

Initializes and creates a new factory.

@yield Invokes the block to create the factory.

# File lib/factory_manager.rb, line 24
def self.create(&block)
  instance = new(strategy: :create)
  instance.generate(&block)
end
new(strategy:) click to toggle source

Initializes a new factory.

# File lib/factory_manager.rb, line 6
def initialize(strategy:)
  @locals = {}
  @results = {}
  @scopes = {}
  @strategy = strategy
end

Public Instance Methods

generate(&block) click to toggle source

Generate the factory.

@yield Invokes the block to generate the factory. @return [OpenStruct] An object containing the record results.

# File lib/factory_manager.rb, line 33
def generate(&block)
  instance_eval(&block)

  OpenStruct.new(@locals)
end

Private Instance Methods

_add_to_scope(record, scope:) { || ... } click to toggle source

Add a record to a new or existing scope.

@param [ActiveRecord::Base] The record to add to the scope. @param [Symbol] scope The name of the scope. @return [ActiveRecord::Base] The record.

# File lib/factory_manager.rb, line 46
def _add_to_scope(record, scope:)
  @scopes[scope] ||= []
  @scopes[scope] << record

  yield

  @scopes[scope].pop
end
_assign_local(method, value) click to toggle source

Assign a local variable.

@param [Symbol] method The method name for the local. @param [*] value The value of the local.

# File lib/factory_manager.rb, line 59
def _assign_local(method, value)
  @locals[method.to_s.tr("=", "")] = value
end
_assignment_method?(name) click to toggle source

Determine if a name is an assignment method.

@param [Symbol] name The assignment method name. @return [Boolean] Whether or not the name is an assignment method.

# File lib/factory_manager.rb, line 67
def _assignment_method?(name)
  name.to_s.end_with?("=")
end
_associations_for(name) click to toggle source

Find the associations for a specific factory.

@param [String] name The factory name. @return [Hash] The associations for the factory.

# File lib/factory_manager.rb, line 75
def _associations_for(name)
  @scopes
    .slice(*_factory_attributes(name))
    .transform_values(&:last)
end
_factory_attributes(name) click to toggle source

Determine all attribute names for a factory.

@param [String] name The factory name. @return [Array] The attributes for the factory.

# File lib/factory_manager.rb, line 85
def _factory_attributes(name)
  @_factory_attributes ||= {}
  @_factory_attributes[name] ||= FactoryBot.factories.find(name).definition.attributes.names
end
_generate_factory(name, *arguments) click to toggle source

Generate a factory record with associations and custom attributes.

@param [String] name The factory name. @param [Hash] arguments The factory arguments. @return [ActiveRecord::Base] The built factory record.

# File lib/factory_manager.rb, line 95
def _generate_factory(name, *arguments)
  arguments.push(
    _associations_for(name).merge(arguments.extract_options!)
  )

  method = arguments.first.is_a?(Integer) ? "#{@strategy}_list" : @strategy

  FactoryBot.public_send(method, name, *arguments)
end
method_missing(method, *arguments, &block) click to toggle source

Generate a factory record for the missing method.

@param [Symbol] method The name of the method. @param [Hash] arguments The factory arguments. @return [ActiveRecord::Base] The built factory record.

Calls superclass method
# File lib/factory_manager.rb, line 110
def method_missing(method, *arguments, &block)
  super unless respond_to_missing?(method)

  if _assignment_method?(method)
    _assign_local(method, arguments.first)
  else
    record = _generate_factory(method, *arguments)

    _add_to_scope(record, scope: method) do
      generate(&block) if block
    end

    record
  end
end
respond_to_missing?(method) click to toggle source

Determine if a factory exists for the missing method, or if a local variable is being assigned.

@param [Symbol] method The name of the method. @return [Boolean] Whether or not the factory exists.

# File lib/factory_manager.rb, line 131
def respond_to_missing?(method)
  !FactoryBot.factories.find(method).nil?
rescue KeyError
  _assignment_method?(method)
end