Qx
Qx is a small, dependency-free collection of utilities and helpers for everyday Elixir work — the handful of functions that otherwise get re-written in every project.
Installation
Add qx to your dependencies in mix.exs:
def deps do
[
{:qx, "~> 0.2.0"}
]
end
What's in the box
Qx.String
Presence checks, URL-safe slugs and display truncation.
Qx.String.blank?(" ") #=> true
Qx.String.present?("hi") #=> true
Qx.String.slugify("Crème Brûlée") #=> "creme-brulee"
Qx.String.slugify("Elixir Rocks", separator: "_")
#=> "elixir_rocks"
Qx.String.truncate("Hello, World!", 8) #=> "Hello..."
Qx.Map
Reshaping nested data — recursive merging, key conversion and pruning.
Qx.Map.deep_merge(%{a: %{b: 1, c: 2}}, %{a: %{c: 3}})
#=> %{a: %{b: 1, c: 3}}
Qx.Map.atomize_keys(%{"a" => %{"b" => 1}})
#=> %{a: %{b: 1}}
Qx.Map.stringify_keys(%{a: %{b: 1}})
#=> %{"a" => %{"b" => 1}}
Qx.Map.compact(%{a: %{b: nil, c: 2}, d: nil}, recursive: true)
#=> %{a: %{c: 2}}
atomize_keys/1 only ever uses existing atoms — a key with no matching atom
is left as a string, so untrusted input cannot exhaust the atom table.
Qx.Result
Pipelines over the {:ok, value} / {:error, reason} tuples Elixir uses
everywhere, so a chain of fallible calls reads top-to-bottom instead of nesting.
Qx.Result.ok(2)
|> Qx.Result.map(&(&1 * 5))
|> Qx.Result.and_then(&validate/1)
|> Qx.Result.unwrap(:default)
Qx.Result.collect([{:ok, 1}, {:ok, 2}]) #=> {:ok, [1, 2]}
Qx.Result.collect([{:ok, 1}, {:error, :nope}]) #=> {:error, :nope}
Qx
The most frequently reached-for string and map helpers are delegated to the
top-level Qx module, so a single alias Qx is often enough:
Qx.slugify("Hello, World!") #=> "hello-world"
Qx.deep_merge(%{a: %{b: 1}}, %{a: %{c: 2}})
#=> %{a: %{b: 1, c: 2}}
Documentation
Full API docs are published on HexDocs.
License
MIT — see LICENSE.