Last active
September 30, 2015 21:54
-
-
Save maetl/4542fc2390eb8701284e to your computer and use it in GitHub Desktop.
Using transproc to compose various hash transformations and mappings
This file contains 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 'transproc/all' | |
require 'addressable/uri' | |
## | |
# Convert string keys to symbols | |
# | |
transform = Transproc(:symbolize_keys) | |
data = { | |
'name' => 'Mark Rickerby', | |
'website' => 'http://maetl.net' | |
} | |
puts transform.call(data) | |
# => {:name=>"Mark Rickerby", :website=>"http://maetl.net"} | |
## | |
# Transform key names | |
# | |
transform = Transproc(:map_hash, :name => :full_name, :website => :external_uri) | |
data = { | |
:name => 'Mark Rickerby', | |
:website => 'http://maetl.net' | |
} | |
puts transform.call(data) | |
# => {:full_name=>"Mark Rickerby", :external_uri=>"http://maetl.net"} | |
## | |
# Mapping to a value object using default coercion | |
# | |
transform = Transproc(:map_key, :postcode, Transproc(:to_integer)) | |
data = { | |
:postcode => '2008' | |
} | |
puts transform.call(data) | |
# => {:postcode=>2008} | |
## | |
# Compose a chain of default coercions | |
# | |
integer = Transproc(:map_key, :postcode, Transproc(:to_integer)) | |
datetime = Transproc(:map_key, :updated_at, Transproc(:to_datetime)) | |
boolean = Transproc(:map_key, :is_active, Transproc(:to_boolean)) | |
transform = integer + datetime + boolean | |
data = { | |
:postcode => '2008', | |
:updated_at => '2015-03-28', | |
:is_active => 'true' | |
} | |
puts transform.call(data) | |
# => {:postcode=>2008, :updated_at=>#<DateTime: 2015-03-28T00:00:00+00:00 ((2457110j,0s,0n),+0s,2299161j)>, :is_active=>true} | |
## | |
# Mapping to a URI object using a custom coercion | |
# | |
module Transproc | |
register(:to_uri) do |value| | |
Addressable::URI.parse(value) | |
end | |
end | |
transform = Transproc(:map_key, :href, Transproc(:to_uri)) | |
data = { | |
:href => 'http://maetl.net/about/me' | |
} | |
puts transform.call(data) | |
# => {:href=>#<Addressable::URI:0x3ff125cb47c8 URI:http://maetl.net/about/me>} | |
## | |
# Group multiple items into a nested array | |
# | |
transform = Transproc(:group, :links, [:website]) | |
data = [ | |
{ :name => 'Mark Rickerby', :website => 'http://maetl.net' }, | |
{ :name => 'Mark Rickerby', :website => 'http://editorial.technology' } | |
] | |
puts transform.call(data) | |
# => {:name=>"Mark Rickerby", :links=>[{:website=>"http://maetl.net"}, {:website=>"http://editorial.technology"}]} | |
## | |
# Compose functional transforms | |
# | |
map = Transproc(:map_array, Transproc(:map_hash, :website => :href)) | |
group = Transproc(:group, :links, [:href]) | |
transform = map + group | |
data = [ | |
{ :name => 'Mark Rickerby', :website => 'http://maetl.net' }, | |
{ :name => 'Mark Rickerby', :website => 'http://editorial.technology' } | |
] | |
puts transform.call(data) | |
# => {:name=>"Mark Rickerby", :links=>[{:href=>"http://maetl.net"}, {:href=>"http://editorial.technology"}]} | |
## | |
# Join keys together using a default separator token (single space) | |
# | |
module Transproc | |
SEPARATOR = ' '.freeze | |
register(:join_keys) do |hash, mapping| | |
Transproc(:join_keys!, mapping)[Hash[hash]] | |
end | |
register(:join_keys!) do |hash, mapping| | |
mapping.each do |to, from| | |
hash[to] = hash.select { |k,v| from.include?(k) }.values.join(SEPARATOR) | |
from.each { |k| hash.delete(k) } | |
end | |
hash | |
end | |
end | |
transform = Transproc(:join_keys, :name => [:first_name, :last_name]) | |
data = { | |
:first_name => 'Mark', | |
:last_name => 'Rickerby' | |
} | |
puts transform.call(data) | |
# => {:name=>"Mark Rickerby"} | |
## | |
# Split keys based on a default separator token | |
# | |
module Transproc | |
register(:split_keys) do |hash, mapping| | |
Transproc(:split_keys!, mapping)[Hash[hash]] | |
end | |
register(:split_keys!) do |hash, mapping| | |
mapping.each do |to, from| | |
hash[from].split(SEPARATOR).each_with_index do |value, index| | |
hash[to[index]] = value | |
end | |
hash.delete(from) | |
end | |
hash | |
end | |
end | |
transform = Transproc(:split_keys, [:first_name, :last_name] => :name) | |
data = { | |
:name => 'Mark Rickerby' | |
} | |
puts transform.call(data) | |
# => {:first_name=>"Mark", :last_name=>"Rickerby"} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment