strict is a rudimentary static typesystem for ruby objects - it enables easy validation of individual ruby objects and Hash sets.
For an example of validation:
require ‘typestrict’
class Rectangle
include Strict
def initialize(p)
validate_map!({
:width => :natural_number,
:height => :natural_number,
:color => :hex_color
}, p)
@width = p[:width]
@height = p[:height]
@color = p[:color]
end
def set_dimensions(dimensions)
validate_map!({
:width => :natural_number,
:height => :natural_number
}, dimensions) #checks for the presence + validity of all declared parameters
@height = dimensions[:height]
@width = dimensions[:width]
end
def scale_height(scale_coefficent)
enforce!(:float, scale_coefficent)
return scale_coefficent*@height #alays valid
end
end
Strict defines a number of ‘super-types’, currently which are: :natural_number :float :boolean :integer :numeric :character :procedure :string_array :numeric_array :float_array :integer_array :hex_color
New supertypes may be registered with the register_supertype as follows:
register_supertype(:char, proc {|data, context| enforce_primitive!(String, data); catch_error(“#{data.inspect} must be a single character in length”) unless (data.size == 1)}) registered a dynamic handler for supertype: character
> nil
irb(main)> enforce!(:char, “a”)
> “a”
irb(main)> enforce!(:char, “aa”) Strict::TypeError: TypeError caught: “aa” must be a single character in length
from (irb):6 from ./str.rb:148:in ‘call’ from ./str.rb:148:in ‘enforce!’ from (irb):8
irb(main):009:0> enforce!(:char, “x”)
> “x”
Strict simply implements an extendable static type-checker over dynamic ruby objects. For an example of validation with troublesome datasets:
#enforce!(:string_array, [“one”, “two”, 3, “four”]) #./strict.rb:3:in ‘enforce_primitive!’: 3 must be of type String (RuntimeError)
type_matrix = {
:fruit => [:apple, :orange, :banana],
:height => :natural_number,
:width => :float,
:broken => :boolean
}
invalid_data =
:fruit => :pear,
:height => -1,
:width => 100,
:broken => 1
validate_map!(type_matrix, invalid_data) #./strict.rb:27:in ‘enforce_weak_primitives!’: 1 must be of one of the types of [TrueClass, FalseClass] (RuntimeError) #./strict.rb:3:in ‘enforce_primitive!’: 10 must be of type Float (RuntimeError) #./strict.rb:38:in ‘enforce!’: pear should take on a value within [:apple, :orange, :banana] (RuntimeError) #./strict.rb:53:in ‘enforce!’: -1 must be > 0 (RuntimeError)
A valid dataset for this type_matrix would be:
valid_data = {
:fruit => :apple,
:height => 200,
:width => 100.011,
:broken => true
}
validate_map!(type_matrix, invalid_data) # => all checks pass