class Builder

Builds immutable parameter models using a field DSL.

Definitions

def initialize(parser: Parser.default, types: TYPES, strict: true)

Initialize a parameter model builder.

Signature

parameter parser Parser

The content parser.

parameter types Hash

The available type conversions.

parameter strict Boolean

Whether unknown fields should produce validation errors.

Implementation

def initialize(parser: Parser.default, types: TYPES, strict: true)
	@parser = parser
	@types = types
	@strict = strict
	@fields = {}
end

def build(&block)

Evaluate fields and construct an immutable parameter model.

Signature

returns Model

The frozen parameter model.

Implementation

def build(&block)
	instance_eval(&block)
	return Model.new(@parser, @fields, strict: @strict).freeze
end

def field(name, type = Object, required: false, nullable: false)

Declare a scalar field.

Signature

parameter name String

The field name.

parameter type Module | #call

The expected value type or converter.

parameter required Boolean

Whether the field must be present.

parameter nullable Boolean

Whether the field may be nil.

returns Field

The field.

Implementation

def field(name, type = Object, required: false, nullable: false)
	return add(ValueField.new(name, resolve(type), required:, nullable:))
end

def upload(name, required: false, multiple: false, accept: nil, size_limit: nil)

Declare a streaming file upload.

Signature

parameter name String

The upload field name.

parameter required Boolean

Whether at least one handled upload must be present.

parameter multiple Boolean

Whether the field accepts multiple uploads using anonymous array notation.

parameter accept Protocol::Media::Set | Array(String | Protocol::Media::Range) | Nil

The accepted media ranges.

parameter size_limit Integer | Nil

The maximum accepted upload size.

returns Field

The upload field.

Implementation

def upload(name, required: false, multiple: false, accept: nil, size_limit: nil)
	if size_limit && size_limit < 0
		raise ArgumentError, "Upload size limit must be non-negative!"
	end
	
	if accept
		accept = Protocol::Media::Set.for(accept)
	end
	
	return add(UploadField.new(name, required:, multiple:, accept:, size_limit:))
end

def enumeration(*values, **options)

Construct an enumeration converter from accepted values or an input-to-output mapping.

Signature

parameter values Array(Object)

The accepted values.

parameter options Hash

Additional input-to-output mappings.

returns Enumeration

The enumeration converter.

Implementation

def enumeration(*values, **options)
	return Enumeration.build(*values, **options)
end

def array(name, type = nil, required: false, nullable: false, strict: @strict, &block)

Declare an array of scalar values or nested argument hierarchies.

Signature

parameter name String

The array field name.

parameter type Module | #call | Nil

The expected element type or converter.

parameter required Boolean

Whether the array must be present.

parameter nullable Boolean

Whether the array may be nil.

parameter strict Boolean

Whether unknown nested fields should produce validation errors.

returns Field

The array field.

Implementation

def array(name, type = nil, required: false, nullable: false, strict: @strict, &block)
	if block
		# A block defines the element shape and cannot be combined with conversion:
		if type
			raise ArgumentError, "An array cannot declare both an element type and nested fields!"
		end
		
		model = nested_model(strict:, &block)
	elsif type
		type = resolve(type)
	end
	
	return add(ArrayField.new(name, type, model, required:, nullable:))
end

def nested(name, required: false, nullable: false, strict: @strict, &block)

Declare a nested argument hierarchy. Without a block, all nested values are accepted.

Signature

parameter name String

The nested field name.

parameter required Boolean

Whether the field must be present.

parameter nullable Boolean

Whether the field may be nil.

parameter strict Boolean

Whether unknown nested fields should produce validation errors.

returns Field

The nested field.

Implementation

def nested(name, required: false, nullable: false, strict: @strict, &block)
	if block
		model = nested_model(strict:, &block)
	end
	
	return add(NestedField.new(name, model, required:, nullable:))
end