Class: Vial::Definition

Inherits:
Object
  • Object
show all
Defined in:
lib/vial/definition.rb

Defined Under Namespace

Classes: AttributeBuilder, CallableValue, Generation, Include, IncludeOverrideBuilder, Record, RecordContext, SequenceDefinition

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, primary_key: :id, record_type: nil, id_base: nil, id_range: nil, id_type: nil, abstract: false) ⇒ Definition

Returns a new instance of Definition.

Raises:

  • (ArgumentError)


12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/vial/definition.rb', line 12

def initialize(name, primary_key: :id, record_type: nil, id_base: nil, id_range: nil, id_type: nil, abstract: false)
  @name = normalize_name(name)
  @primary_key = primary_key.to_s
  @record_type = (record_type ? record_type.to_s : default_record_type(@name))
  @id_base = id_base.nil? ? Vial.config.id_base : id_base
  @id_range = id_range.nil? ? Vial.config.id_range : id_range
  @abstract = !!abstract
  raise ArgumentError, "id_type is not supported; Vial derives deterministic integer IDs" unless id_type.nil?
  raise ArgumentError, "id_range must be positive" unless @id_range.to_i > 0
  @base_attributes = {}
  @variant_attributes = {}
  @generations = []
  @sequence_defs = {}
  @includes = []
  @sequences = nil
end

Instance Attribute Details

#base_attributesObject (readonly)

Returns the value of attribute base_attributes.



10
11
12
# File 'lib/vial/definition.rb', line 10

def base_attributes
  @base_attributes
end

#id_baseObject (readonly)

Returns the value of attribute id_base.



10
11
12
# File 'lib/vial/definition.rb', line 10

def id_base
  @id_base
end

#id_rangeObject (readonly)

Returns the value of attribute id_range.



10
11
12
# File 'lib/vial/definition.rb', line 10

def id_range
  @id_range
end

#nameObject (readonly)

Returns the value of attribute name.



10
11
12
# File 'lib/vial/definition.rb', line 10

def name
  @name
end

#primary_keyObject (readonly)

Returns the value of attribute primary_key.



10
11
12
# File 'lib/vial/definition.rb', line 10

def primary_key
  @primary_key
end

#record_typeObject (readonly)

Returns the value of attribute record_type.



10
11
12
# File 'lib/vial/definition.rb', line 10

def record_type
  @record_type
end

#variant_attributesObject (readonly)

Returns the value of attribute variant_attributes.



10
11
12
# File 'lib/vial/definition.rb', line 10

def variant_attributes
  @variant_attributes
end

Instance Method Details

#abstract?Boolean

Returns:

  • (Boolean)


116
117
118
# File 'lib/vial/definition.rb', line 116

def abstract?
  @abstract
end

#base(&block) ⇒ Object



29
30
31
# File 'lib/vial/definition.rb', line 29

def base(&block)
  @base_attributes = build_attributes(&block)
end

#build_recordsObject



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/vial/definition.rb', line 70

def build_records
  @sequences = build_sequences
  base_attrs = resolved_base_attributes
  records = []

  grouped_generations.each do |group|
    variant = group[:variant]
    label = group[:label]
    count = group[:count]
    variant_attrs = variant ? (@variant_attributes[variant] || {}) : {}
    merged_attrs = merge_attributes(base_attrs, variant_attrs)
    static_attrs, dynamic_entries = split_attributes(merged_attrs)
    variant_stack = variant ? [variant] : []
    source_file = group[:source_file]
    source_line = group[:source_line]

    count.times do |offset|
      index = offset + 1
      fixture_label = fixture_label_for(label, index, count)

      attrs = static_attrs.dup
      if dynamic_entries.any?
        context = RecordContext.new(self, label: label, variant: variant, index: index)
        dynamic_entries.each do |key, value|
          attrs[key] = resolve_value(value, context)
        end
      end

      records << Record.new(
        definition: self,
        fixture_label: fixture_label,
        identity_label: label,
        variant_stack: variant_stack,
        index: index,
        attributes: attrs,
        source_file: source_file,
        source_line: source_line
      )
    end
  end

  records
ensure
  @sequences = nil
end

#derive_id(label:, variant_stack:, index:, salt: 0) ⇒ Object



135
136
137
# File 'lib/vial/definition.rb', line 135

def derive_id(label:, variant_stack:, index:, salt: 0)
  derived_id_for(label: label, variant_stack: variant_stack, index: index, salt: salt)
end

#explain_id(label:, variant_stack:, index:) ⇒ Object



120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/vial/definition.rb', line 120

def explain_id(label:, variant_stack:, index:)
  variants = Array(variant_stack)
  parts = [@name, @record_type, label] + variants + [index]
  normalized = parts.map { |part| normalize_identity_part(part) }.join('::')
  hash_value = Zlib.crc32(normalized)
  {
    tuple: parts,
    normalized: normalized,
    hash: hash_value,
    base: @id_base,
    range: @id_range,
    final: @id_base + (hash_value % @id_range)
  }
end

#generate(*args, **kwargs) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/vial/definition.rb', line 48

def generate(*args, **kwargs)
  count, variant, label_prefix = parse_generation_args(*args, **kwargs)
  loc = caller_locations(1, 1).first
  source_file = loc&.absolute_path || loc&.path
  @generations << Generation.new(
    count: count,
    variant: variant,
    label_prefix: label_prefix,
    source_file: source_file,
    source_line: loc&.lineno
  )
end

#include_vial(name, &block) ⇒ Object



37
38
39
40
41
42
43
44
45
46
# File 'lib/vial/definition.rb', line 37

def include_vial(name, &block)
  overrides = {}
  if block
    builder = IncludeOverrideBuilder.new(self)
    builder.instance_eval(&block)
    overrides = builder.attributes
  end

  @includes << Include.new(name: normalize_name(name), overrides: overrides)
end

#sequence(name, start: 1, &block) ⇒ Object



61
62
63
64
65
66
67
68
# File 'lib/vial/definition.rb', line 61

def sequence(name, start: 1, &block)
  if block
    @sequence_defs[name.to_sym] = SequenceDefinition.new(start: start, block: block)
    return
  end

  SequenceRef.new(name)
end

#sequence_definitionsObject



139
140
141
# File 'lib/vial/definition.rb', line 139

def sequence_definitions
  @sequence_defs
end

#unused_sequence_namesObject

Sequences defined with a block but never consumed via attr sequence(:name) in base or a variant. Defining one without referencing it is a silent no-op, so the compiler warns about these.



146
147
148
149
150
151
152
153
154
# File 'lib/vial/definition.rb', line 146

def unused_sequence_names
  return [] if abstract?

  referenced = sequence_refs_in(resolved_base_attributes)
  @variant_attributes.each_value do |attrs|
    referenced |= sequence_refs_in(attrs)
  end
  @sequence_defs.keys - referenced
end

#variant(name, &block) ⇒ Object



33
34
35
# File 'lib/vial/definition.rb', line 33

def variant(name, &block)
  @variant_attributes[name.to_sym] = build_attributes(&block)
end