{"id":13747458,"url":"https://github.com/solnic/transproc","last_synced_at":"2025-05-09T08:33:16.454Z","repository":{"id":25032865,"uuid":"28452477","full_name":"solnic/transproc","owner":"solnic","description":"The project was ported to dry-rb/dry-transformer","archived":true,"fork":false,"pushed_at":"2019-12-28T12:29:22.000Z","size":456,"stargazers_count":410,"open_issues_count":0,"forks_count":29,"subscribers_count":13,"default_branch":"master","last_synced_at":"2024-05-12T00:40:49.465Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"jgraph/drawio-diagrams","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/solnic.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-12-24T15:15:27.000Z","updated_at":"2024-05-11T09:29:30.000Z","dependencies_parsed_at":"2022-08-23T11:31:26.351Z","dependency_job_id":null,"html_url":"https://github.com/solnic/transproc","commit_stats":null,"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/solnic%2Ftransproc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/solnic%2Ftransproc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/solnic%2Ftransproc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/solnic%2Ftransproc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/solnic","download_url":"https://codeload.github.com/solnic/transproc/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224849243,"owners_count":17380078,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-03T06:01:29.825Z","updated_at":"2024-11-15T21:30:31.749Z","avatar_url":"https://github.com/solnic.png","language":"Ruby","funding_links":[],"categories":["Ruby"],"sub_categories":[],"readme":"# :warning: The project was ported to [dry-rb/dry-transformer](https://github.com/dry-rb/dry-transformer) :warning:\n\n[gem]: https://rubygems.org/gems/transproc\n[travis]: https://travis-ci.org/solnic/transproc\n[codeclimate]: https://codeclimate.com/github/solnic/transproc\n[coveralls]: https://coveralls.io/r/solnic/transproc\n[inchpages]: https://inch-ci.org/github/solnic/transproc\n\n# Transproc\n\n[![Gem Version](https://badge.fury.io/rb/transproc.svg)][gem]\n[![Build Status](https://travis-ci.org/solnic/transproc.svg?branch=master)][travis]\n[![Code Climate](https://codeclimate.com/github/solnic/transproc/badges/gpa.svg)][codeclimate]\n[![Test Coverage](https://codeclimate.com/github/solnic/transproc/badges/coverage.svg)][codeclimate]\n[![Inline docs](https://inch-ci.org/github/solnic/transproc.svg?branch=master)][inchpages]\n\nTransproc is a small library that allows you to compose procs into a functional pipeline using left-to-right function composition.\n\nThe approach came from Functional Programming, where simple functions are composed into more complex functions in order to transform some data. It works like `|\u003e` in Elixir\nor `\u003e\u003e` in F#.\n\n`transproc` provides a mechanism to define and compose transformations,\nalong with a number of built-in transformations.\n\nIt's currently used as the data mapping backend in [Ruby Object Mapper](https://rom-rb.org).\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'transproc'\n```\n\nAnd then execute:\n\n    $ bundle\n\nOr install it yourself as:\n\n    $ gem install transproc\n\n## Basics\n\nSimple transformations are defined as easy as:\n\n```ruby\nincrement = Transproc::Function.new(-\u003e (data) { data + 1 })\nincrement[1] # =\u003e 2\n```\n\nIt's easy to compose transformations:\n\n```ruby\nto_string = Transproc::Function.new(:to_s.to_proc)\n(increment \u003e\u003e to_string)[1] # =\u003e '2'\n```\n\nIt's easy to pass additional arguments to transformations:\n\n```ruby\nappend = Transproc::Function.new(-\u003e (value, suffix) { value + suffix })\nappend_bar = append.with('_bar')\nappend_bar['foo'] # =\u003e foo_bar\n```\n\nOr even accept another transformation as an argument:\n\n```ruby\nmap_array = Transproc::Function.new(-\u003e (array, fn) { array.map(\u0026fn) })\nmap_array.with(to_string).call([1, 2, 3]) # =\u003e ['1', '2', '3']\n```\n\nTo improve this low-level definition, you can use class methods\nwith `Transproc::Registry`:\n\n```ruby\nM = Module.new do\n  extend Transproc::Registry\n\n  def self.to_string(value)\n    value.to_s\n  end\n\n  def self.map_array(array, fn)\n    array.map(\u0026fn)\n  end\nend\nM[:map_array, M[:to_string]].([1, 2, 3]) # =\u003e ['1', '2', '3']\n```\n\n### Built-in transformations\n\n`transproc` comes with a lot of built-in functions. They come in the form of\nmodules with class methods, which you can import into a registry:\n\n* [Coercions](https://www.rubydoc.info/gems/transproc/Transproc/Coercions)\n* [Array transformations](https://www.rubydoc.info/gems/transproc/Transproc/ArrayTransformations)\n* [Hash transformations](https://www.rubydoc.info/gems/transproc/Transproc/HashTransformations)\n* [Class transformations](https://www.rubydoc.info/gems/transproc/Transproc/ClassTransformations)\n* [Proc transformations](https://www.rubydoc.info/gems/transproc/Transproc/ProcTransformations)\n* [Conditional](https://www.rubydoc.info/gems/transproc/Transproc/Conditional)\n* [Recursion](https://www.rubydoc.info/gems/transproc/Transproc/Recursion)\n\nYou can import everything with:\n\n```ruby\nmodule T\n  extend Transproc::Registry\n\n  import Transproc::Coercions\n  import Transproc::ArrayTransformations\n  import Transproc::HashTransformations\n  import Transproc::ClassTransformations\n  import Transproc::ProcTransformations\n  import Transproc::Conditional\n  import Transproc::Recursion\nend\nT[:to_string].call(:abc) # =\u003e 'abc'\n```\n\nOr import selectively with:\n\n```ruby\nmodule T\n  extend Transproc::Registry\n\n  import :to_string, from: Transproc::Coercions, as: :stringify\nend\nT[:stringify].call(:abc) # =\u003e 'abc'\nT[:to_string].call(:abc)\n# =\u003e Transproc::FunctionNotFoundError: No registered function T[:to_string]\n```\n\n### Transformer\n\nTransformer is a class-level DSL for composing transformation pipelines,\nfor example:\n\n```ruby\nT = Class.new(Transproc::Transformer) do\n  map_array do\n    symbolize_keys\n    rename_keys user_name: :name\n    nest :address, [:city, :street, :zipcode]\n  end\nend\n\nT.new.call(\n  [\n    { 'user_name' =\u003e 'Jane',\n      'city' =\u003e 'NYC',\n      'street' =\u003e 'Street 1',\n      'zipcode' =\u003e '123'\n    }\n  ]\n)\n# =\u003e [{:name=\u003e\"Jane\", :address=\u003e{:city=\u003e\"NYC\", :street=\u003e\"Street 1\", :zipcode=\u003e\"123\"}}]\n```\n\nIt converts every method call to its corresponding transformation, and joins\nthese transformations into a transformation pipeline (a transproc).\n\n## Transproc Example Usage\n\n``` ruby\nrequire 'json'\nrequire 'transproc/all'\n\n# create your own local registry for transformation functions\nmodule Functions\n  extend Transproc::Registry\nend\n\n# import necessary functions from other transprocs...\nmodule Functions\n  # import all singleton methods from a module/class\n  import Transproc::HashTransformations\n  import Transproc::ArrayTransformations\nend\n\n# ...or from any external library\nrequire 'inflecto'\nmodule Functions\n  # import only necessary singleton methods from a module/class\n  # and rename them locally\n  import :camelize, from: Inflecto, as: :camel_case\nend\n\ndef t(*args)\n  Functions[*args]\nend\n\n# use imported transformation\ntransformation = t(:camel_case)\n\ntransformation.call 'i_am_a_camel'\n# =\u003e \"IAmACamel\"\n\ntransformation = t(:map_array, (\n  t(:symbolize_keys).\u003e\u003e t(:rename_keys, user_name: :user)\n  )).\u003e\u003e t(:wrap, :address, [:city, :street, :zipcode])\n\ntransformation.call(\n  [\n    { 'user_name' =\u003e 'Jane',\n      'city' =\u003e 'NYC',\n      'street' =\u003e 'Street 1',\n      'zipcode' =\u003e '123' }\n  ]\n)\n# =\u003e [{:user=\u003e\"Jane\", :address=\u003e{:city=\u003e\"NYC\", :street=\u003e\"Street 1\", :zipcode=\u003e\"123\"}}]\n\n# define your own composable transformation easily\ntransformation = t(-\u003e v { JSON.dump(v) })\n\ntransformation.call(name: 'Jane')\n# =\u003e \"{\\\"name\\\":\\\"Jane\\\"}\"\n\n# ...or add it to registered functions via singleton method of the registry\nmodule Functions\n  # ...\n\n  def self.load_json(v)\n    JSON.load(v)\n  end\nend\n\n# ...or add it to registered functions via .register method\nFunctions.register(:load_json) { |v| JSON.load(v) }\n\ntransformation = t(:load_json) \u003e\u003e t(:map_array, t(:symbolize_keys))\n\ntransformation.call('[{\"name\":\"Jane\"}]')\n# =\u003e [{ :name =\u003e \"Jane\" }]\n```\n\n## Credits\n\nThis project is inspired by the work of the following people:\n\n* [Markus Schirp](https://github.com/mbj) and [morpher](https://github.com/mbj/morpher) project\n* [Josep M. Bach](https://github.com/txus) and [kleisli](https://github.com/txus/kleisli) project\n\n## Contributing\n\n1. Fork it ( https://github.com/solnic/transproc/fork )\n2. Create your feature branch (`git checkout -b my-new-feature`)\n3. Commit your changes (`git commit -am 'Add some feature'`)\n4. Push to the branch (`git push origin my-new-feature`)\n5. Create a new Pull Request\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsolnic%2Ftransproc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsolnic%2Ftransproc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsolnic%2Ftransproc/lists"}