Module: Assistant::InputBuilder::DefaultOption

Included in:
Assistant::InputBuilder
Defined in:
lib/assistant/input_builder/default_option.rb

Overview

M1: class-time gate for the default: option — fail fast on illegal providers, warn on shared mutable literals. Pure side-effects, no interaction with the per-class definitions registry.

Instance Method Summary collapse

Instance Method Details

#process_default_option(name:, default:) ⇒ void

This method returns an undefined value.

Run the class-time gate for an input's default: provider: reject illegal providers, warn on shared mutable literals.

Parameters:

  • name (Symbol)

    input name

  • default (Object, Proc)

    the literal value or zero-arity Proc

Raises:

  • (ArgumentError)

    when default is callable but not a zero-arity Proc



14
15
16
17
# File 'lib/assistant/input_builder/default_option.rb', line 14

def process_default_option(name:, default:)
  validate_default!(name:, default:)
  warn_on_mutable_default(name:, default:)
end

#validate_default!(name:, default:) ⇒ Object

M1: a default: provider must be either a literal value or a zero-arity Proc/Lambda. Anything else that responds to #call (a Method object, a custom callable) is rejected at class-definition time.



23
24
25
26
27
28
29
# File 'lib/assistant/input_builder/default_option.rb', line 23

def validate_default!(name:, default:)
  if default.is_a?(Proc) && !default.arity.zero? && default.arity != -1
    raise ArgumentError, "default: for input :#{name} must be a zero-arity Proc, got arity #{default.arity}"
  elsif !default.is_a?(Proc) && default.respond_to?(:call)
    raise ArgumentError, "default: for input :#{name} must be a literal or a zero-arity Proc, not a #{default.class}"
  end
end

#warn_on_mutable_default(name:, default:) ⇒ Object

M1: warn when a mutable literal default (unfrozen Array/Hash) is used — such a default is shared across every instance of the Service subclass and almost never what the author wants. Frozen literals and Procs are safe and pass silently.



35
36
37
38
39
40
# File 'lib/assistant/input_builder/default_option.rb', line 35

def warn_on_mutable_default(name:, default:)
  return unless (default.is_a?(Array) || default.is_a?(Hash)) && !default.frozen?

  Kernel.warn("assistant: input :#{name} has a mutable #{default.class} default; " \
              'use `default: -> { ... }` to avoid sharing state across instances')
end