Finitio - In Ruby
Ruby Gherkin Common Lisp
Switch branches/tags
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
examples
features
lib
spec
tasks
.coveralls.yml
.gitignore
.travis.yml
CHANGELOG.md
Gemfile
Gemfile.lock
LICENCE.md
Manifest.txt
README.md
Rakefile
finitio.gemspec
finitio.noespec

README.md

Build Status Dependency Status Code Climate Coverage Status

Finitio(-rb)

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

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.

Example

require 'finitio'
require 'json'

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

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

# 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
  end
  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])
  end

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

  # ...

end

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)
    Color.new(tuple[:r], tuple[:g], tuple[:b])
  end

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

end

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.