Last active
December 25, 2015 07:19
-
-
Save mbj/6938357 to your computer and use it in GitHub Desktop.
Illustrative ducktrap example:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'ducktrap' | |
# Very simple ducktrap without any real world use | |
# | |
# Not transforming. | |
# | |
string = Ducktrap.build do | |
primitive(String) | |
end | |
evaluator = string.call("") | |
evaluator.success? # => true | |
evaluator.output # => "" | |
evaluator = string.call(:foo) | |
evaluator.success? # => false | |
evaluator.output # => Ducktrap::Evaluator::Invalid | |
# A composed example | |
# | |
# Not transforming. | |
# | |
ducktrap = Ducktrap.build do | |
primitive(Array) | |
# stupid dsl node name, must be replaced | |
map do | |
# using another ducktrap node here | |
# | |
# Equivalent to: | |
# | |
# primitive(String) | |
# | |
add(string) | |
end | |
end | |
ducktrap.call([]).success? # => true | |
ducktrap.call([""]).success? # => true | |
ducktrap.call(nil).success? # => false | |
ducktrap.call([nil]).success? # => false | |
# A transforming example | |
# Some PORO to map to | |
class Item | |
include Anima.new(:foo, :bar) | |
end # Item | |
item = Ducktrap.build do | |
primitive(Hash) | |
# Suboptimal dsl I know. | |
hash_transform do | |
# fetch_key => dump_key will be tranform_key(origin => target, origin2 => target2) in future | |
fetch_key('complex_name') do | |
primitive(String) | |
dump_key(:foo) | |
end | |
fetch_key('bar') do | |
primitive(String) | |
dump_key(:bar) | |
end | |
end | |
anima_load(Item) | |
end | |
input = { | |
'complex_name' => 'a value for foo', | |
'bar' => 'a value for bar' | |
} | |
evaluator = item.call(input) | |
evaluator.success? # => true | |
evaluator.output.class # => Item | |
evaluator.output # => <Item @foo='a value for foo', @bar == 'a value for bar' | |
# Inversible properties: | |
item.inverse.call(Item.new(:foo => 'foo', :bar => 'bar')) # => { 'complex_name' => 'foo', 'bar' => 'bar' } | |
# Round trippable on node level | |
item.inverse.inverse == item # => true | |
# Round trippable semantics | |
item.inverse.inverse.call(input) == item.call(input) # => true | |
# A composed transforming example: | |
class SomeOtherItem | |
include Anima.new(:items, :title) | |
end | |
some_other_item = Ducktrap.build do | |
primitive(Hash) | |
hash_transform do | |
fetch_key('items') do | |
map do | |
add(item) | |
end | |
dump_key(:item) | |
end | |
fetch_key('title') do | |
primitive(String) | |
dump_key(:title) | |
end | |
end | |
end | |
input = { | |
'items' => [ | |
{ | |
'complex_name' => 'A complex name', | |
'bar' => 'A value for bar' | |
}, | |
{ | |
'complex_name' => 'Another complex name', | |
'bar' => 'Another value for bar' | |
} | |
], | |
'title' => 'A title' | |
} | |
evaluator = some_other_item.call(input) | |
evaluator.success? # => true | |
evaluator.output # => <SomeOtherItem @items=[<Item @foo='A complex name'> ....] @title='A title'> | |
# Error behavior | |
input = { | |
'items' => [ | |
nil, # Note incompatible input here | |
{ | |
'complex_name' => 'A complex name', | |
'bar' => 'A value for bar' | |
}, | |
{ | |
'complex_name' => 'Another complex name', | |
'bar' => 'Another value for bar' | |
} | |
], | |
'title' => 'A title' | |
} | |
evaluator = some_other_item.call(input) | |
evaluator.success? # => false | |
# Precise error location here: | |
evaluator.output # => #<Ducktrap::Error context=#<Ducktrap::Node::Hash::Transform::Evaluator context=#<Ducktr... | |
# And pretty dumpable/inspectable of course :D | |
# | |
# Yeah this is TOO verbose. But guys this is a 0.0.1 version and many times more than a: | |
# | |
# NoMethodError: undefined method `each' for nil:NilClass | |
# With a stacktrace NOT showing input data ;) | |
# | |
evaluator.output.pretty_dump | |
# prints: | |
# Ducktrap::Error | |
# input: {"items"=>[nil, {"complex_name"=>"A complex name", "bar"=>"A value for bar"}, {"complex_name"=>"Another complex name", "bar"=>"Another value for bar"}], "title"=>"A title"} | |
# context: | |
# Ducktrap::Node::Hash::Transform::Evaluator | |
# input: {"items"=>[nil, {"complex_name"=>"A complex name", "bar"=>"A value for bar"}, {"complex_name"=>"Another complex name", "bar"=>"Another value for bar"}], "title"=>"A title"} | |
# error: | |
# Ducktrap::Error | |
# input: {"items"=>[nil, {"complex_name"=>"A complex name", "bar"=>"A value for bar"}, {"complex_name"=>"Another complex name", "bar"=>"Another value for bar"}], "title"=>"A title"} | |
# context: | |
# Ducktrap::Node::Key::Fetch::Evaluator | |
# input: {"items"=>[nil, {"complex_name"=>"A complex name", "bar"=>"A value for bar"}, {"complex_name"=>"Another complex name", "bar"=>"Another value for bar"}], "title"=>"A title"} | |
# error: | |
# Ducktrap::Error | |
# input: {"items"=>[nil, {"complex_name"=>"A complex name", "bar"=>"A value for bar"}, {"complex_name"=>"Another complex name", "bar"=>"Another value for bar"}], "title"=>"A title"} | |
# context: | |
# Ducktrap::Node::Block::Evaluator | |
# input: [nil, {"complex_name"=>"A complex name", "bar"=>"A value for bar"}, {"complex_name"=>"Another complex name", "bar"=>"Another value for bar"}] | |
# error: | |
# Ducktrap::Error | |
# input: [nil, {"complex_name"=>"A complex name", "bar"=>"A value for bar"}, {"complex_name"=>"Another complex name", "bar"=>"Another value for bar"}] | |
# context: | |
# Ducktrap::Node::Map::Evaluator | |
# input: [nil, {"complex_name"=>"A complex name", "bar"=>"A value for bar"}, {"complex_name"=>"Another complex name", "bar"=>"Another value for bar"}] | |
# error: | |
# Ducktrap::Error | |
# input: [nil, {"complex_name"=>"A complex name", "bar"=>"A value for bar"}, {"complex_name"=>"Another complex name", "bar"=>"Another value for bar"}] | |
# context: | |
# Ducktrap::Node::Block::Evaluator | |
# input: nil | |
# error: | |
# Ducktrap::Error | |
# input: nil | |
# context: | |
# Ducktrap::Node::Block::Evaluator | |
# input: nil | |
# error: | |
# Ducktrap::Error | |
# input: nil | |
# context: | |
# Ducktrap::Evaluator::Invalid | |
# input: nil | |
# error: | |
# Ducktrap::Error | |
# input: nil | |
# context: | |
# Ducktrap::Node::Primitive | |
# primitive: Hash | |
# context: | |
# Ducktrap::Node::Primitive | |
# primitive: Hash | |
# context: | |
# Ducktrap::Node::Block | |
# body: | |
# Ducktrap::Node::Primitive | |
# primitive: Hash | |
# Ducktrap::Node::Hash::Transform | |
# body: | |
# Ducktrap::Node::Key::Fetch | |
# key: "complex_name" | |
# operand: | |
# Ducktrap::Node::Block | |
# body: | |
# Ducktrap::Node::Primitive | |
# primitive: String | |
# Ducktrap::Node::Key::Dump | |
# key: :foo | |
# operand: | |
# Ducktrap::Node::Noop | |
# Ducktrap::Node::Key::Fetch | |
# key: "bar" | |
# operand: | |
# Ducktrap::Node::Block | |
# body: | |
# Ducktrap::Node::Primitive | |
# primitive: String | |
# Ducktrap::Node::Key::Dump | |
# key: :bar | |
# operand: | |
# Ducktrap::Node::Noop | |
# Ducktrap::Node::Anima::Load | |
# model: Item | |
# context: | |
# Ducktrap::Node::Block | |
# body: | |
# Ducktrap::Node::Block | |
# body: | |
# Ducktrap::Node::Primitive | |
# primitive: Hash | |
# Ducktrap::Node::Hash::Transform | |
# body: | |
# Ducktrap::Node::Key::Fetch | |
# key: "complex_name" | |
# operand: | |
# Ducktrap::Node::Block | |
# body: | |
# Ducktrap::Node::Primitive | |
# primitive: String | |
# Ducktrap::Node::Key::Dump | |
# key: :foo | |
# operand: | |
# Ducktrap::Node::Noop | |
# Ducktrap::Node::Key::Fetch | |
# key: "bar" | |
# operand: | |
# Ducktrap::Node::Block | |
# body: | |
# Ducktrap::Node::Primitive | |
# primitive: String | |
# Ducktrap::Node::Key::Dump | |
# key: :bar | |
# operand: | |
# Ducktrap::Node::Noop | |
# Ducktrap::Node::Anima::Load | |
# model: Item | |
# context: | |
# Ducktrap::Node::Map | |
# operand: | |
# Ducktrap::Node::Block | |
# body: | |
# Ducktrap::Node::Block | |
# body: | |
# Ducktrap::Node::Primitive | |
# primitive: Hash | |
# Ducktrap::Node::Hash::Transform | |
# body: | |
# Ducktrap::Node::Key::Fetch | |
# key: "complex_name" | |
# operand: | |
# Ducktrap::Node::Block | |
# body: | |
# Ducktrap::Node::Primitive | |
# primitive: String | |
# Ducktrap::Node::Key::Dump | |
# key: :foo | |
# operand: | |
# Ducktrap::Node::Noop | |
# Ducktrap::Node::Key::Fetch | |
# key: "bar" | |
# operand: | |
# Ducktrap::Node::Block | |
# body: | |
# Ducktrap::Node::Primitive | |
# primitive: String | |
# Ducktrap::Node::Key::Dump | |
# key: :bar | |
# operand: | |
# Ducktrap::Node::Noop | |
# Ducktrap::Node::Anima::Load | |
# model: Item | |
# context: | |
# Ducktrap::Node::Block | |
# body: | |
# Ducktrap::Node::Map | |
# operand: | |
# Ducktrap::Node::Block | |
# body: | |
# Ducktrap::Node::Block | |
# body: | |
# Ducktrap::Node::Primitive | |
# primitive: Hash | |
# Ducktrap::Node::Hash::Transform | |
# body: | |
# Ducktrap::Node::Key::Fetch | |
# key: "complex_name" | |
# operand: | |
# Ducktrap::Node::Block | |
# body: | |
# Ducktrap::Node::Primitive | |
# primitive: String | |
# Ducktrap::Node::Key::Dump | |
# key: :foo | |
# operand: | |
# Ducktrap::Node::Noop | |
# Ducktrap::Node::Key::Fetch | |
# key: "bar" | |
# operand: | |
# Ducktrap::Node::Block | |
# body: | |
# Ducktrap::Node::Primitive | |
# primitive: String | |
# Ducktrap::Node::Key::Dump | |
# key: :bar | |
# operand: | |
# Ducktrap::Node::Noop | |
# Ducktrap::Node::Anima::Load | |
# model: Item | |
# Ducktrap::Node::Key::Dump | |
# key: :item | |
# operand: | |
# Ducktrap::Node::Noop | |
# context: | |
# Ducktrap::Node::Key::Fetch | |
# key: "items" | |
# operand: | |
# Ducktrap::Node::Block | |
# body: | |
# Ducktrap::Node::Map | |
# operand: | |
# Ducktrap::Node::Block | |
# body: | |
# Ducktrap::Node::Block | |
# body: | |
# Ducktrap::Node::Primitive | |
# primitive: Hash | |
# Ducktrap::Node::Hash::Transform | |
# body: | |
# Ducktrap::Node::Key::Fetch | |
# key: "complex_name" | |
# operand: | |
# Ducktrap::Node::Block | |
# body: | |
# Ducktrap::Node::Primitive | |
# primitive: String | |
# Ducktrap::Node::Key::Dump | |
# key: :foo | |
# operand: | |
# Ducktrap::Node::Noop | |
# Ducktrap::Node::Key::Fetch | |
# key: "bar" | |
# operand: | |
# Ducktrap::Node::Block | |
# body: | |
# Ducktrap::Node::Primitive | |
# primitive: String | |
# Ducktrap::Node::Key::Dump | |
# key: :bar | |
# operand: | |
# Ducktrap::Node::Noop | |
# Ducktrap::Node::Anima::Load | |
# model: Item | |
# Ducktrap::Node::Key::Dump | |
# key: :item | |
# operand: | |
# Ducktrap::Node::Noop | |
# context: | |
# Ducktrap::Node::Hash::Transform | |
# body: | |
# Ducktrap::Node::Key::Fetch | |
# key: "items" | |
# operand: | |
# Ducktrap::Node::Block | |
# body: | |
# Ducktrap::Node::Map | |
# operand: | |
# Ducktrap::Node::Block | |
# body: | |
# Ducktrap::Node::Block | |
# body: | |
# Ducktrap::Node::Primitive | |
# primitive: Hash | |
# Ducktrap::Node::Hash::Transform | |
# body: | |
# Ducktrap::Node::Key::Fetch | |
# key: "complex_name" | |
# operand: | |
# Ducktrap::Node::Block | |
# body: | |
# Ducktrap::Node::Primitive | |
# primitive: String | |
# Ducktrap::Node::Key::Dump | |
# key: :foo | |
# operand: | |
# Ducktrap::Node::Noop | |
# Ducktrap::Node::Key::Fetch | |
# key: "bar" | |
# operand: | |
# Ducktrap::Node::Block | |
# body: | |
# Ducktrap::Node::Primitive | |
# primitive: String | |
# Ducktrap::Node::Key::Dump | |
# key: :bar | |
# operand: | |
# Ducktrap::Node::Noop | |
# Ducktrap::Node::Anima::Load | |
# model: Item | |
# Ducktrap::Node::Key::Dump | |
# key: :item | |
# operand: | |
# Ducktrap::Node::Noop | |
# Ducktrap::Node::Key::Fetch | |
# key: "title" | |
# operand: | |
# Ducktrap::Node::Block | |
# body: | |
# Ducktrap::Node::Primitive | |
# primitive: String | |
# Ducktrap::Node::Key::Dump | |
# key: :title | |
# operand: | |
# Ducktrap::Node::Noop |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment