<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
      <title>The iNK blot</title>
        <link>https://novemberkilo.com</link>
        <description></description>
        <generator>Zola</generator>
        <language>en</language>
        <atom:link href="https://novemberkilo.com/rss.xml" rel="self" type="application/rss+xml"/>
        <lastBuildDate>Mon, 25 May 2020 00:00:00 +0000</lastBuildDate>
        <item>
            <title>Data Engineering Principles</title>
            <pubDate>Mon, 25 May 2020 00:00:00 +0000</pubDate>
            <link>https://novemberkilo.com/posts/data-engineering-principles/</link>
            <guid>https://novemberkilo.com/posts/data-engineering-principles/</guid>
            <description>&lt;p&gt;Here are a set of principles that guide the design and development of systems responsible
for transforming data. They come from experience with this general domain but they originated
from my experience at Ambiata. I was taught these principles by Russell Aronson, Mark Hibberd and
Nick Hibberd, and I am very grateful to them.&lt;&#x2F;p&gt;
&lt;p&gt;Perhaps the fundamental principle is this first one.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;expect-data-to-be-poor-quality&quot;&gt;Expect data to be poor quality&lt;&#x2F;h3&gt;
&lt;p&gt;Expect data to be poorly formed, to have errors, and work defensively to detect and correct this.
Failure to adopt this principle is indicated by sporadic failures in data pipelines with diagnoses
that point to unexpected data. These are usually accompanied by complaints, fingers pointed at
the source of the data, and judgement passed. The code base ends up with churny fixes that
patch the system to cope with these point problems - a whack-a-mole approach if you will.&lt;&#x2F;p&gt;
&lt;p&gt;Here are some examples of poor data quality in a data feed that should be expected
and accepted:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Date-formats that change over time&lt;&#x2F;li&gt;
&lt;li&gt;Schemas that change - columns disappear or appear&lt;&#x2F;li&gt;
&lt;li&gt;File formats change (dos, unix)&lt;&#x2F;li&gt;
&lt;li&gt;The size&#x2F;amount varies suddenly (possibly indicating errors upstream to the system)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The remainder of the principles are mostly in response to this fundamental principle.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;measure-the-characteristics-of-the-data&quot;&gt;Measure the characteristics of the data&lt;&#x2F;h3&gt;
&lt;p&gt;If we expect the data to be poor quality, it behooves us to gather information about data so that
we know what is being ingested and whether it should be processed. Here are some characteristics
that are relatively straightforward to collect and store as metadata:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Size&lt;&#x2F;li&gt;
&lt;li&gt;Header&lt;&#x2F;li&gt;
&lt;li&gt;Number of columns&lt;&#x2F;li&gt;
&lt;li&gt;Number of rows&lt;&#x2F;li&gt;
&lt;li&gt;Means, medians, quartiles of numeric data&lt;&#x2F;li&gt;
&lt;li&gt;Uniqueness of entries in col x&lt;&#x2F;li&gt;
&lt;li&gt;Type inference for column x (what primitive type does the column show up as - String, Int, Double or Bool)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;A corollary is that we need steps in the pipeline to act on these measurements. This is usually
a stage of the pipeline that has operational responsibility - it typically occurs soon after
ingestion&#x2F;extraction and compares incoming data with measurements from similar events. It raises
alerts and&#x2F;or stops the pipeline from processing data that is deemed suspect.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;normalise-and-enrich-the-data&quot;&gt;Normalise and enrich the data&lt;&#x2F;h3&gt;
&lt;p&gt;Have a transformation step to normalize the data to formats and schemas the pipeline can expect. The
sorts of normalising transformations that fit this step include:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Standardising file and character encodings (use command line tools like &lt;code&gt;file&lt;&#x2F;code&gt; and &lt;code&gt;iconv&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;Transforming different date and time formats&lt;&#x2F;li&gt;
&lt;li&gt;Standardising separators, padding etc. (this also allows for detection of mangled quoting in CSVs for example)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;maintain-provenance-information&quot;&gt;Maintain provenance information&lt;&#x2F;h3&gt;
&lt;p&gt;Information pertaining to the provenance of data in the system enables the ability to trace
or backtrack through transformations. It helps with diagnosing issues but also with definitively being able
to answer questions about when and from where, data entered any stage of the pipeline. The next
principle follows on quite naturally from this.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;keep-the-data-immutable&quot;&gt;Keep the data immutable&lt;&#x2F;h3&gt;
&lt;p&gt;At every step in the pipeline, source data should always be available exactly as it was first encountered.
This will address:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Concerns around processing corrupt or otherwise mangled data&lt;&#x2F;li&gt;
&lt;li&gt;Easier and faster debugging or troubleshooting&lt;&#x2F;li&gt;
&lt;li&gt;The ability to re-run any component or stage of the pipeline in isolation&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This will mean storing multiple copies of data but the copies should have different contexts (typically
corresponding to the stages of the pipeline).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;monitor-information-loss&quot;&gt;Monitor information loss&lt;&#x2F;h3&gt;
&lt;p&gt;As data traverses the pipeline it can lose information. This should not be accidental.
Consciously allow this to happen, or not.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Hopefully these principles are thought provoking and help provide some structure. They are not a complete
set by any means - please be in touch if you see errors or have suggestions for improvements. I recommend
Mark Hibberd&#x27;s &lt;a href=&quot;http:&#x2F;&#x2F;mth.io&#x2F;talks&#x2F;data-quality&#x2F;&quot;&gt;Lake, Swamp or Puddle: Data Quality at Scale&lt;&#x2F;a&gt;
for more on the topic.&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Refactoring with Applicative - a small example in Haskell</title>
            <pubDate>Sun, 27 May 2018 00:00:00 +0000</pubDate>
            <link>https://novemberkilo.com/posts/refactoring-with-applicative/</link>
            <guid>https://novemberkilo.com/posts/refactoring-with-applicative/</guid>
            <description>&lt;p&gt;Recently I came across a neat little refactoring example that I thought
might prove useful, particularly to those starting out with Haskell.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;setting-the-scene&quot;&gt;Setting the scene&lt;&#x2F;h4&gt;
&lt;p&gt;Say you have a file of comma-separated data, where each row is meant
to represent the length, breadth and height of a box. Our task is to calculate
the volume of each box. Simple, right? Well, like in real life, the data is not
complete and sometimes values are missing. We want to handle these cases by
simply not calculating a volume if any of the dimensions of the box are missing.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#282828;color:#fdf4c1aa;&quot;&gt;&lt;code&gt;&lt;span&gt;l,b,h (inputs)      v (our output)
&lt;&#x2F;span&gt;&lt;span&gt;---------------------------------
&lt;&#x2F;span&gt;&lt;span&gt;4,5,1               20
&lt;&#x2F;span&gt;&lt;span&gt;1,,                 -
&lt;&#x2F;span&gt;&lt;span&gt;3,4,                -
&lt;&#x2F;span&gt;&lt;span&gt;1,2,4               8
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;maybe-volume&quot;&gt;Maybe volume&lt;&#x2F;h3&gt;
&lt;p&gt;We&#x27;ll work towards a function to calculate volume - something with a signature like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;maybeVolume &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;:: Maybe Length -&amp;gt; Maybe Breadth -&amp;gt; Maybe Height -&amp;gt; Maybe Volume
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To illustrate the patterns at play in this example let&#x27;s start with something a bit simpler.
Let&#x27;s work with Area before we get to Volume.&lt;&#x2F;p&gt;
&lt;p&gt;A great place to start is with some data types.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;newtype &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;Length &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;Length&lt;&#x2F;span&gt;&lt;span&gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;getLength &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;:: Int
&lt;&#x2F;span&gt;&lt;span&gt;  } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;deriving&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;Eq&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;Show&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;newtype &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;Width &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;Width&lt;&#x2F;span&gt;&lt;span&gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;getWidth &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;:: Int
&lt;&#x2F;span&gt;&lt;span&gt;  } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;deriving&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;Eq&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;Show&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;newtype &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;Area &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;Area&lt;&#x2F;span&gt;&lt;span&gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;getArea &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;:: Int
&lt;&#x2F;span&gt;&lt;span&gt;  } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;deriving&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;Eq&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;Show&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So with these types our pure function for &lt;code&gt;area&lt;&#x2F;code&gt; is:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;area &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;:: Length -&amp;gt; Width -&amp;gt; Area
&lt;&#x2F;span&gt;&lt;span&gt;area l w &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;Area &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; (getLength l) * (getWidth w)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Working towards the problem at hand, let&#x27;s extend this to
a function that handles missing values. &lt;a href=&quot;https:&#x2F;&#x2F;wiki.haskell.org&#x2F;Maybe&quot;&gt;&lt;code&gt;Maybe&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
encodes the concept that a value may be missing. Following a simple pattern
matching approach gets us:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;marea &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;:: Maybe Length -&amp;gt; Maybe Width -&amp;gt; Maybe Area
&lt;&#x2F;span&gt;&lt;span&gt;marea ml mw &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;case&lt;&#x2F;span&gt;&lt;span&gt; ml &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;of
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;Nothing &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;-&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;Nothing
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;Just&lt;&#x2F;span&gt;&lt;span&gt; l &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;-&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;case&lt;&#x2F;span&gt;&lt;span&gt; mw &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;of
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;Nothing &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;-&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;Nothing
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;Just&lt;&#x2F;span&gt;&lt;span&gt; w &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;-&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;Just &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; area l w
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is fine but it is a little verbose and is ripe for some simplification.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s use the fact that &lt;code&gt;Maybe&lt;&#x2F;code&gt; is a monad. The bind operation passes through Just,
while Nothing will force the result to always be Nothing. Using &lt;code&gt;do&lt;&#x2F;code&gt; notation we
can rewrite &lt;code&gt;marea&lt;&#x2F;code&gt; like so:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;marea&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;:: Maybe Length -&amp;gt; Maybe Width -&amp;gt; Maybe Area
&lt;&#x2F;span&gt;&lt;span&gt;marea&amp;#39; ml mw &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;do
&lt;&#x2F;span&gt;&lt;span&gt;  l &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; ml
&lt;&#x2F;span&gt;&lt;span&gt;  w &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; mw
&lt;&#x2F;span&gt;&lt;span&gt;  pure &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; area l w
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The shape of &lt;code&gt;marea&#x27;&lt;&#x2F;code&gt; is exactly the motivating example for introducing applicative in
McBride and Patterson&#x27;s, &lt;a href=&quot;https:&#x2F;&#x2F;www.staff.city.ac.uk&#x2F;%7Eross&#x2F;papers&#x2F;Applicative.html&quot;&gt;Applicative Programming with Effects&lt;&#x2F;a&gt;.
Using applicative notation gets us to a one-liner.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;marea&amp;#39;&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;:: Maybe Length -&amp;gt; Maybe Width -&amp;gt; Maybe Area
&lt;&#x2F;span&gt;&lt;span&gt;marea&amp;#39;&amp;#39; ml mw &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=
&lt;&#x2F;span&gt;&lt;span&gt;  area &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;lt;$&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; ml &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; mw
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Armed with these examples, let us return to &lt;code&gt;maybeVolume.&lt;&#x2F;code&gt; We will need a couple
of extra data types.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;newtype &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;Breadth &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;Breadth&lt;&#x2F;span&gt;&lt;span&gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;getBreadth &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;:: Int
&lt;&#x2F;span&gt;&lt;span&gt;  } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;deriving&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;Eq&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;Show&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;newtype &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;Volume &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;Volume&lt;&#x2F;span&gt;&lt;span&gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;getVolume &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;:: Int
&lt;&#x2F;span&gt;&lt;span&gt;  } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;deriving&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;Eq&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;Show&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And then our pure function for &lt;code&gt;volume&lt;&#x2F;code&gt; is simply:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;volume &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;:: Length -&amp;gt; Width -&amp;gt; Breadth -&amp;gt; Volume
&lt;&#x2F;span&gt;&lt;span&gt;volume l w b &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;Volume &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; (getLength l) * (getWidth w) * (getBreadth b)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Skipping over the simplest version of the function (that uses pattern matching),
here are the monadic and applicative versions of &lt;code&gt;maybeVolume&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;-- monadic approach
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;mvolume &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;:: Maybe Length -&amp;gt; Maybe Width -&amp;gt; Maybe Breadth -&amp;gt; Maybe Volume
&lt;&#x2F;span&gt;&lt;span&gt;mvolume ml mw mb &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;do
&lt;&#x2F;span&gt;&lt;span&gt;   l &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; ml
&lt;&#x2F;span&gt;&lt;span&gt;   w &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; mw
&lt;&#x2F;span&gt;&lt;span&gt;   b &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; mb
&lt;&#x2F;span&gt;&lt;span&gt;   pure &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; volume l w b
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;-- and with applicative
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;mvolume&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;:: Maybe Length -&amp;gt; Maybe Width -&amp;gt; Maybe Breadth -&amp;gt; Maybe Volume
&lt;&#x2F;span&gt;&lt;span&gt;mvolume&amp;#39; ml mw mb &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=
&lt;&#x2F;span&gt;&lt;span&gt;    volume &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;lt;$&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; ml &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; mw &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; mb
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To wrap up, we&#x27;ve seen how to take perfectly good code that uses
pattern matching, to code that uses idiomatic Haskell patterns like
monadic &lt;code&gt;do&lt;&#x2F;code&gt; notation, and composable applicative notation. It&#x27;s routine
to run into monads and applicatives in Haskell codebases and I found
simple examples like this one to help concretely connect with them.&lt;&#x2F;p&gt;
&lt;p&gt;Highly recommend the McBride and Patterson &lt;a href=&quot;https:&#x2F;&#x2F;www.staff.city.ac.uk&#x2F;%7Eross&#x2F;papers&#x2F;Applicative.html&quot;&gt;paper&lt;&#x2F;a&gt;
on applicatives by the way. Same goes for pretty much anything written by Conor McBride.&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Postgres JSON Functions From Rails</title>
            <pubDate>Sun, 25 May 2014 00:00:00 +0000</pubDate>
            <link>https://novemberkilo.com/posts/json-finders/</link>
            <guid>https://novemberkilo.com/posts/json-finders/</guid>
            <description>&lt;p&gt;Say you are storing JSON in Postgres and need scopes to get records
based on their JSON attributes. This post covers the use of JSON functions
available in Postgres v9.3 to achieve this.&lt;&#x2F;p&gt;
&lt;p&gt;Suppose you have an Order class, containing a JSON blob that describes
the product that the order relates to:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ruby&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-ruby &quot;&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;# == Schema Information
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;#
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;# Table name: orders
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;#
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;#  id                                    :integer  not null, primary key
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;#  customer_id                           :integer
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;#  product                               :json
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;#  created_at                            :datetime
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;#  updated_at                            :datetime
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;Order &lt;&#x2F;span&gt;&lt;span&gt;&amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;ActiveRecord&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;::Base
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;end
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Suppose &lt;code&gt;product&lt;&#x2F;code&gt; has the following structure:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;json&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-json &quot;&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;name&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;Widget 01&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;code&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;W001&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;plan&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;name&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;Silver&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;terms&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;12 months&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;   },
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;created_at&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;2013-12-22 09:27:45 UTC&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;updated_at&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;2014-10-21 10:30:40 UTC&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And you want a scope on &lt;code&gt;Order&lt;&#x2F;code&gt; to find all orders with a particular
code - something like &lt;code&gt;Order.with_code(&amp;quot;W001&amp;quot;)&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;If you are using version 9.3 of Postgres, you can get it to do the heavy
lifting for you using its &lt;a href=&quot;http:&#x2F;&#x2F;www.postgresql.org&#x2F;docs&#x2F;9.3&#x2F;static&#x2F;functions-json.html&quot;&gt;JSON functions&lt;&#x2F;a&gt;
like so:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ruby&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-ruby &quot;&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span&gt;scope &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;:with_code&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;(code) { where(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;product -&amp;gt;&amp;gt; &amp;#39;code&amp;#39; = ?&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, code) }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Getting to nested JSON attributes is a bit trickier. Say you want a
scope for all orders with a particular plan name - something like
&lt;code&gt;Order.with_plan_name(&amp;quot;Silver&amp;quot;)&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ruby&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-ruby &quot;&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span&gt;scope &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;:with_plan_name&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;(plan_name) { where(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;product::json #&amp;gt;&amp;gt; &amp;#39;{ plan,name }&amp;#39; = ?&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, plan_name) }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I got to these by looking through Stack Overflow posts, grokking the Postgres
docs on JSON functions and &lt;a href=&quot;http:&#x2F;&#x2F;devblog.avdi.org&#x2F;2014&#x2F;01&#x2F;31&#x2F;playing-with-json-in-postgres&#x2F;&quot;&gt;this post&lt;&#x2F;a&gt;
of Avdi Grimm&#x27;s. As usual, you can&#x27;t comment here but if you see an error or
want to offer a suggestion for improvement, please get in touch via email.&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Handy scopes for associations</title>
            <pubDate>Sun, 29 Sep 2013 00:00:00 +0000</pubDate>
            <link>https://novemberkilo.com/posts/scopes-for-empty-relationships/</link>
            <guid>https://novemberkilo.com/posts/scopes-for-empty-relationships/</guid>
            <description>&lt;p&gt;If your Rails project has a has-many association and you want a way of finding records that have no associated records, or,
records that have at least one associated record, you might find this post useful.&lt;&#x2F;p&gt;
&lt;p&gt;Suppose you have classes &lt;code&gt;Person&lt;&#x2F;code&gt; and &lt;code&gt;Friend&lt;&#x2F;code&gt; that are associated via a &lt;code&gt;has_many&lt;&#x2F;code&gt; relationship:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ruby&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-ruby &quot;&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;Person &lt;&#x2F;span&gt;&lt;span&gt;&amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;ActiveRecord&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;::Base
&lt;&#x2F;span&gt;&lt;span&gt;  has_many &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;:friends
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;end
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;Friend &lt;&#x2F;span&gt;&lt;span&gt;&amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;ActiveRecord&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;::Base
&lt;&#x2F;span&gt;&lt;span&gt;  belongs_to &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;:person
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;end
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;How do you find &lt;code&gt;persons&lt;&#x2F;code&gt; that have no &lt;code&gt;friends&lt;&#x2F;code&gt;?&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ruby&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-ruby &quot;&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;Person&lt;&#x2F;span&gt;&lt;span&gt;.includes(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;:friends&lt;&#x2F;span&gt;&lt;span&gt;).where(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;friends.person_id IS NULL&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Or that have at least one &lt;code&gt;friend&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ruby&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-ruby &quot;&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;Person&lt;&#x2F;span&gt;&lt;span&gt;.includes(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;:friends&lt;&#x2F;span&gt;&lt;span&gt;).where(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;friends.person_id IS NOT NULL&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h4 id=&quot;using-arel&quot;&gt;Using Arel&lt;&#x2F;h4&gt;
&lt;p&gt;To accomplish this with Arel
set up the following scopes on &lt;code&gt;Friend&lt;&#x2F;code&gt; (thanks to &lt;a href=&quot;http:&#x2F;&#x2F;twitter.com&#x2F;macfanatic&quot;&gt;@macfanatic&lt;&#x2F;a&gt; for the tip),&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ruby&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-ruby &quot;&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;Friend
&lt;&#x2F;span&gt;&lt;span&gt;  belongs_to &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;:person
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  scope &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;:to_somebody&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;{ where arel_table[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;:person_id&lt;&#x2F;span&gt;&lt;span&gt;].not_eq(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;nil&lt;&#x2F;span&gt;&lt;span&gt;) }
&lt;&#x2F;span&gt;&lt;span&gt;  scope &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;:to_nobody&lt;&#x2F;span&gt;&lt;span&gt;,   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;{ where arel_table[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;:person_id&lt;&#x2F;span&gt;&lt;span&gt;].eq(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;nil&lt;&#x2F;span&gt;&lt;span&gt;) }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;end
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And then, Persons who have at least one friend:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ruby&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-ruby &quot;&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;Person&lt;&#x2F;span&gt;&lt;span&gt;.includes(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;:friends&lt;&#x2F;span&gt;&lt;span&gt;).merge(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;Friend&lt;&#x2F;span&gt;&lt;span&gt;.to_somebody)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The friendless:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ruby&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-ruby &quot;&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;Person&lt;&#x2F;span&gt;&lt;span&gt;.includes(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;:friends&lt;&#x2F;span&gt;&lt;span&gt;).merge(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;Friend&lt;&#x2F;span&gt;&lt;span&gt;.to_nobody)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;em&gt;Note:&lt;&#x2F;em&gt; If you are on Rails 4 don&#x27;t forget to append &lt;code&gt;references(:friends)&lt;&#x2F;code&gt; to these.&lt;&#x2F;p&gt;
</description>
        </item>
    </channel>
</rss>
