Module: Synthra::FactoryBotIntegration

Defined in:
lib/synthra/factory_bot_integration.rb

Overview

Factory Bot Integration

Provides seamless integration between Synthra and Factory Bot. Define factories using Synthra schemas with full trait support.

Examples:

Define a factory

Synthra.define_factory(:user, schema: "User") do
  trait(:admin) do
    role { "admin" }
  end

  trait(:with_address) do
    address { Synthra.generate("Address") }
  end
end

Use in tests

create(:user)
create(:user, :admin)
create(:user, :admin, :with_address, name: "Custom Name")

Defined Under Namespace

Modules: DSL, RSpec

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.factoriesObject

Registry of Synthra factories



28
29
30
# File 'lib/synthra/factory_bot_integration.rb', line 28

def factories
  @factories
end

Class Method Details

.build(factory_name, *traits, **overrides) ⇒ Hash

Generate data using a defined factory

Parameters:

  • factory_name (Symbol)

    the factory name

  • traits (Array<Symbol>)

    traits to apply

  • overrides (Hash)

    field overrides

Returns:

  • (Hash)

    generated data

Raises:

  • (ArgumentError)


57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/synthra/factory_bot_integration.rb', line 57

def build(factory_name, *traits, **overrides)
  factory = @factories&.[](factory_name)
  raise ArgumentError, "Unknown factory: #{factory_name}" unless factory

  # Get the schema
  schema = Synthra.parse(load_schema_source(factory[:schema]))

  # Apply traits
  merged_overrides = overrides.dup
  traits.each do |trait_name|
    trait = factory[:traits][trait_name]
    merged_overrides.merge!(trait) if trait
  end

  # Generate with overrides
  schema.generate(overrides: merged_overrides)
end

.define_factory(factory_name, schema:) { ... } ⇒ void

This method returns an undefined value.

Define a factory using a Synthra schema

Parameters:

  • factory_name (Symbol)

    the factory name

  • schema (String)

    the schema name

Yields:

  • block for defining traits and overrides



37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/synthra/factory_bot_integration.rb', line 37

def define_factory(factory_name, schema:, &block)
  @factories ||= {}
  @factories[factory_name] = {
    schema: schema,
    traits: {},
    overrides: {},
    block: block
  }

  # Register with Factory Bot if available
  register_with_factory_bot(factory_name, schema, &block) if factory_bot_available?
end

.factory_bot_available?Boolean

Check if Factory Bot is available

Returns:

  • (Boolean)


79
80
81
# File 'lib/synthra/factory_bot_integration.rb', line 79

def factory_bot_available?
  !!defined?(FactoryBot)
end

.load_schema_source(schema_name) ⇒ Object (private)



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/synthra/factory_bot_integration.rb', line 85

def load_schema_source(schema_name)
  # Check if it's already a schema object or a string
  if schema_name.is_a?(Schema)
    return schema_name
  end

  # Try to find in default registry
  if Synthra.instance_variable_get(:@default_registry)
    registry = Synthra.instance_variable_get(:@default_registry)
    return registry.schema(schema_name) if registry.schema?(schema_name)
  end

  # Create minimal DSL for the schema
  "#{schema_name}:\n  id: uuid"
end

.register_with_factory_bot(factory_name, schema_name, &block) ⇒ Object (private)

:nocov: requires the factory_bot gem's DSL runtime (FactoryBot.define / factory / trait), which is not a dependency of this gem; exercised only inside a consuming app that has factory_bot loaded. The dispatch into here is covered (see define_factory spec).



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/synthra/factory_bot_integration.rb', line 104

def register_with_factory_bot(factory_name, schema_name, &block)
  # Integration with Factory Bot DSL
  factory_config = @factories[factory_name]

  FactoryBot.define do
    factory factory_name do
      initialize_with do
        Synthra::FactoryBotIntegration.build(
          factory_name,
          *@build_strategy_traits,
          **attributes
        )
      end

      # Process the block to extract traits
      instance_exec(&block) if block
    end
  end
end