Sha256: 0cf1239e3db49c2df2eca4da516295420950e6281a14bc781dfcc5097e17874f

Contents?: true

Size: 1.68 KB

Versions: 3

Compression:

Stored size: 1.68 KB

Contents

module DataModel
	# Or type, allows for value to be one of several types
	# Types will be tried in order. The first type to succeed will be used.
	# If all types fail, the or type fails
	#
	# @example
	#   [:or, :string, [:array, :string]]
	class Builtin::Or < Type
		include Errors
		include Logging

		# Arguments for this type
		class Arguments < Struct
			prop :optional, :boolean, default: false
		end

		# support either :string shorthand or [:string, {optional: true}]
		# @param params [Array<untyped>] the params to configure this type
		# @return [void]
		def configure(params)
			if params.first.is_a?(Array)
				params = params.first
			end

			@child_types = []

			nodes = params.map { |p| Scanner.scan(Array(p)) }
			for node in nodes
				type = instantiate(node.type, args: node.args, params: node.params)
				@child_types << type
			end
		end

		# read a value, and validate it
		# @param val [Object] the value to read
		# @param coerce [Boolean] whether to coerce the value
		# @return [Array(Object, Error)] the result of reading the value
		def read(val, coerce: false)
			args = Arguments.new(type_args)
			err = Error.new
			child_names = @child_types.map(&:type_name)

			log.debug("coerce: #{coerce} or type #{child_names} with value #{val}")

			# optional and missing
			if !args.optional && val.nil?
				err.add(missing_error(child_names))
			end

			# when missing, return early
			if val.nil?
				return [val, err]
			end

			valid = false

			for type in @child_types
				val, err = type.read(val, coerce: coerce)
				if err.empty?
					valid = true
					break
				end
			end

			if !valid
				err.add(type_error(child_names, val))
			end

			# done
			return [val, err]
		end
	end
end

Version data entries

3 entries across 3 versions & 1 rubygems

Version Path
data_model-0.6.1 lib/data_model/builtin/or.rb
data_model-0.6.0 lib/data_model/builtin/or.rb
data_model-0.5.0 lib/data_model/builtin/or.rb