The old soon to be unmaintained ducktrap. Successor is mbj/morpher
Ruby
Switch branches/tags
Nothing to show
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
config
lib
spec
.circle.yml
.gitignore
.rspec
.travis.yml
Gemfile
Gemfile.devtools
Guardfile
LICENSE
README.md
Rakefile
TODO
circle.yml
ducktrap.gemspec

README.md

WARNING

This repository/lib is unlikely to receive any issues / bugfixes. The ducktrap idea had grown into morpher.

With the first release of morpher, ducktrap will be unmaintained.

ducktrap

Build Status Dependency Status Code Climate

Ducktrap is a spike for a data transformation algebra. The main idea is to define the transformations with composable blocks that allow to generate an inverse transformation.

It can be used at various places:

  • Domain to JSON and vice versa, for building rest style APIS
  • Domain to document db and vice versa, for buidling mappers
  • Form processing
  • ...

Installation

There is no gem release.

Examples

For slightly more details, have a look at this gist for now.

A simple real world scenario would probably look something like this:

require 'anima'
require 'ducktrap'

class Address
  include Anima.new(:id, :city, :zip)

  TRAP = Ducktrap.build do
    primitive(Hash)
    hash_transform do
      fetch_key(:id) do
        primitive(Integer)
        dump_key(:id)
      end

      fetch_key(:city) do
        primitive(String)
        dump_key(:city)
      end

      fetch_key(:zip) do
        primitive(Integer)
        dump_key(:zip)
      end
    end
    anima_load(Address)
  end
end

class Task
  include Anima.new(:id, :name)

  TRAP = Ducktrap.build do
    primitive(Hash)
    hash_transform do
      fetch_key(:id) do
        primitive(Integer)
        dump_key(:id)
      end

      fetch_key(:name) do
        primitive(String)
        dump_key(:name)
      end
    end
    anima_load(Task)
  end
end

class Person
  include Anima.new(:id, :name, :address, :tasks)

  TRAP = Ducktrap.build do
    primitive(Hash)
    hash_transform do
      fetch_key(:id) do
        primitive(Integer)
        dump_key(:id)
      end

      fetch_key(:name) do
        primitive(String)
        dump_key(:name)
      end

      fetch_key(:address) do
        add(Address::TRAP)
        dump_key(:address)
      end

      fetch_key(:tasks) do
        map { add(Task::TRAP) }
        dump_key(:tasks)
      end
    end
    anima_load(Person)
  end
end

t_hash = {id: 1, name: 'DOIT'}
a_hash = {id: 1, city: 'Linz', zip: 4040}
p_hash = {id: 1, name: 'John', address: a_hash, tasks: [t_hash]}

result = Person::TRAP.call(p_hash)

if result.success?
  person = result.output
  puts person.inspect
  # => #<Person id=1 name="John" address=#<Address id=1 city="Linz" zip=4040> tasks=[#<Task id=1 name="DOIT">]>

  result = Person::TRAP.inverse.call(person)
  if result.success?
    p_hash = result.output
    puts p_hash.inspect
    # => {:id=>1, :name=>"John", :address=>{:id=>1, :city=>"Linz", :zip=>4040}, :tasks=>[{:id=>1, :name=>"DOIT"}]}
  else
    puts result.pretty_dump
  end
else
  puts result.pretty_dump
end

Credits

Contributing

  • Fork the project.
  • Make your feature addition or bug fix.
  • Add tests for it. This is important so I don't break it in a future version unintentionally.
  • Commit, do not mess with Rakefile or version (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
  • Send me a pull request. Bonus points for topic branches.

License

See LICENSE file.