Class: Plutonium::Wizard::FieldCapture

Inherits:
Object
  • Object
show all
Includes:
Definition::DefineableProps, Definition::FormLayout, Definition::StructuredInputs
Defined in:
lib/plutonium/wizard/field_capture.rb

Overview

Records the field surface declared inside a step block.

A step block reuses Plutonium's existing field DSL — attribute, input, validates, structured_input, form_layout — plus the per-step hooks on_submit and on_rollback. This object captures all of it by instance_exec-ing the block against itself.

The union data schema (§2.6) is built from inline attribute name, type declarations recorded here as attribute_schema (=> type).

using: import (a model — see FieldImporter) is recorded as a marker (using_spec) and merged lazily; this object only captures inline declarations and composes them over the resolved import (inline wins).

Constant Summary

Constants included from Definition::FormLayout

Definition::FormLayout::UNGROUPED_KEY

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Definition::FormLayout

assign_ownership, #defined_form_layout, #resolve_form_sections, resolve_sections

Constructor Details

#initializeFieldCapture

Returns a new instance of FieldCapture.



34
35
36
37
38
39
# File 'lib/plutonium/wizard/field_capture.rb', line 34

def initialize
  @inline_attribute_schema = {}
  @inline_attribute_options = {}
  @validations = []
  @hooks = {}
end

Instance Attribute Details

#hooksObject (readonly)

Returns the value of attribute hooks.



25
26
27
# File 'lib/plutonium/wizard/field_capture.rb', line 25

def hooks
  @hooks
end

#using_specObject (readonly)

Returns the value of attribute using_spec.



25
26
27
# File 'lib/plutonium/wizard/field_capture.rb', line 25

def using_spec
  @using_spec
end

#validationsObject (readonly)

Returns the value of attribute validations.



25
26
27
# File 'lib/plutonium/wizard/field_capture.rb', line 25

def validations
  @validations
end

Class Method Details

.build(using: nil, using_opts: {}, &block) ⇒ Object



27
28
29
30
31
32
# File 'lib/plutonium/wizard/field_capture.rb', line 27

def self.build(using: nil, using_opts: {}, &block)
  capture = new
  capture.record_using(using, using_opts) if using
  capture.instance_exec(&block) if block
  capture
end

Instance Method Details

#attribute(name, type = :string, **options) ⇒ Object

Inline attribute :name, :type — records the union-schema type and any options (default:, etc.), which are threaded into the typed data snapshot so e.g. default: applies (§2.6).



44
45
46
47
48
49
# File 'lib/plutonium/wizard/field_capture.rb', line 44

def attribute(name, type = :string, **options)
  key = name.to_sym
  @inline_attribute_schema[key] = type
  @inline_attribute_options[key] = options unless options.empty?
  self
end

#attribute_optionsObject

The effective per-attribute options (=> {default:, ...}). Imports contribute none (types come from the source; options stay inline); inline declarations are returned as-is.



61
62
63
# File 'lib/plutonium/wizard/field_capture.rb', line 61

def attribute_options
  @inline_attribute_options
end

#attribute_schemaObject

The effective union-schema types for this step (=> type), composing a using: import with inline attribute declarations — inline wins on a name conflict (§2.4). The imported surface is resolved lazily.



54
55
56
# File 'lib/plutonium/wizard/field_capture.rb', line 54

def attribute_schema
  imported_spec ? imported_spec.attribute_schema.merge(@inline_attribute_schema) : @inline_attribute_schema
end

#defined_structured_inputsObject



121
122
123
# File 'lib/plutonium/wizard/field_capture.rb', line 121

def defined_structured_inputs
  instance_structured_inputs
end

#delete_hook(name) ⇒ Object

Pop a recorded hook (used by the DSL when building the Step).



148
# File 'lib/plutonium/wizard/field_capture.rb', line 148

def delete_hook(name) = @hooks.delete(name)

#form_layout(&block) ⇒ Object

form_layout is provided by the FormLayout concern as a class method; the step block runs at instance level, so expose an instance-level shim that records onto this capture's own builder.

Raises:

  • (ArgumentError)


136
137
138
139
140
141
# File 'lib/plutonium/wizard/field_capture.rb', line 136

def form_layout(&block)
  raise ArgumentError, "`form_layout` requires a block" unless block
  builder = Plutonium::Definition::FormLayout::Builder.new
  builder.instance_exec(&block)
  @form_layout = builder.sections.freeze
end

#form_layout_sectionsObject

The form_layout for this step (§7.1 resolution order): an inline form_layout wins; else the layout inherited from a using: source (already filtered to the imported fields); else nil (default single grid).



76
77
78
# File 'lib/plutonium/wizard/field_capture.rb', line 76

def form_layout_sections
  @form_layout || imported_spec&.form_layout
end

#imported_form_validatorsObject

The imported model's form-relevant validators ([[name], options] pairs), replayed onto the typed data class so imported fields render their required/length/etc. metadata. Empty without a using: import. Distinct from validations (inline, runner-bound) so imports aren't double-validated.



91
92
93
# File 'lib/plutonium/wizard/field_capture.rb', line 91

def imported_form_validators
  imported_spec&.form_validators || []
end

#imported_specObject

The resolved using: import surface, or nil. Memoized.



96
97
98
99
100
101
102
# File 'lib/plutonium/wizard/field_capture.rb', line 96

def imported_spec
  return @imported_spec if defined?(@imported_spec)
  @imported_spec =
    if @using_spec
      FieldImporter.resolve(using: @using_spec[:using], opts: @using_spec[:opts])
    end
end

#imported_validate_fnObject

The imported validation runner (=> [messages] over a data slice), or nil when there's no using: import or validate: false. The runner (Task 4) combines this with inline validates.



83
84
85
# File 'lib/plutonium/wizard/field_capture.rb', line 83

def imported_validate_fn
  imported_spec&.validate_fn
end

#inputsObject

The effective input config (=> {options:, block:}) — imported inputs composed with inline input/field declarations, inline winning on conflict. Drives the step form (Task 6).



68
69
70
71
# File 'lib/plutonium/wizard/field_capture.rb', line 68

def inputs
  imported = imported_spec ? imported_spec.inputs : {}
  imported.merge(defined_inputs)
end

#on_rollback(&block) ⇒ Object



129
130
131
# File 'lib/plutonium/wizard/field_capture.rb', line 129

def on_rollback(&block)
  @hooks[:on_rollback] = block
end

#on_submit(&block) ⇒ Object



125
126
127
# File 'lib/plutonium/wizard/field_capture.rb', line 125

def on_submit(&block)
  @hooks[:on_submit] = block
end

#record_using(using, opts) ⇒ Object



143
144
145
# File 'lib/plutonium/wizard/field_capture.rb', line 143

def record_using(using, opts)
  @using_spec = {using:, opts: opts || {}}
end

#structured_input(name, **options, &block) ⇒ Object

Instance-level structured_input: the step block runs at instance level, but the StructuredInputs concern only exposes a class method. Record into a per-instance registry mirroring defined_structured_inputs.



113
114
115
116
117
118
119
# File 'lib/plutonium/wizard/field_capture.rb', line 113

def structured_input(name, **options, &block)
  unless block || options[:using] || options[:fields]
    raise ArgumentError,
      "`structured_input :#{name}` needs a block, `using:`, or `fields:`"
  end
  instance_structured_inputs[name] = {options:, block:}.compact
end

#validates(*args, **options) ⇒ Object

Inline validates — recorded as raw args for the runner (Task 4) to apply.



105
106
107
108
# File 'lib/plutonium/wizard/field_capture.rb', line 105

def validates(*args, **options)
  @validations << [args, options]
  self
end