wolf4earth
Babel - Data transformations made easy
Babel was born out of a desire to simplify non-trivial data transformation pipelines. To focus on the “happy path” instead of having to write a bunch of boilerplate error handling code.
But don’t listen to me, take a look for yourself:
pipeline =
Babel.begin()
|> Babel.fetch(["some", "nested", "path"])
|> Babel.map(Babel.into(%{atom_key: Babel.fetch("string-key")}))
data = %{
"some" => %{
"nested" => %{
"path" => [
%{"string-key" => :value2},
%{"string-key" => :value2},
%{"string-key" => :value2}
]
}
}
}
Babel.apply(pipeline, data)
=> {:ok, [
%{atom_key: :value1},
%{atom_key: :value2},
%{atom_key: :value3}
]}
Since you’ll most likely build non-trivial transformation pipelines with Babel - which can fail at any given step - Babel ships with elaborate error reporting:
Error Reporting
pipeline =
Babel.begin()
|> Babel.fetch(["some", "nested", "path"])
|> Babel.map(Babel.into(%{atom_key: Babel.fetch("string-key")}))
data = %{
"some" => %{
"nested" => %{
"path" => [
%{"unexpected-key" => :value1},
%{"unexpected-key" => :value2},
%{"unexpected-key" => :value3}
]
}
}
}
Babel.apply!(pipeline, data)
Which will produce the following error
** (Babel.Error) Failed to transform data: [not_found: "string-key", not_found: "string-key", not_found: "string-key"]
Root Cause(s):
1. Babel.Trace<ERROR>{
data = %{"unexpected-key" => :value1}
Babel.fetch("string-key")
|=> {:error, {:not_found, "string-key"}}
}
2. Babel.Trace<ERROR>{
data = %{"unexpected-key" => :value2}
Babel.fetch("string-key")
|=> {:error, {:not_found, "string-key"}}
}
3. Babel.Trace<ERROR>{
data = %{"unexpected-key" => :value3}
Babel.fetch("string-key")
|=> {:error, {:not_found, "string-key"}}
}
Full Trace:
Babel.Trace<ERROR>{
data = %{"some" => %{"nested" => %{"path" => [%{"unexpected-key" => :value1}, %{"unexpected-key" => :value2}, %{"unexpected-key" => :value3}]}}}
Babel.Pipeline<>
|
| Babel.fetch(["some", "nested", "path"])
| |=< %{"some" => %{"nested" => %{"path" => [%{"unexpected-key" => :value1}, %{...}, ...]}}}
| |=> [%{"unexpected-key" => :value1}, %{"unexpected-key" => :value2}, %{"unexpected-key" => :value3}]
|
| Babel.map(Babel.into(%{atom_key: Babel.fetch("string-key")}))
| |=< [%{"unexpected-key" => :value1}, %{"unexpected-key" => :value2}, %{"unexpected-key" => :value3}]
| |
| | Babel.into(%{atom_key: Babel.fetch("string-key")})
| | |=< %{"unexpected-key" => :value1}
| | |
| | | Babel.fetch("string-key")
| | | |=< %{"unexpected-key" => :value1}
| | | |=> {:error, {:not_found, "string-key"}}
| | |
| | |=> {:error, [not_found: "string-key"]}
| |
| | Babel.into(%{atom_key: Babel.fetch("string-key")})
| | |=< %{"unexpected-key" => :value2}
| | |
| | | Babel.fetch("string-key")
| | | |=< %{"unexpected-key" => :value2}
| | | |=> {:error, {:not_found, "string-key"}}
| | |
| | |=> {:error, [not_found: "string-key"]}
| |
| | Babel.into(%{atom_key: Babel.fetch("string-key")})
| | |=< %{"unexpected-key" => :value3}
| | |
| | | Babel.fetch("string-key")
| | | |=< %{"unexpected-key" => :value3}
| | | |=> {:error, {:not_found, "string-key"}}
| | |
| | |=> {:error, [not_found: "string-key"]}
| |
| |=> {:error, [not_found: "string-key", not_found: "string-key", not_found: "string-key"]}
|
|=> {:error, [not_found: "string-key", not_found: "string-key", not_found: "string-key"]}
}
Most Liked
wolf4earth
If you’re wondering whether or not Babel is production-ready: we’ve been using a pre-release version for nearly a year at this point at work in production, and it made external API integrations a lot easier and smoother. ![]()
wolf4earth
What I’m taking away from this, is that more examples would be helpful and a comparison against libraries like Ecto.
kasvith
Popular in Announcing
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #hex









