Finitio - In Ruby
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.

Build Status Dependency Status Code Climate Coverage Status


Finitio is a language for capturing information structure. Think "JSON/XML schema" but the right way. For more information about Finitio itself, see

finitio-rb is the ruby binding of Finitio. It allows defining data schemas and validating and coercing data against them in an idiomatic ruby way.


require 'finitio'
require 'json'

# Let load a schema
schema = Finitio::DEFAULT_SYSTEM.parse <<-FIO
    name: String( s | s.strip.size > 0 ),
    at: DateTime

# Let load some JSON document
data = JSON.parse <<-JSON
  { "name": "Finitio", "at": "20142-03-01" }

# And try dressing that data
puts schema.dress(data)

ADTs with internal contracts

finitio-rb tries to provide an idiomatic binding for ruby developers. In particular, it uses a simple convention-over-configuration protocol for information contracts. This protocol is easily described through an example. The following ADT definition:

Color = .Color <rgb> {r: Byte, g: Byte, b: Byte}

expects the following ruby class:

class Color

  # Constructor & internal representation
  def initialize(r, g, b)
    @r, @g, @b = r, g, b
  attr_reader :r, :g, :b

  # Public dresser for the RGB information contract on the class
  def self.rgb(tuple)
    new(tuple[:r], tuple[:g], tuple[:b])

  # Public undresser on the instance
  def to_rgb
    { r: @r, g: @g, b: @b }

  # ...


ADTs with external contracts

When the scenario above is not possible or not wanted (would require core extensions for instance), finitio-rb allows defining ADTs with external contracts. The following ADT definition:

Color = .Color <rgb> {r: Byte, g: Byte, b: Byte} .RgbContract

expected the following ruby module:

module RgbContract

  def self.dress(tuple)[:r], tuple[:g], tuple[:b])

  def self.undress(color)
    { r: color.r, g: color.g, b: color.b }


About representations

The Rep representation function mapping Finitio types to ruby classes is as follows:

# Any type is represented by Ruby's Object class
Rep(.) = Object

# Builtins are represented by the corresponding ruby class
Rep(.Builtin) = Builtin

# Sub types are represented by the same representation as the super type
Rep(SuperType( s | ... )) = Rep(SuperType)

# Unions are represented by the corresponding classes. The guaranteed result
# class is thus the least common super class (^) of the corresponding
# representations of candidate types
Rep(T1 | ... | Tn) = Rep(T1) ^ ... ^ Rep(Tn)

# Sequences are represented through ::Array.
Rep([ElmType]) = Array<Rep(ElmType)>

# Sets are represented through ::Set.
Rep({ElmType}) = Set<Rep(ElmType)>

# Tuples are represented through ruby ::Hash. Attribute names are always
# symbolized
Rep({Ai => Ti}) = Hash<Symbol => Rep(Ti)>

# Relations are represented through ruby ::Set of ::Hash.
Rep({{Ai => Ti}}) = Set<Hash<Symbol => Rep(Ti)>>

# Abstract data types are represented through the corresponding class when
# specified. ADTs behave as Union types if no class is bound.
Rep(.Builtin <rep> ...) = Builtin

About the default system

See lib/finitio/Finitio/default.fio for the precise definition of the default system. In summary,

  • Most ruby native (data) classes are already aliased to avoid explicit use of builtins. In particular, Integer, String, etc.
  • A Boolean union type also hides the TrueClass and FalseClass distinction.
  • Date, Time and DateTime ADTs are also provided that perform common conversions from JSON strings, through iso8601.