Project

infer-type

0.0
The project is in a healthy, maintained state
If a string is a representation of another class, such as "1", converts it to that other class. Works for basic Ruby types and can be extended.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Development

~> 1.17, >= 1.17.3
~> 0.14, >= 0.14.1
~> 3.4, >= 3.4.0
~> 3.11, >= 3.11.0
 Project Readme

InferType

A simple and lightweight Ruby utility that converts strings into their most appropriate Ruby types using a pluggable, priority-based parser system.

  • Detects common Ruby types (list below)
  • You can specify a smaller list to detect when you call parse()
  • You can define custom parsers to detect other types of any kind
  • Priority order of detection is configurable

Basic usage

InferType.parse("123")
# => 123 # Integer

InferType.parse("1.5")
# => 1.5 # Float

InferType.parse("hello")
# => "hello" # remains a string as no other type detected

Parsers

InferType runs through a series of Parser classes in priority order, which each get a chance to detect and parse the string into the type that they're concerned with, e.g. Integer or Date.

InferType comes with default parsers. It will detect, in order:

  • Integer
  • Float
  • True
  • False
  • Nil
  • Date (if valid)
  • Time (if valid)

You can define your own class inheriting from InferType::Parser to detect other types -- see Custom Parsers below.

Restricting Types

You can explicitly control which types are allowed for a parse operation:

# Assuming a parser for BigDecimal has been registered...
InferType.parse("1000", BigDecimal, Date, Time)
# => 0.1e4 # BigDecimal. Integer parser wasn't called.

When specifying the types to look for explicitly like this, you are also specifying the priority order that will be used.

Parser Priority

You can modify any parser's priority order with:

InferType.prioritise(DateParser) # move to front
InferType.deprioritise(DateParser) # move to back
# American spellings also work
InferType.prioritize(DateParser, IntegerParser)
# moves both to front in this order

A parser can also be deregistered:

InferType.deregister(IntegerParser)
# integers will no longer be parsed

Parser Settings

Parsers may expose settings that let you modify how they parse. These are the settings available for built-in parsers (showing their defaults):

Integer

# Allow numbers with leading zeros like "00001" = 1
ALLOW_LEADING_ZERO = true
# Allow leading plus sign like "+2" = 2
ALLOW_LEADING_PLUS = true

Float

# If false, "1" is NOT considered a Float (must be "1.0" etc.)
ALLOW_INTEGER = true
# Allow exponential notation like 1e3 or 1.5E-2
ALLOW_EXPONENTIAL = true
# Allow special values: NaN, Infinity
ALLOW_SPECIAL_VALUES = false

True, False, Nil

# In strict mode, only accept "true", "false", "nil" to mean those respective things
# In relaxed mode, other similar terms are also allowed e.g. "on", "no", "null"
STRICT = true
# If true, case sensitive
CASE_SENSITIVE = false

Time

# If timezone offset is missing from a Time string, assume UTC
# If false, the system's local timezone will be used
DEFAULT_UTC = true

Custom Parsers

Custom parsers must be registered:

InferType.register(BigDecimalParser)
InferType.register(MyCustomIntegerParser)

By default a newly registered parser either:

  • replaces the parser already registered to deal with that type, in the same priority position; or
  • goes to last place in priority order.

A parser must:

  1. Subclass InferType::Parser
  2. Declare exactly one class it detects with detects <Class>
  3. Implement #parse(str)
  4. Use failure or success(value) methods to return
  5. If it parses successfully it must return the type of object declared in detects
  6. Never raise on invalid input

Example

class UUIDParser < InferType::Parser
	detects MyCustomUUIDClass

	UUID_REGEX = /\A[0-9a-f\-]{36}\z/i

	def parse(str)
		return failure unless UUID_REGEX.match?(str)
		success(MyCustomUUIDClass.new(str))
	end
end

InferType.register(UUIDParser)