wolf4earth
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"]}
}
Trending in Announcing
Flop is an Elixir library that applies filtering, ordering and pagination parameters to your Ecto queries.
offset-based pagination with...
New
I needed to reuse React components from my Chrome extension in my Phoenix/LiveView backend. I noticed that for Svelte/Vue, there are live...
New
I released Doggo, a collection of unstyled Phoenix components.
https://github.com/woylie/doggo
Features
Unstyled Phoenix components....
New
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
Hi there! We created Gust: A task orchestrator inspired by Airflow.
For those who have never heard about Aiflow, it’s a Python-based wor...
New
Hello
Published a new library - ProcessHub!
ProcessHub is a library designed to manage process distribution within the Elixir cluster. ...
New
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Other Trending Topics
I am happy to introduce the very α version of the new programming language compiled to BEAM.
Welcome Cure.
It has literally three kille...
New
Hi everyone!
The first release candidate for the Expert language server project is now available!
We’ve published a press release detai...
New
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself.
My main conc...
New
It’s not that it’s vocabulary is too advanced. It’s something worse.
I get lost trying to follow even a paragraph written by Claude. It’...
New
This showed up on my feed.. anyone heard of it? Just hype?
Ox Alpha is a reasoning model designed for coding, sustained ag...
New
Hey folks,
I just published a post about Hologram’s funding and where the project goes next - the short version:
Curiosum as Main Spons...
New
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixirconf-us
- #ai
- #blog-post
- #elixir-ls
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #hex
- #security











Most Liked- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
wolf4earth
If you’re wondering whether or not
Babelis 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
babel can be misinterpreted as the popular js transpiler
Last Post!
Eiji
This one was only for the example you shared as you said it’s more complex one it’s used in production, so I have tried to re-produce it.
I didn’t have a problem with that at all, but who am I to speak about it when
Gentoowas my firstLinuxdistribution.Perhaps you mean cases like
Map.fetch/2returning:erroratom? It could be solved with a simple wrapper function.All
Elixircore features including debugging is more than enough for me and I rarely need to write any wrapper. As said ifElixircore is not enough at most I have usedecto.Ignore that, I got something wrong when quickly browsing documentation.
That’s a good point … for a
Rustdevelopers.I’m writing pipelines in pure
Elixirsupporting not single, but all “happy paths” and either “let it default” tonilin case some part of data is expected to be nullable or let it fail when it’s not supported. Especially the “let it fail” isErlangandElixirconcept, so speaking generally about “happy paths” have not sense in general context in such languages. Therefore at the very end the code is very specific to your needs. I believe that your package may therefore be or not be used even in very similar cases. Just speaking it’s a good for “Rust” was 50-50 for fun.Sounds like latest
Elixirimprovements likedbgmacro, improved error messages and using part of code in error output. I guess that I personally would be more interested in such package before mentioned improvements, but at the end I would stop use said package after that improvements would be added.Again who am I to speak about that when in many answers I gave few possible solutions where the biggest one is based only on the pattern-matching. I have no idea, but for some reason I like how things works now.
Oh, at first I did not expanded it, so I did not saw it. Hmm …
More seriously … it’s really long and maybe that’s because it somehow reminds me a terrible long stacktrace in
JVM-based languages. I’m exhausted by just seeingand XX moreat the bottom of already too long stacktrace. Again I like how things works now, so I’m not sure if I can see a real-world usage in my personal case.Why you mention control? You have only control if your app is generating the data, right? As said for all those years I have used pure
Elixirand at mostectoto cover almost all if not all cases of casting a data from for exampleJSONAPI response.What? You are developing the “shape” as same as you are creating structs. Regardless if data have proper format or not you simply pass
"audioCollection"value tochangesetfunction and in worst case you use some mapper like the default one supported byectoi.e.@field_source_mappermentioned previously.Yeah, I guess that I did not get non-ecto use cases.
I can see that posting:
without explaining what exactly use-cases you mean is really confusing. That makes me only more interested to hear “your story”.
Maybe answering such questions could help you describe your point of view more easily:
ectostarts causing trouble?@field_source_mapperare not enough for a data with different structure?Edit: When writing all of this I got some idea. If it’s not “something like”
JSONAPI that have a well known structure then the source could have a dynamic structure. Ok, but how to parse a dynamic structure? How about creating a complex htmlformfor dynamically querying data of unknown for the app structure (but known by user)? That’s interesting, but how such data would be used? How about using dynamic rules to fetch dynamic data in order to present it in a predictable format like a graph? Am I going into the right direction or by any change I have messed it up completely? Maybe I think about it too much and there is much simpler use case …