New Transproc Released

Transproc is a small library I wrote a couple of months back. It’s been growing nicely and yesterday its 0.3.0 version was released which redefined how it works and what it is. I’m excited about this project as it’s been used in ROM to implement its Mapper component and turned out to be very powerful and flexible while remaining simple.

In this post, I’d like to show you what transproc is and how it can be used with other libraries.

New Way Of Importing Methods

Thanks to awesome work by Andrew Kozin Transproc can now import methods from other modules and wrap it with a simple API allowing you to compose imported methods into a pipeline:

module Functions
  extend Transproc::Registry

  import Transproc::Coercions
  import Transproc::ArrayTransformations
  import Transproc::HashTransformations
end

def t(*args)
  Functions[*args]
end

t(:to_string)[1] # => "1"

t(:rename_keys, user_name: :name)[{ user_name: "Jane"}] # => {:name=>"Jane"}

t(:map_array, t(:to_integer))[["1", "2", "3"]] # => [1,2,3]

Importing Methods From Any Module

Importing methods is not limited to built-in transproc modules. You can import methods from any module that has singleton methods, like for example inflecto gem:

module Functions
  # ...

  # import all
  import Inflecto

  # you can cherry-pick and even rename too
  import :camelize, from: Inflecto, as: :camel_case
end

t(:tableize)["FooBar"] # => "foo_bars"

t(:camel_case)["foo_bar"] # => "fooBar"

This means you can define your own modules too:

module Serializers
  def self.from_json(input)
    JSON.parse(input)
  end
end

module Functions
  # ...

  import Serializers
end

t(:from_json)['[{"foo":"bar"}]'] # => [{"foo" => "bar"}]

Composing Imported Methods

Imported methods can be composed together into a single tranformation pipeline:

transformation = t(:rename_keys, user_name: :name) >> t(:map_value, :age, t(:to_integer))

transformation[{ user_name: 'Jane', age: '21' }] # => {:age=>21, :name=>"Jane"}

As you can see composition works the same but the global Transproc function registry is deprecated and you can now define your own registries with Transproc::Registry extension. This solution is simpler and more flexible and removes the need for a single global registry which could result in name-conflicts.

So, what’s Transproc?

It’s now clear that transproc has become a library for method composition via its first-class Transproc::Function API. Since now you can import methods from any module it is very likely you’ll manage to use transproc with other gems or your own modules.

Ability to import methods from any module and being able to provide arbitrary procs too makes it very flexible. You can easily encapsulate small transformation functions, test them in isolation and compose into a single complex transformation.

This approach is quite simple and consistent and doesn’t require any monkey-patching.

And it’s not just for transformations! Transproc already provides other functions like :is predicate or :recursion. You can check them out in the API documentation.

Plans for 1.0.0

We’re thinking about splitting transproc into smaller gems and probably establishing a separate organization on GitHub for it. Main transproc gem would provide core functionality with additional gems shipping specific methods like transproc-array or transproc-coercions. There’s still a lot of work pending to improve test coverage and of course deprecated APIs will be removed for 1.0.0 release, so please upgrade to 0.3.0 and get rid of any deprecation warnings that you see.