class Highway::Steps::Parameters::Compound

This class is used in step definition classes to represent a compound parameter of a step that consists of other parameters.

Attributes

children[R]

Child parameters.

@return [Array<Highway::Steps::Parameters::*>]

Public Class Methods

new(name:, required:, defaults: false, children:) click to toggle source

Initialize an instance.

@param name [String] Name of the parameter. @param required [Boolean] Whether parametr is required. @param defaults [Boolean] Whether to construct default value from child parameters. @param children [Array<Highway::Steps::Parameters::*>] Child parameters.

# File lib/highway/steps/parameters/compound.rb, line 22
def initialize(name:, required:, defaults: false, children:)
  @name = name
  @required = required
  @defaults = defaults
  @children = children
end

Public Instance Methods

default() click to toggle source

Default value of the parameter.

@return [Hash, nil]

# File lib/highway/steps/parameters/compound.rb, line 46
def default
  if @defaults
    Utilities::hash_map(@children) { |child| [child.name, child.default] }
  end
end
find_child_for_name(name) click to toggle source

Find a child parameter definition by name.

@param name [String] Name of the parameter

@return [Highway::Steps::Parameters::*]

# File lib/highway/steps/parameters/compound.rb, line 39
def find_child_for_name(name)
  @children.find { |child| child.name == name }
end
typecheck_and_prevalidate(values, interface:, keypath: []) click to toggle source

Typecheck and prevalidate a value of the parameter. This method is used during the initial prevalidation of step parameter values before evaluating all the values.

This method works in a similar way to `typecheck_and_validate` with one difference: if it encounters a single parameter whose value is (or contains) `:ignore` symbol, it doesn't perform any typechecking and validation on it. That way, the caller can specify which values should be fully validated and which should be ignored.

@param value [Object] A value. @param interface [Highway::Interface] An interface instance. @param keypath [Array<String>] A keypath to be used for debugging purposes.

@return [Void]

# File lib/highway/steps/parameters/compound.rb, line 106
def typecheck_and_prevalidate(values, interface:, keypath: [])

  unless values.is_a?(Hash)
    interface.fatal!("Invalid type of value for parameter: '#{Utilities::keypath_to_s(keypath)}'.")
  end

  @children.each { |child|
    if child.is_required? && !values.keys.include?(child.name) && child.default == nil
      interface.fatal!("Missing value for required parameter: '#{Utilities::keypath_to_s(keypath + [child.name])}'.")
    end
  }

  values.keys.each { |name|
    unless find_child_for_name(name)
      expected = @children.map { |child| "'#{child.name}'" }.join(", ")
      interface.fatal!("Unknown parameter: '#{Utilities::keypath_to_s(keypath + [name])}'. Expected one of: [#{expected}].")
    end
  }

  values.each_pair { |name, value|
    if (child = find_child_for_name(name))
      if child.is_a?(Parameters::Compound)
        child.typecheck_and_prevalidate(value, interface: interface, keypath: keypath + [name])
      elsif !Utilities::recursive_include?(value, :ignore)
        child.typecheck_and_validate(value, interface: interface, keypath: keypath + [name])
      end
    end
  }

end
typecheck_and_validate(values, interface:, keypath: []) click to toggle source

Typecheck and validate a value of the parameter.

This method returns typechecked, coerced and validated value or raises a fatal error if value has invalid type, can't be coerced or is othweriwse invalid.

@param value [Object] A value. @param interface [Highway::Interface] An interface instance. @param keypath [Array<String>] A keypath to be used for debugging purposes.

@return [Object]

# File lib/highway/steps/parameters/compound.rb, line 63
def typecheck_and_validate(values, interface:, keypath: [])

  unless values.is_a?(Hash)
    interface.fatal!("Invalid type of value for parameter: '#{Utilities::keypath_to_s(keypath)}'.")
  end

  @children.each { |child|
    if child.is_required? && !values.keys.include?(child.name) && child.default == nil
      interface.fatal!("Missing value for required parameter: '#{Utilities::keypath_to_s(keypath + [child.name])}'.")
    end
  }

  values.keys.each { |name|
    unless find_child_for_name(name)
      expected = @children.map { |child| "'#{child.name}'" }.join(", ")
      interface.fatal!("Unknown parameter: '#{Utilities::keypath_to_s(keypath + [name])}'. Expected one of: [#{expected}].")
    end
  }

  typechecked = Utilities::hash_map(values) { |name, value|
    child = find_child_for_name(name)
    [name, child.typecheck_and_validate(value, interface: interface, keypath: keypath + [name])]
  }

  (default || {}).merge(typechecked)

end