bonfire-app/bonfire-flavoured-elixir.html
2024-04-16 21:21:08 +00:00

253 lines
30 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="ExDoc v0.31.2">
<meta name="project" content="bonfire_umbrella v0.9.10-cooperation-beta.62">
<title>Bonfire-flavoured Elixir — bonfire_umbrella v0.9.10-cooperation-beta.62</title>
<link rel="stylesheet" href="dist/html-elixir-JKHCEBPC.css" />
<script src="dist/handlebars.runtime-NWIB6V2M.js"></script>
<script src="dist/handlebars.templates-A7S2WMC7.js"></script>
<script src="dist/sidebar_items-0AD831F9.js"></script>
<script src="docs_config.js"></script>
<script async src="dist/html-JRPQ5PR6.js"></script>
</head>
<body data-type="extras" class="page-extra">
<script>
try {
var settings = JSON.parse(localStorage.getItem('ex_doc:settings') || '{}');
if (settings.theme === 'dark' ||
((settings.theme === 'system' || settings.theme == null) &&
window.matchMedia('(prefers-color-scheme: dark)').matches)
) {
document.body.classList.add('dark')
}
} catch (error) { }
</script>
<div class="main">
<button id="sidebar-menu" class="sidebar-button sidebar-toggle" aria-label="toggle sidebar" aria-controls="sidebar">
<i class="ri-menu-line ri-lg" title="Collapse/expand sidebar"></i>
</button>
<div class="background-layer"></div>
<nav id="sidebar" class="sidebar">
<div class="sidebar-header">
<div class="sidebar-projectInfo">
<a href="https://bonfirenetworks.org" class="sidebar-projectImage">
<img src="assets/logo.png" alt="bonfire_umbrella" />
</a>
<div>
<a href="https://bonfirenetworks.org" class="sidebar-projectName" translate="no">
bonfire_umbrella
</a>
<div class="sidebar-projectVersion" translate="no">
v0.9.10-cooperation-beta.62
</div>
</div>
</div>
<ul id="sidebar-listNav" class="sidebar-listNav" role="tablist">
<li>
<button id="extras-list-tab-button" role="tab" data-type="extras" aria-controls="extras-tab-panel" aria-selected="true" tabindex="0">
Pages
</button>
</li>
<li>
<button id="modules-list-tab-button" role="tab" data-type="modules" aria-controls="modules-tab-panel" aria-selected="false" tabindex="-1">
Modules
</button>
</li>
</ul>
</div>
<div id="extras-tab-panel" class="sidebar-tabpanel" role="tabpanel" aria-labelledby="extras-list-tab-button">
<ul id="extras-full-list" class="full-list"></ul>
</div>
<div id="modules-tab-panel" class="sidebar-tabpanel" role="tabpanel" aria-labelledby="modules-list-tab-button" hidden>
<ul id="modules-full-list" class="full-list"></ul>
</div>
</nav>
<main class="content">
<output role="status" id="toast"></output>
<div class="content-outer">
<div id="content" class="content-inner">
<div class="top-search">
<div class="search-settings">
<form class="search-bar" action="search.html">
<label class="search-label">
<span class="sr-only">Search documentation of bonfire_umbrella</span>
<input name="q" type="text" class="search-input" placeholder="Press / to search" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" />
</label>
<button type="submit" class="search-button" aria-label="Submit Search">
<i class="ri-search-2-line ri-lg" aria-hidden="true" title="Submit search"></i>
</button>
<button type="button" tabindex="-1" class="search-close-button" aria-hidden="true">
<i class="ri-close-line ri-lg" title="Cancel search"></i>
</button>
</form>
<div class="autocomplete">
</div>
<button class="icon-settings display-settings">
<i class="ri-settings-3-line"></i>
<span class="sr-only">Settings</span>
</button>
</div>
</div>
<h1>
<a href="https://github.com/bonfire-networks/bonfire-app/blob/main/docs/BONFIRE-FLAVOURED-ELIXIR.md#L1" title="View Source" class="icon-action" rel="help">
<i class="ri-code-s-slash-line" aria-hidden="true"></i>
<span class="sr-only">View Source</span>
</a>
<span>Bonfire-flavoured Elixir</span>
</h1>
<p>Bonfire has a few libraries that are widely used in the codebase and make writing Elixir feel a little bit different. To help you get less confused by this, here's a guide on what we can call &quot;bonfire-flavoured elixir&quot;!</p><p>Please note this guide assumes you already know <a href="https://elixir-lang.org/getting-started/introduction.html">Elixir</a>.</p><h2 id="arrows" class="section-heading">
<a href="#arrows" class="hover-link">
<i class="ri-link-m" aria-hidden="true"></i>
</a>
<span class="text"><a href="https://hexdocs.pm/arrows/0.1.1/Arrows.html"><code class="inline">Arrows</code></a></span>
</h2>
<p>The Elixir <a href="https://hexdocs.pm/elixir/Kernel.html#%7C%3E/2">|&gt; (&quot;pipe&quot;) operator</a> is one of the things that seems to get people excited about elixir. Probably in part because you then don't have to keep coming up with function names. Unfortunately it's kind of limiting.
The moment you need to pipe a parameter into a position that isn't the first one, it breaks down and you have to drop out of the pipeline format or write a secondary function to handle it.</p><p>Not any more! By simply inserting <code class="inline">...</code> where you would like the value to be inserted, <a href="https://hexdocs.pm/arrows/0.1.1/Arrows.html"><code class="inline">Arrows</code></a> will override where it is placed. This allows you to keep on piping while accommodating that function with the annoying argument order. <a href="https://hexdocs.pm/arrows/0.1.1/Arrows.html"><code class="inline">Arrows</code></a> was inspired by <a href="https://hexdocs.pm/magritte/Magritte.html">an existing library</a>. Here is part of the test suite in lieu of examples:</p><pre><code class="makeup elixir" translate="no"><span class="kd">defmodule</span><span class="w"> </span><span class="nc">ArrowsTest</span><span class="w"> </span><span class="k" data-group-id="6997166091-1">do</span><span class="w">
</span><span class="kn">use</span><span class="w"> </span><span class="nc">ExUnit.Case</span><span class="w">
</span><span class="kn">use</span><span class="w"> </span><span class="nc">Arrows</span><span class="w">
</span><span class="kd">def</span><span class="w"> </span><span class="nf">double</span><span class="p" data-group-id="6997166091-2">(</span><span class="n">x</span><span class="p" data-group-id="6997166091-2">)</span><span class="p">,</span><span class="w"> </span><span class="ss">do</span><span class="p">:</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mi">2</span><span class="w">
</span><span class="kd">def</span><span class="w"> </span><span class="nf">double_fst</span><span class="p" data-group-id="6997166091-3">(</span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="bp">_</span><span class="p" data-group-id="6997166091-3">)</span><span class="p">,</span><span class="w"> </span><span class="ss">do</span><span class="p">:</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mi">2</span><span class="w">
</span><span class="kd">def</span><span class="w"> </span><span class="nf">double_snd</span><span class="p" data-group-id="6997166091-4">(</span><span class="bp">_</span><span class="p">,</span><span class="w"> </span><span class="n">x</span><span class="p" data-group-id="6997166091-4">)</span><span class="p">,</span><span class="w"> </span><span class="ss">do</span><span class="p">:</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mi">2</span><span class="w">
</span><span class="kd">def</span><span class="w"> </span><span class="nf">add_snd_thd</span><span class="p" data-group-id="6997166091-5">(</span><span class="bp">_</span><span class="p">,</span><span class="w"> </span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="n">y</span><span class="p" data-group-id="6997166091-5">)</span><span class="p">,</span><span class="w"> </span><span class="ss">do</span><span class="p">:</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">y</span><span class="w">
</span><span class="n">test</span><span class="w"> </span><span class="s">&quot;|&gt;&quot;</span><span class="w"> </span><span class="k" data-group-id="6997166091-6">do</span><span class="w">
</span><span class="n">assert</span><span class="w"> </span><span class="mi">4</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="p" data-group-id="6997166091-7">(</span><span class="mi">2</span><span class="w"> </span><span class="o">|&gt;</span><span class="w"> </span><span class="n">double</span><span class="p" data-group-id="6997166091-7">)</span><span class="w">
</span><span class="n">assert</span><span class="w"> </span><span class="mi">4</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="p" data-group-id="6997166091-8">(</span><span class="mi">2</span><span class="w"> </span><span class="o">|&gt;</span><span class="w"> </span><span class="n">double</span><span class="p" data-group-id="6997166091-9">(</span><span class="p" data-group-id="6997166091-9">)</span><span class="p" data-group-id="6997166091-8">)</span><span class="w">
</span><span class="n">assert</span><span class="w"> </span><span class="mi">4</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="p" data-group-id="6997166091-10">(</span><span class="mi">2</span><span class="w"> </span><span class="o">|&gt;</span><span class="w"> </span><span class="n">double</span><span class="p" data-group-id="6997166091-11">(</span><span class="n">...</span><span class="p" data-group-id="6997166091-11">)</span><span class="p" data-group-id="6997166091-10">)</span><span class="w">
</span><span class="n">assert</span><span class="w"> </span><span class="mi">8</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="p" data-group-id="6997166091-12">(</span><span class="mi">2</span><span class="w"> </span><span class="o">|&gt;</span><span class="w"> </span><span class="n">double</span><span class="p" data-group-id="6997166091-13">(</span><span class="n">double</span><span class="p" data-group-id="6997166091-14">(</span><span class="n">...</span><span class="p" data-group-id="6997166091-14">)</span><span class="p" data-group-id="6997166091-13">)</span><span class="p" data-group-id="6997166091-12">)</span><span class="w">
</span><span class="n">assert</span><span class="w"> </span><span class="mi">4</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="p" data-group-id="6997166091-15">(</span><span class="mi">2</span><span class="w"> </span><span class="o">|&gt;</span><span class="w"> </span><span class="n">double_fst</span><span class="p" data-group-id="6997166091-16">(</span><span class="mi">1</span><span class="p" data-group-id="6997166091-16">)</span><span class="p" data-group-id="6997166091-15">)</span><span class="w">
</span><span class="n">assert</span><span class="w"> </span><span class="mi">4</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="p" data-group-id="6997166091-17">(</span><span class="mi">2</span><span class="w"> </span><span class="o">|&gt;</span><span class="w"> </span><span class="n">double_fst</span><span class="p" data-group-id="6997166091-18">(</span><span class="n">...</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p" data-group-id="6997166091-18">)</span><span class="p" data-group-id="6997166091-17">)</span><span class="w">
</span><span class="n">assert</span><span class="w"> </span><span class="mi">8</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="p" data-group-id="6997166091-19">(</span><span class="mi">2</span><span class="w"> </span><span class="o">|&gt;</span><span class="w"> </span><span class="n">double_fst</span><span class="p" data-group-id="6997166091-20">(</span><span class="n">double</span><span class="p" data-group-id="6997166091-21">(</span><span class="n">...</span><span class="p" data-group-id="6997166091-21">)</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p" data-group-id="6997166091-20">)</span><span class="p" data-group-id="6997166091-19">)</span><span class="w">
</span><span class="n">assert</span><span class="w"> </span><span class="mi">4</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="p" data-group-id="6997166091-22">(</span><span class="mi">2</span><span class="w"> </span><span class="o">|&gt;</span><span class="w"> </span><span class="n">double_snd</span><span class="p" data-group-id="6997166091-23">(</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="n">...</span><span class="p" data-group-id="6997166091-23">)</span><span class="p" data-group-id="6997166091-22">)</span><span class="w">
</span><span class="n">assert</span><span class="w"> </span><span class="mi">8</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="p" data-group-id="6997166091-24">(</span><span class="mi">2</span><span class="w"> </span><span class="o">|&gt;</span><span class="w"> </span><span class="n">double_snd</span><span class="p" data-group-id="6997166091-25">(</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="n">double</span><span class="p" data-group-id="6997166091-26">(</span><span class="n">...</span><span class="p" data-group-id="6997166091-26">)</span><span class="p" data-group-id="6997166091-25">)</span><span class="p" data-group-id="6997166091-24">)</span><span class="w">
</span><span class="n">assert</span><span class="w"> </span><span class="mi">3</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="p" data-group-id="6997166091-27">(</span><span class="mi">2</span><span class="w"> </span><span class="o">|&gt;</span><span class="w"> </span><span class="n">add_snd_thd</span><span class="p" data-group-id="6997166091-28">(</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="n">...</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p" data-group-id="6997166091-28">)</span><span class="p" data-group-id="6997166091-27">)</span><span class="w">
</span><span class="n">assert</span><span class="w"> </span><span class="mi">4</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="p" data-group-id="6997166091-29">(</span><span class="mi">2</span><span class="w"> </span><span class="o">|&gt;</span><span class="w"> </span><span class="n">add_snd_thd</span><span class="p" data-group-id="6997166091-30">(</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="n">...</span><span class="p">,</span><span class="w"> </span><span class="n">...</span><span class="p" data-group-id="6997166091-30">)</span><span class="p" data-group-id="6997166091-29">)</span><span class="w">
</span><span class="n">assert</span><span class="w"> </span><span class="mi">6</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="p" data-group-id="6997166091-31">(</span><span class="mi">2</span><span class="w"> </span><span class="o">|&gt;</span><span class="w"> </span><span class="n">add_snd_thd</span><span class="p" data-group-id="6997166091-32">(</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="n">...</span><span class="p">,</span><span class="w"> </span><span class="n">double</span><span class="p" data-group-id="6997166091-33">(</span><span class="n">...</span><span class="p" data-group-id="6997166091-33">)</span><span class="p" data-group-id="6997166091-32">)</span><span class="p" data-group-id="6997166091-31">)</span><span class="w">
</span><span class="k">for</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="p" data-group-id="6997166091-34">[</span><span class="ss">:yes</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="no">nil</span><span class="p">,</span><span class="w"> </span><span class="no">false</span><span class="p" data-group-id="6997166091-34">]</span><span class="w"> </span><span class="k" data-group-id="6997166091-35">do</span><span class="w">
</span><span class="n">assert</span><span class="w"> </span><span class="p" data-group-id="6997166091-36">{</span><span class="ss">:ok</span><span class="p">,</span><span class="w"> </span><span class="n">x</span><span class="p" data-group-id="6997166091-36">}</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="p" data-group-id="6997166091-37">(</span><span class="n">x</span><span class="w"> </span><span class="o">|&gt;</span><span class="w"> </span><span class="p" data-group-id="6997166091-38">{</span><span class="ss">:ok</span><span class="p">,</span><span class="w"> </span><span class="n">...</span><span class="p" data-group-id="6997166091-38">}</span><span class="p" data-group-id="6997166091-37">)</span><span class="w">
</span><span class="k" data-group-id="6997166091-35">end</span><span class="w">
</span><span class="k" data-group-id="6997166091-6">end</span><span class="w">
</span><span class="k" data-group-id="6997166091-1">end</span></code></pre><p>A few little extra features you might notice here:</p><ul><li>You can move the parameter into a subexpression, as in <code class="inline">2 |&gt; double_fst(double(...), 1)</code> where double will be called before the parameter is passed to <code class="inline">double_fst</code>.</li><li>You can use <code class="inline">...</code> multiple times, substituting it in multiple places.</li><li>The right hand side need not even be a function call, you can use any expression with <code class="inline">...</code>.</li></ul><h3 id="ok-pipe" class="section-heading">
<a href="#ok-pipe" class="hover-link">
<i class="ri-link-m" aria-hidden="true"></i>
</a>
<span class="text">Ok-pipe</span>
</h3>
<p><a href="https://hexdocs.pm/arrows/0.1.1/Arrows.html"><code class="inline">Arrows</code></a> also provides an <code class="inline">ok-pipe</code> operator, <code class="inline">~&gt;</code>, which only pipes into the next function if the result from the last one was considered a success. It's inspired by <a href="https://hexdocs.pm/ok/readme.html">OK</a>, but we have chosen to do things slightly differently so it better fits with our regular pipe.</p><table><tbody><tr><td style="text-align: left;">input</td><td style="text-align: left;">result</td><td style="text-align: left;"></td></tr><tr><td style="text-align: left;">:-----------------------</td><td style="text-align: left;">:--------------</td><td style="text-align: left;"></td></tr><tr><td style="text-align: left;"><code class="inline">{:ok, x}</code></td><td style="text-align: left;"><code class="inline">fun.(x)</code></td><td style="text-align: left;"></td></tr><tr><td style="text-align: left;"><code class="inline">{:error, e}</code></td><td style="text-align: left;"><code class="inline">{:error, e}</code></td><td style="text-align: left;"></td></tr><tr><td style="text-align: left;"><code class="inline">nil</code></td><td style="text-align: left;"><code class="inline">nil</code></td><td style="text-align: left;"></td></tr><tr><td style="text-align: left;"><code class="inline">x when not is_nil(x)</code></td><td style="text-align: left;"><code class="inline">fun.(x)</code></td><td style="text-align: left;"></td></tr></tbody></table><p>In the case of a function returning an ok/error tuple being on the left hand side, this is straightforward to determine. In the event of <code class="inline">{:ok, x}</code>, x will be passed into the right hand side to call. In the event of <code class="inline">{:error, x}</code>, the result will be <code class="inline">{:error, x}</code>.</p><p>We also deal with a lot of functions that indicate failure by returning nil. <code class="inline">~&gt;</code> tries to 'do what I mean' for both of these so you can have one pipe operator to rule them all. If <code class="inline">nil</code> is a valid result, you must thus be sure to wrap it in an <code class="inline">ok</code> tuple when it occurs on the left hand side of <code class="inline">~&gt;</code>.</p><p><code class="inline">|&gt;</code> and <code class="inline">~&gt;</code> compose in the way you'd expect; i.e. a <code class="inline">~&gt;</code> receiving an error tuple or nil will stop executing the rest of the chain of (mixed) pipes.</p><h2 id="untangle" class="section-heading">
<a href="#untangle" class="hover-link">
<i class="ri-link-m" aria-hidden="true"></i>
</a>
<span class="text">Untangle</span>
</h2>
<p><a href="https://hexdocs.pm/untangle/0.3.0/Untangle.html"><code class="inline">Untangle</code></a> provides replacements for the macros in Elixir's <a href="https://hexdocs.pm/logger/Logger.html"><code class="inline">Logger</code></a> module and the <code class="inline">IO.inspect</code> function to output code location information. The first argument will be <code class="inline">inspect</code>ed and the second (where provided) will be used as a label:</p><pre><code class="makeup elixir" translate="no"><span class="gp unselectable">iex(1)&gt; </span><span class="kn">import</span><span class="w"> </span><span class="nc">Untangle</span><span class="w">
</span><span class="nc">Untangle</span><span class="w">
</span><span class="gp unselectable">iex(2)&gt; </span><span class="n">debug</span><span class="p" data-group-id="3167751984-1">(</span><span class="ss">:no</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;the answer is&quot;</span><span class="p" data-group-id="3167751984-1">)</span><span class="w"> </span><span class="c1"># log at debug</span><span class="w">
</span><span class="mi">11</span><span class="p">:</span><span class="mi">19</span><span class="p">:</span><span class="mf">09.915</span><span class="w"> </span><span class="p" data-group-id="3167751984-2">[</span><span class="n">debug</span><span class="p" data-group-id="3167751984-2">]</span><span class="w"> </span><span class="p" data-group-id="3167751984-3">[</span><span class="n">iex</span><span class="p">:</span><span class="mi">2</span><span class="p" data-group-id="3167751984-3">]</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">answer</span><span class="w"> </span><span class="ss">is</span><span class="p">:</span><span class="w"> </span><span class="ss">:no</span><span class="w">
</span><span class="ss">:no</span><span class="w">
</span><span class="gp unselectable">iex(3)&gt; </span><span class="n">dump</span><span class="p" data-group-id="3167751984-4">(</span><span class="p" data-group-id="3167751984-5">%{</span><span class="ss">a</span><span class="p">:</span><span class="w"> </span><span class="ss">:map</span><span class="p" data-group-id="3167751984-5">}</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;it&quot;</span><span class="p" data-group-id="3167751984-4">)</span><span class="w"> </span><span class="c1"># inspect something on stdout</span><span class="w">
</span><span class="p" data-group-id="3167751984-6">[</span><span class="n">iex</span><span class="p">:</span><span class="mi">3</span><span class="p" data-group-id="3167751984-6">]</span><span class="w"> </span><span class="ss">it</span><span class="p">:</span><span class="w"> </span><span class="p" data-group-id="3167751984-7">%{</span><span class="ss">a</span><span class="p">:</span><span class="w"> </span><span class="ss">:map</span><span class="p" data-group-id="3167751984-7">}</span><span class="w">
</span><span class="p" data-group-id="3167751984-8">%{</span><span class="ss">a</span><span class="p">:</span><span class="w"> </span><span class="ss">:map</span><span class="p" data-group-id="3167751984-8">}</span></code></pre><p>When used in a code file, the location information becomes slightly more useful, e.g.:</p><pre><code class="makeup elixir" translate="no"><span class="p" data-group-id="3169636453-1">[</span><span class="n">lib</span><span class="o">/</span><span class="n">test_untangle</span><span class="o">.</span><span class="n">ex</span><span class="p">:</span><span class="mi">15</span><span class="err">@</span><span class="nc">Test.Untangle</span><span class="o">.</span><span class="n">example</span><span class="o">/</span><span class="mi">2</span><span class="p" data-group-id="3169636453-1">]</span><span class="w"> </span><span class="nc">Here</span><span class="err">&#39;</span><span class="n">s</span><span class="w"> </span><span class="n">an</span><span class="w"> </span><span class="n">empty</span><span class="w"> </span><span class="ss">list</span><span class="p">:</span><span class="w"> </span><span class="p" data-group-id="3169636453-2">[</span><span class="p" data-group-id="3169636453-2">]</span></code></pre><p>You may also notice from the iex output that it returns its first argument. This makes it ideal for
inserting into a pipeline for debugging purposes:</p><pre><code class="makeup elixir" translate="no"><span class="n">do_something</span><span class="p" data-group-id="4618764515-1">(</span><span class="p" data-group-id="4618764515-1">)</span><span class="w">
</span><span class="o">|&gt;</span><span class="w"> </span><span class="n">debug</span><span class="p" data-group-id="4618764515-2">(</span><span class="s">&quot;output of do_something/0&quot;</span><span class="p" data-group-id="4618764515-2">)</span></code></pre><p>When you are done debugging something, the location of the debug statement is already in the output so you know where to remove it or comment it out! Bliss!</p><p>You will find the codebase uses this a lot, though the debugs are frequently commented out. Just uncomment the ones that would help you with a particular debugging task and you're off.</p><h2 id="error-handling" class="section-heading">
<a href="#error-handling" class="hover-link">
<i class="ri-link-m" aria-hidden="true"></i>
</a>
<span class="text">Error handling</span>
</h2>
<p><a href="https://hexdocs.pm/bonfire_fail/0.1.0/Bonfire.Fail.html"><code class="inline">Bonfire.Fail</code></a> is an <a href="https://hexdocs.pm/elixir/Exception.html"><code class="inline">Exception</code></a> handler, which you can use to stop the show anywhere in the code, e.g:</p><p><code class="inline">id = ulid(object) || raise(Bonfire.Fail, :not_found)</code> </p><p>You can use this special exception when you want to redirect the user to the login page rather than just show an error:
<code class="inline">user = current_user(assigns) || raise(Bonfire.Fail.Auth, :needs_login)</code> </p><p>Advantages include:</p><ul><li>standardised error messages (defaults are defined at <a href="https://github.com/bonfire-networks/bonfire_fail/blob/main/lib/runtime_config.ex#L16">https://github.com/bonfire-networks/bonfire_fail/blob/main/lib/runtime_config.ex#L16</a>) which can be overridden in your app's config using <code class="inline">config :bonfire_fail, :common_errors</code></li><li>friendly error messages are defined in one place, which means no duplicated localisation efforts</li><li>uses the elixir/OTP pattern of &quot;let it crash&quot;</li><li>returns the correct HTTP code when applicable</li><li>no need to wrap blocks in if/else or the like </li><li>for users of the LiveView frontend, this will make the corresponding friendly error message appear in a flash overlay (if using <a href="https://hexdocs.pm/bonfire_ui_common/0.1.0/Bonfire.UI.Common.LiveHandlers.html"><code class="inline">Bonfire.UI.Common.LiveHandlers</code></a> and/or <code class="inline">Bonfire.UI.Common.undead/3</code>)</li></ul>
<div class="bottom-actions">
<div class="bottom-actions-item">
<a href="architecture.html" class="bottom-actions-button" rel="prev">
<span class="subheader">
← Previous Page
</span>
<span class="title">
Bonfire Architecture
</span>
</a>
</div>
<div class="bottom-actions-item">
<a href="database.html" class="bottom-actions-button" rel="next">
<span class="subheader">
Next Page →
</span>
<span class="title">
Bonfire's Database - an intro
</span>
</a>
</div>
</div>
<footer class="footer">
<p>
<span class="line">
<button class="a-main footer-button display-quick-switch" title="Search HexDocs packages">
Search HexDocs
</button>
<a href="bonfire_umbrella.epub" title="ePub version">
Download ePub version
</a>
</span>
</p>
<p class="built-using">
Built using
<a href="https://github.com/elixir-lang/ex_doc" title="ExDoc" target="_blank" rel="help noopener" translate="no">ExDoc</a> (v0.31.2) for the
<a href="https://elixir-lang.org" title="Elixir" target="_blank" translate="no">Elixir programming language</a>
</p>
</footer>
</div>
</div>
</main>
</div>
</body>
</html>