Class: Synthra::Field

Inherits:
Object
  • Object
show all
Defined in:
lib/synthra/field.rb

Overview

Represents a single field in a schema definition

A Field encapsulates all information about a schema field including:

  • Field name and whether it's optional
  • Type name and arguments for generation
  • Nullable status (can the value be nil?)
  • Conditional expression (when should this field be included?)
  • Field-level behaviors (latency, partial_data, etc.)

Examples:

Create a field programmatically

field = Field.new(
  name: "email",
  type_name: "email",
  type_args: { domain: "example.com" },
  nullable: false
)

Optional field (from DSL: "nickname?: text")

field = Field.new(name: "nickname?", type_name: "text")
field.name        # => "nickname"
field.optional?   # => true

Nullable type (from DSL: "manager: User?")

field = Field.new(name: "manager", type_name: "User?")
field.nullable?   # => true

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name:, type_name:, type_args: {}, nullable: false, condition: nil, behaviors: []) ⇒ Field

Create a new Field instance

Examples:

Simple field

Field.new(name: "id", type_name: "uuid")

Field with arguments

Field.new(
  name: "age",
  type_name: "number",
  type_args: { min: 18, max: 80 }
)

Optional nullable field with condition

Field.new(
  name: "manager?",
  type_name: "User?",
  condition: "is_employee"
)

Parameters:

  • name (String)

    field name (may include ? suffix for optional)

  • type_name (String)

    the type name (may include ? suffix for nullable)

  • type_args (Hash) (defaults to: {})

    arguments to pass to the type generator

  • nullable (Boolean) (defaults to: false)

    whether the field value can be nil

  • condition (String, nil) (defaults to: nil)

    field name that must be truthy for inclusion

  • behaviors (Array<FieldBehavior>) (defaults to: [])

    field-level behaviors to apply



117
118
119
120
121
122
123
124
125
126
# File 'lib/synthra/field.rb', line 117

def initialize(name:, type_name:, type_args: {}, nullable: false, condition: nil, behaviors: [])
  @raw_name = name
  @name = name.delete_suffix("?")
  @optional = name.end_with?("?")
  @type_name = type_name.to_s.delete_suffix("?")
  @type_args = type_args || {}
  @nullable = nullable || type_name.to_s.end_with?("?")
  @condition = condition
  @behaviors = behaviors
end

Instance Attribute Details

#behaviorsObject (readonly)

Returns the value of attribute behaviors.



87
88
89
# File 'lib/synthra/field.rb', line 87

def behaviors
  @behaviors
end

#conditionObject (readonly)

Returns the value of attribute condition.



80
81
82
# File 'lib/synthra/field.rb', line 80

def condition
  @condition
end

#nameObject (readonly)

Returns the value of attribute name.



59
60
61
# File 'lib/synthra/field.rb', line 59

def name
  @name
end

#type_argsObject (readonly)

Returns the value of attribute type_args.



73
74
75
# File 'lib/synthra/field.rb', line 73

def type_args
  @type_args
end

#type_nameObject (readonly)

Returns the value of attribute type_name.



66
67
68
# File 'lib/synthra/field.rb', line 66

def type_name
  @type_name
end

Instance Method Details

#behavior(type) ⇒ FieldBehavior?

Get a specific behavior by type

Examples:

behavior = field.behavior(:latency)
behavior.value  # => { min: 100, max: 500 }

Parameters:

  • type (Symbol, String)

    the behavior type to retrieve

Returns:



240
241
242
# File 'lib/synthra/field.rb', line 240

def behavior(type)
  behaviors.find { |b| b.type == type.to_sym }
end

#conditional?Boolean

Check if this field has a condition

Conditional fields are only included when another field has a truthy value. The condition is specified with "if field_name" in the DSL.

Examples:

DSL: "admin_note: text if is_admin"

field.conditional?  # => true
field.condition     # => "is_admin"

Returns:

  • (Boolean)

    true if the field has a condition



176
177
178
# File 'lib/synthra/field.rb', line 176

def conditional?
  !condition.nil?
end

#has_behavior?(type) ⇒ Boolean

Check if this field has a specific behavior

Examples:

field.has_behavior?(:latency)       # => true
field.has_behavior?(:partial_data)  # => false

Parameters:

  • type (Symbol, String)

    the behavior type to check for

Returns:

  • (Boolean)

    true if the field has the specified behavior



225
226
227
# File 'lib/synthra/field.rb', line 225

def has_behavior?(type)
  behaviors.any? { |b| b.type == type.to_sym }
end

#inspectString

Inspect representation for debugging

Returns:

  • (String)

    inspect string



293
294
295
# File 'lib/synthra/field.rb', line 293

def inspect
  "#<Field #{self}>"
end

#modifiersHash

Get all modifiers as a hash

Returns a hash containing all field modifiers (unique, range, nullable, optional) with their values, excluding nil values.

Examples:

field.modifiers
# => { unique: true, nullable: false, optional: true }

Returns:

  • (Hash)

    modifier name => value pairs



257
258
259
260
261
262
263
264
# File 'lib/synthra/field.rb', line 257

def modifiers
  {
    unique: unique?,
    range: range,
    nullable: nullable?,
    optional: optional?
  }.compact
end

#nullable?Boolean

Check if this field's type is nullable

Nullable types (marked with ? suffix on type in DSL) can generate nil values. This is different from optional - nullable fields are always included but may have nil values.

Examples:

Field.new(name: "manager", type_name: "User?").nullable?  # => true
Field.new(name: "manager", type_name: "User").nullable?   # => false

Returns:

  • (Boolean)

    true if the type can be nil



159
160
161
# File 'lib/synthra/field.rb', line 159

def nullable?
  @nullable
end

#optional?Boolean

Check if this field is optional

Optional fields (marked with ? suffix in DSL) may be omitted from the generated output entirely based on configuration or randomness.

Examples:

Field.new(name: "nickname?", type_name: "text").optional?  # => true
Field.new(name: "name", type_name: "text").optional?       # => false

Returns:

  • (Boolean)

    true if the field is optional



141
142
143
# File 'lib/synthra/field.rb', line 141

def optional?
  @optional
end

#rangeRange?

Get the range constraint if present

Range constraints limit the generated values to a specific range. Common for number types.

Examples:

DSL: "age: number(18..80)"

field.range  # => 18..80

Returns:

  • (Range, nil)

    the range constraint, or nil if not specified



208
209
210
211
212
# File 'lib/synthra/field.rb', line 208

def range
  return nil unless type_args[:range]

  type_args[:range]
end

#to_sString

String representation of the field

Returns a human-readable string showing the field definition similar to how it would appear in a DSL file.

Examples:

field.to_s  # => "name: text"
field.to_s  # => "age: number({min: 18, max: 80})"

Returns:

  • (String)

    string representation



279
280
281
282
283
284
285
# File 'lib/synthra/field.rb', line 279

def to_s
  parts = ["#{@raw_name}: #{type_name}"]
  parts << "(#{type_args})" unless type_args.empty?
  parts << "if #{condition}" if condition
  behaviors.each { |b| parts << "@#{b.type} #{b.value}" }
  parts.join(" ")
end

#unique?Boolean

Check if this field has a uniqueness constraint

Unique fields will not generate duplicate values within a batch. The generator will retry up to max_unique_retries times.

Examples:

DSL: "id: uuid unique"

field.unique?  # => true

Returns:

  • (Boolean)

    true if the field requires unique values



192
193
194
# File 'lib/synthra/field.rb', line 192

def unique?
  type_args[:unique] == true
end