ProductPromotion
Logo

Elixir

made by https://0x3d.site

GitHub - vic/happy: the alchemist's happy path with elixir
the alchemist's happy path with elixir. Contribute to vic/happy development by creating an account on GitHub.
Visit Site

GitHub - vic/happy: the alchemist's happy path with elixir

GitHub - vic/happy: the alchemist's happy path with elixir

Happy

help maintain this lib

the alchemist's happy path with elixir

If you are using Elixir >= 1.2, you might prefer happy_with

Installation

Available in Hex, the package can be installed as:

  1. Add happy to your list of dependencies in mix.exs:
  def deps do
    [{:happy, "~> 1.3.1"}]
  end

About

Ok, so I was just trying to find a nice way (beautiful syntax, yet flexible enough) to handle errors in elixir. Handling :ok/:error like tuples without lots of if/cases.

After creating ok_jose, looking at Elixir's with special form and other alternatives, I wanted to create this tiny library with the following goals in mind:

  • The happy path must be immediately obvious to the eyes.
  • Code should not be cluttered and should just work using the elixir you already know.
  • Avoid introducing noisy operators ~>>, requiring commas after each pattern
  • Should provide a way to recover when not so happy moments come.

If you dont need special features like tags, and are using elixir ~> 1.2, checkout happy_with wich is just tiny sugar around with special form.

Usage

import Happy
the happy_path macro

The happy_path macro takes a do block and rewrites any first-level pattern matching expression into a case.

happy_path do
  {:ok, b} = a
  {:ok, d} = b
  c(d)
end

gets rewritten to something like:

case(a) do
  {:ok, b} ->
    case (b) do
      {:ok, d} -> c(d)
    end
end

Note that a variable pattern match (assignment) is not rewritten, as it will always match and would cause warnings.

happy_path do
  x = some(thing) # simple assignment is left as is
end
handling errors with else clauses

If you want to handle non-matching values, provide an else block with additional matching clauses:

happy_path do
  {:ok, b} = a
  c(b)
else
  {:error, x} -> x
end
sharing common error handling code

Sometimes you would want to share common error handling code on many happy_paths, for example in an api controller with many actions, all of which handle common invalid cases like parameter validation.

In those cases you can provide happy_path with an default error handler as first argument. Note that if no local else clause matches, the error value is piped into the provided error handler. Thus the handler is anything you can pipe the error value into.

happy_path(else: handler) do 
 {:ok, x} = foo
 x + 1
else
 {:error, y} -> y
end

gets rewritten to something like:

case foo do
  {:ok, x} -> 
    x + 1
  {:error, y} ->
    y
  err -> 
    err |> handler
end
support for guards

Just like with case you can include guard tests.

happy_path do
  x when not is_nil(x) = some(foo)
  x + 1
end
tags

Tags is an special feature of happy_path not found on alternatives like elixir's with expression.

Tags look like module attributes but they are not, they are just shorthand for tagging a pattern.

happy_path do
  # using the `foo` tag
  @foo {:ok, x} = y

  # is exactly the same as
  {:foo, {:ok, x}} = {:foo, y}
else
  {:foo, {:error, e}} -> "Foo error"
end

Tags can help error handlers to get a clue about which context the mismatch was produced on. It's mostly useful for distingishing between lots of {:error, _} like tuples.

@happy tag

The special tag @happy lets you mark a pattern matching expression to be skipped by happy_path. For example when you know something will always match.

happy_path do
  @happy {this, would} = {"always", "match"}
end

produces just:

{this, would} = {"always", "match"}
Example usage in a web application creating a user
happy_path do

  %{valid?: true} = ch = User.changeset(params)
  {:ok, user} = Repo.insert(ch)
  render(conn, "user.json", user: user)

else

  %{valid?: false} = ch -> render(conn, "validation_errors.json", ch: ch)
  {:error, ch} -> render(conn, "db_error.json", ch: ch)
  _ -> text(conn, "error")

end

Is it any good?

Yes

Articles
to learn more about the elixir concepts.

Resources
which are currently available to browse on.

mail [email protected] to add your project or resources here 🔥.

FAQ's
to know more about the topic.

mail [email protected] to add your project or resources here 🔥.

Queries
or most google FAQ's about Elixir.

mail [email protected] to add more queries here 🔍.

More Sites
to check out once you're finished browsing here.

0x3d
https://www.0x3d.site/
0x3d is designed for aggregating information.
NodeJS
https://nodejs.0x3d.site/
NodeJS Online Directory
Cross Platform
https://cross-platform.0x3d.site/
Cross Platform Online Directory
Open Source
https://open-source.0x3d.site/
Open Source Online Directory
Analytics
https://analytics.0x3d.site/
Analytics Online Directory
JavaScript
https://javascript.0x3d.site/
JavaScript Online Directory
GoLang
https://golang.0x3d.site/
GoLang Online Directory
Python
https://python.0x3d.site/
Python Online Directory
Swift
https://swift.0x3d.site/
Swift Online Directory
Rust
https://rust.0x3d.site/
Rust Online Directory
Scala
https://scala.0x3d.site/
Scala Online Directory
Ruby
https://ruby.0x3d.site/
Ruby Online Directory
Clojure
https://clojure.0x3d.site/
Clojure Online Directory
Elixir
https://elixir.0x3d.site/
Elixir Online Directory
Elm
https://elm.0x3d.site/
Elm Online Directory
Lua
https://lua.0x3d.site/
Lua Online Directory
C Programming
https://c-programming.0x3d.site/
C Programming Online Directory
C++ Programming
https://cpp-programming.0x3d.site/
C++ Programming Online Directory
R Programming
https://r-programming.0x3d.site/
R Programming Online Directory
Perl
https://perl.0x3d.site/
Perl Online Directory
Java
https://java.0x3d.site/
Java Online Directory
Kotlin
https://kotlin.0x3d.site/
Kotlin Online Directory
PHP
https://php.0x3d.site/
PHP Online Directory
React JS
https://react.0x3d.site/
React JS Online Directory
Angular
https://angular.0x3d.site/
Angular JS Online Directory