<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  <title>Coding on the Road</title>
  <subtitle>Erratic thoughts from a travelling programmer</subtitle>
  <link href="https://codingontheroad.com/feed.xml" rel="self" />
  <link href="https://codingontheroad.com/" />
  <updated>2023-08-13T00:00:00Z</updated>
  <id>https://codingontheroad.com/</id>
  <author>
    <name>Igor de Alcantara Barroso</name>
    <email>igor@coderative.fr</email>
  </author>
  <entry>
    <title>DPG</title>
    <link href="https://codingontheroad.com/posts/dockerized-postgres/" />
    <updated>2023-08-13T00:00:00Z</updated>
    <id>https://codingontheroad.com/posts/dockerized-postgres/</id>
    <content type="html">&lt;p&gt;Most of the time, projects I work on are using PostgreSQL as their database. But they don&#39;t necessarily use the same
version, and this can lead to some subtle surprises. Fortunately, today most projects use Docker and Docker Compose
which makes it explicit which version a project depends on.&lt;/p&gt;
&lt;p&gt;But every now and again, it happens to run into a project that doesn&#39;t use Docker. And I don&#39;t want to add it as a
dependency, especially for local development. This is even more the case, if there are already other team members with
their own setup.&lt;/p&gt;
&lt;p&gt;For that I wrote a &lt;a href=&quot;https://gist.github.com/idabmat/59e08ae6ddb1e169ff07494990d62f90&quot;&gt;small wrapper&lt;/a&gt; around Docker, that
has a similar interface than Docker Compose. I&#39;ve saved it in my &lt;code&gt;PATH&lt;/code&gt; as &lt;code&gt;dpg&lt;/code&gt;. It requires &lt;code&gt;ruby&lt;/code&gt;, &lt;code&gt;thor&lt;/code&gt;
(&lt;code&gt;gem install thor&lt;/code&gt;), and of course &lt;code&gt;Docker&lt;/code&gt;.&lt;/p&gt;
&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://codingontheroad.com/img/4dVum2vIep-400.webp 400w, https://codingontheroad.com/img/4dVum2vIep-800.webp 800w, https://codingontheroad.com/img/4dVum2vIep-1280.webp 1280w&quot; sizes=&quot;100vh&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://codingontheroad.com/img/4dVum2vIep-400.jpeg&quot; alt=&quot;dpg usage screenshot&quot; width=&quot;1280&quot; height=&quot;428&quot; srcset=&quot;https://codingontheroad.com/img/4dVum2vIep-400.jpeg 400w, https://codingontheroad.com/img/4dVum2vIep-800.jpeg 800w, https://codingontheroad.com/img/4dVum2vIep-1280.jpeg 1280w&quot; sizes=&quot;100vh&quot;&gt;&lt;/picture&gt;
</content>
  </entry>
  <entry>
    <title>Extracting workers from Rails</title>
    <link href="https://codingontheroad.com/posts/extracting-workers-from-rails/" />
    <updated>2018-06-14T00:00:00Z</updated>
    <id>https://codingontheroad.com/posts/extracting-workers-from-rails/</id>
    <content type="html">&lt;p&gt;Sidekiq has always been my go-to gem as soon as I need some sort of background
processing in a Rails app. But one thing that always felt weird to me with
background workers is having the web and the workers instances share the same
code. If what I want is to process some jobs asynchronously, does my worker
instance really need to load my entire Rails app?&lt;/p&gt;
&lt;p&gt;As an experiment, I decided to have my rails API post a JSON payload describing a
given job straight to Redis. A separate app containing the worker logic then
pulls that payload from Redis in order to process the job.&lt;/p&gt;
&lt;p&gt;The following is a walk through of that experiment, using Docker for local
development. If you prefer to browse the code directly, I&#39;ve &lt;a href=&quot;https://github.com/idabmat/rails-without-jobs&quot;&gt;uploaded it to
GitHub&lt;/a&gt;. And if you prefer to skip
to the conclusion of this experiment, feel free to scroll to the bottom.&lt;/p&gt;
&lt;h2&gt;Setup&lt;/h2&gt;
&lt;p&gt;At the root, let&#39;s start by creating a &lt;code&gt;docker-compose.yml&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;3&quot;&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ./api
    &lt;span class=&quot;token key atrule&quot;&gt;depends_on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; db
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; sidekiq
    &lt;span class=&quot;token key atrule&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;3000:3000&quot;&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; ./api&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;/api
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; api_bundle&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;/usr/local/bundle
  &lt;span class=&quot;token key atrule&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; postgres&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;alpine
    &lt;span class=&quot;token key atrule&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; postgres
    &lt;span class=&quot;token key atrule&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;5432:5432&quot;&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;redis&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; redis&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;alpine
    &lt;span class=&quot;token key atrule&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;6379:6379&quot;&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;sidekiq&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ./sidekiq
    &lt;span class=&quot;token key atrule&quot;&gt;depends_on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; redis
    &lt;span class=&quot;token key atrule&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; ./sidekiq&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;/sidekiq
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; sidekiq_bundle&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;/usr/local/bundle
&lt;span class=&quot;token key atrule&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;api_bundle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;sidekiq_bundle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This way we can spin up the different apps together and make sure they can
communicate with one another.&lt;/p&gt;
&lt;p&gt;Now let&#39;s configure a basic worker.&lt;/p&gt;
&lt;h2&gt;The worker&lt;/h2&gt;
&lt;p&gt;We can create an app to pull the jobs from Redis in &lt;code&gt;./sidekiq&lt;/code&gt; by just
creating a Gemfile in &lt;code&gt;./sidekiq/Gemfile&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# frozen_string_literal: true&lt;/span&gt;

source &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;https://rubygems.org&#39;&lt;/span&gt;&lt;/span&gt;
git_source&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;:github&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;repo_name&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;https://github.com/&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token delimiter punctuation&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;token content&quot;&gt;repo_name&lt;/span&gt;&lt;span class=&quot;token delimiter punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

ruby &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;2.5.1&#39;&lt;/span&gt;&lt;/span&gt;

gem &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;sidekiq&#39;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then we configure our docker image by creating a file in &lt;code&gt;./sidekiq/Dockerfile&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-dockerfile&quot;&gt;&lt;code class=&quot;language-dockerfile&quot;&gt;&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;FROM&lt;/span&gt; ruby:2.5-alpine&lt;/span&gt;

&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;WORKDIR&lt;/span&gt; /sidekiq&lt;/span&gt;

&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;COPY&lt;/span&gt; Gemfile* ./&lt;/span&gt;

&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;RUN&lt;/span&gt; apk update &lt;span class=&quot;token operator&quot;&gt;&#92;&lt;/span&gt;
 &amp;amp;&amp;amp; apk upgrade &lt;span class=&quot;token operator&quot;&gt;&#92;&lt;/span&gt;
 &amp;amp;&amp;amp; bundle install&lt;/span&gt;

&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;RUN&lt;/span&gt; addgroup -g 1000 -S sidekiq &lt;span class=&quot;token operator&quot;&gt;&#92;&lt;/span&gt;
 &amp;amp;&amp;amp; adduser -u 1000 -S sidekiq -G sidekiq &lt;span class=&quot;token operator&quot;&gt;&#92;&lt;/span&gt;
 &amp;amp;&amp;amp; chown -R sidekiq:sidekiq /sidekiq&lt;/span&gt;
&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;USER&lt;/span&gt; sidekiq&lt;/span&gt;

&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;CMD&lt;/span&gt; [&lt;span class=&quot;token string&quot;&gt;&quot;bundle&quot;&lt;/span&gt;, &lt;span class=&quot;token string&quot;&gt;&quot;exec&quot;&lt;/span&gt;, &lt;span class=&quot;token string&quot;&gt;&quot;sidekiq&quot;&lt;/span&gt;, &lt;span class=&quot;token string&quot;&gt;&quot;-r&quot;&lt;/span&gt;, &lt;span class=&quot;token string&quot;&gt;&quot;./worker.rb&quot;&lt;/span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And finally we need to create our &lt;code&gt;./sidekiq/worker.rb&lt;/code&gt; file that will
contain the actual worker logic.&lt;/p&gt;
&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;sidekiq&#39;&lt;/span&gt;&lt;/span&gt;

Sidekiq&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;configure_server &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;config&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
  config&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;redis &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;redis://redis:6379&#39;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MyWorker&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;include&lt;/span&gt; Sidekiq&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;Worker

  &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token method-definition&quot;&gt;&lt;span class=&quot;token function&quot;&gt;perform&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;complexity&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; complexity
    &lt;span class=&quot;token keyword&quot;&gt;when&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;super hard&#39;&lt;/span&gt;&lt;/span&gt;
      sleep &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;
      puts &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;This took a while!&#39;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;when&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;hard&#39;&lt;/span&gt;&lt;/span&gt;
      sleep &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;
      puts &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Not too bad&#39;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
      sleep &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
      puts &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Piece of cake&#39;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;One thing to notice here is that we only need to configure the Sidekiq&#39;s server
to process jobs, no client configuration needed.&lt;/p&gt;
&lt;p&gt;With this basic worker done, we can now focus on setting up our Rails API.&lt;/p&gt;
&lt;h2&gt;The Rails API&lt;/h2&gt;
&lt;p&gt;First we create our app with &lt;code&gt;rails new api -d postgresql --skip-bundle --api&lt;/code&gt;.
Then we can add the redis gem to our &lt;code&gt;./api/Gemfile&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;gem &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;redis&#39;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For our container image we create the following &lt;code&gt;./api/Dockerfile&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-dockerfile&quot;&gt;&lt;code class=&quot;language-dockerfile&quot;&gt;&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;FROM&lt;/span&gt; ruby:2.5-alpine&lt;/span&gt;

&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;WORKDIR&lt;/span&gt; /api&lt;/span&gt;

&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;COPY&lt;/span&gt; Gemfile* ./&lt;/span&gt;

&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;RUN&lt;/span&gt; apk update &lt;span class=&quot;token operator&quot;&gt;&#92;&lt;/span&gt;
 &amp;amp;&amp;amp; apk upgrade &lt;span class=&quot;token operator&quot;&gt;&#92;&lt;/span&gt;
 &amp;amp;&amp;amp; apk add --no-cache postgresql-dev tzdata&lt;span class=&quot;token operator&quot;&gt;&#92;&lt;/span&gt;
 &amp;amp;&amp;amp; apk add --virtual .build-dependencies g++ make libffi-dev libxml2-dev zlib-dev libxslt-dev &lt;span class=&quot;token operator&quot;&gt;&#92;&lt;/span&gt;
 &amp;amp;&amp;amp; bundle install &lt;span class=&quot;token operator&quot;&gt;&#92;&lt;/span&gt;
 &amp;amp;&amp;amp; apk del .build-dependencies&lt;/span&gt;


&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;RUN&lt;/span&gt; addgroup -g 1000 -S api &lt;span class=&quot;token operator&quot;&gt;&#92;&lt;/span&gt;
 &amp;amp;&amp;amp; adduser -u 1000 -S api -G api &lt;span class=&quot;token operator&quot;&gt;&#92;&lt;/span&gt;
 &amp;amp;&amp;amp; chown api:api /api&lt;/span&gt;
&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;USER&lt;/span&gt; api&lt;/span&gt;

&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;EXPOSE&lt;/span&gt; 3000&lt;/span&gt;

&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;CMD&lt;/span&gt; [&lt;span class=&quot;token string&quot;&gt;&quot;bundle&quot;&lt;/span&gt;, &lt;span class=&quot;token string&quot;&gt;&quot;exec&quot;&lt;/span&gt;, &lt;span class=&quot;token string&quot;&gt;&quot;rails&quot;&lt;/span&gt;, &lt;span class=&quot;token string&quot;&gt;&quot;s&quot;&lt;/span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Our Rails app will need to know how to access the database service we specified
in our docker-compose file. The simplest way to do this is to edit
&lt;code&gt;./api/config/database.yml&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token important&quot;&gt;&amp;amp;default&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;adapter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; postgresql
  &lt;span class=&quot;token key atrule&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; unicode
  &lt;span class=&quot;token key atrule&quot;&gt;pool&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &amp;lt;%= ENV.fetch(&quot;RAILS_MAX_THREADS&quot;) &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; %&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;postgres://postgres:postgres@db:5432&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now for actually sending the data to Sidekiq, I like to create a specific
gateway class to encapsulate that logic. We can create the following file
&lt;code&gt;./api/lib/my_app/gateway/sidekiq.rb&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;json&#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;redis&#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;securerandom&#39;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MyApp&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Gateway&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Sidekiq&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token method-definition&quot;&gt;&lt;span class=&quot;token function&quot;&gt;initialize&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;redis&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Redis&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token variable&quot;&gt;@redis&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; redis&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;redis://redis:6379&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token method-definition&quot;&gt;&lt;span class=&quot;token function&quot;&gt;do_later&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;klass&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        message &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; create_message&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;klass&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; klass&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; args&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token variable&quot;&gt;@redis&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lpush&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;queue:default&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dump&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token method-definition&quot;&gt;&lt;span class=&quot;token function&quot;&gt;create_message&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;klass&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;class&#39;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; klass&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;queue&#39;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;default&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;args&#39;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; args&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;jid&#39;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; SecureRandom&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hex&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;retry&#39;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;created_at&#39;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Time&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;now&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;to_f&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;enqueued_at&#39;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Time&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;now&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;to_f
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Basically to use this, we instantiate the gateway class, then
call &lt;code&gt;do_later&lt;/code&gt; on the instance passing the name of the worker class (in our case this
will be &lt;code&gt;MyWorker&lt;/code&gt;) and an &lt;strong&gt;array&lt;/strong&gt; of arguments (in our case &lt;code&gt;[&#39;hard&#39;]&lt;/code&gt; will
do).&lt;/p&gt;
&lt;h2&gt;Adding an endpoint&lt;/h2&gt;
&lt;p&gt;For us to play with this, let&#39;s set up an API endpoint where we can post data to
trigger the background job. First we create a route in &lt;code&gt;./api/config/routes.rb&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;Rails&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;application&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;routes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;draw &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
  post &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;/process&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;process#create&#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then we create the matching controller in
&lt;code&gt;./api/app/controllers/process_controller.rb&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;my_app/gateway/sidekiq&#39;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ProcessController&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; ApplicationController
  &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token method-definition&quot;&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;/span&gt;
    job &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; MyApp&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;Gateway&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Sidekiq&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt;
    job&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;do_later&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;token symbol&quot;&gt;klass&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;MyWorker&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token symbol&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;params&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;complexity&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This way we send the &lt;code&gt;complexity&lt;/code&gt; param as the single argument to the background
job.&lt;/p&gt;
&lt;h2&gt;Live Action&lt;/h2&gt;
&lt;p&gt;OK time to see it in action. Let&#39;s build our container images and start our
services. In the terminal:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;docker-compose build&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docker-compose run --rm api rails db:setup db:migrate&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docker-compose up&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In a separate terminal window we can send a post request:&lt;/p&gt;
&lt;pre class=&quot;language-sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-X&lt;/span&gt; POST http://localhost:3000/process &lt;span class=&quot;token parameter variable&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;complexity=hard&quot;&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;
&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://codingontheroad.com/img/Qa58R4H3s6-400.webp 400w, https://codingontheroad.com/img/Qa58R4H3s6-800.webp 800w&quot; sizes=&quot;100vh&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://codingontheroad.com/img/Qa58R4H3s6-400.jpeg&quot; alt=&quot;POST request and Sidekiq worker output&quot; width=&quot;800&quot; height=&quot;380&quot; srcset=&quot;https://codingontheroad.com/img/Qa58R4H3s6-400.jpeg 400w, https://codingontheroad.com/img/Qa58R4H3s6-800.jpeg 800w&quot; sizes=&quot;100vh&quot;&gt;&lt;/picture&gt;
&lt;h2&gt;Takeaway&lt;/h2&gt;
&lt;p&gt;On one hand, I&#39;m quite happy with the separation of responsibility here. If we
wanted to use Sidekiq but with a different API that was not even written in Ruby,
this setup would work. Conversely, if we needed to change our background
processing engine, the only change required on our API would be to swap our
gateway for a new one.&lt;/p&gt;
&lt;p&gt;On the other hand, having one app know the class names of another one still
sounds like too much coupling.&lt;/p&gt;
&lt;p&gt;More information can be found on Sidekiq&#39;s wiki if you want to &lt;a href=&quot;https://github.com/mperham/sidekiq/wiki/FAQ#how-do-i-push-a-job-to-sidekiq-without-ruby&quot;&gt;push jobs to it without Ruby&lt;/a&gt; or if you want more information on &lt;a href=&quot;https://github.com/mperham/sidekiq/wiki/Job-Format&quot;&gt;the job format&lt;/a&gt;. Also, you can check out &lt;a href=&quot;https://github.com/contribsys/faktory&quot;&gt;Faktory&lt;/a&gt; (by the same creator of Sidekiq) as it has clients written in several languages.&lt;/p&gt;
&lt;p&gt;Did you try something similar in a past project? Were there any pain points
with this approach? Let me know in the comments ;)&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Algebra Equality And Elixir Match Operator</title>
    <link href="https://codingontheroad.com/posts/algebra-equality-and-elixir-match-operator/" />
    <updated>2017-05-20T00:00:00Z</updated>
    <id>https://codingontheroad.com/posts/algebra-equality-and-elixir-match-operator/</id>
    <content type="html">&lt;link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.css&quot; integrity=&quot;sha384-nB0miv6/jRmo5UMMR1wu3Gz6NLsoTkbqJghGIsx//Rlm+ZU03BU6SQNC66uf4l5+&quot; crossorigin=&quot;anonymous&quot;&gt;
&lt;script defer=&quot;&quot; src=&quot;https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.js&quot; integrity=&quot;sha384-7zkQWkzuo3B5mTepMUcHkMB5jZaolc2xDwL6VFqjFALcbeS9Ggm/Yr2r3Dy4lfFg&quot; crossorigin=&quot;anonymous&quot;&gt;&lt;/script&gt;
&lt;script defer=&quot;&quot; src=&quot;https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/contrib/auto-render.min.js&quot; integrity=&quot;sha384-43gviWU0YVjaDtb/GhzOouOXtZMP/7XUzwPTstBeZFe/+rCMvRwr4yROQP43s0Xk&quot; crossorigin=&quot;anonymous&quot; onload=&quot;renderMathInElement(document.body);&quot;&gt;&lt;/script&gt;
&lt;p&gt;As the main driver of Moore&#39;s Law today seems to be the increase of processing
cores instead of a processor&#39;s clock speed, modern software has to truly
embrace parallel computing in order to fully use the available resources. In
this scenario, functional programming started becoming increasingly relevant.
More than just the newest buzzword, some are heralding it as the next step in
programming evolution.&lt;/p&gt;
&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://codingontheroad.com/img/VGR4-D4rc3-400.webp 400w, https://codingontheroad.com/img/VGR4-D4rc3-800.webp 800w&quot; sizes=&quot;100vh&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://codingontheroad.com/img/VGR4-D4rc3-400.jpeg&quot; alt=&quot;Evolution from monkey to Homer Simpson&quot; width=&quot;800&quot; height=&quot;355&quot; srcset=&quot;https://codingontheroad.com/img/VGR4-D4rc3-400.jpeg 400w, https://codingontheroad.com/img/VGR4-D4rc3-800.jpeg 800w&quot; sizes=&quot;100vh&quot;&gt;&lt;/picture&gt;
&lt;p&gt;Curiously, due to my background in Mathematics and the computer science
professor I had in college, my first computer science lessons were in functional
programming more than 10 years ago. As much as I enjoyed writing code in a
functional style, I never envisioned it gaining traction, as I felt it had a
more academic flavor to it. Personally moving from functional to
object-oriented programming was a revolution and enabled me to speak a more
widespread dialect. It is funny how certain things play out.&lt;/p&gt;
&lt;p&gt;Recently I have been investing some time looking more closely into Elixir. After
having read some blog posts, gone through a couple of tutorials, and played the
obligatory CodeSchool challenges, I decided to get myself a copy of Dave
Thomas&#39; Programming Elixir 1.3. Most resources start by explaining the match
operator. As most languages use the &lt;code&gt;=&lt;/code&gt; symbol to represent assignment, some
relearning has to be done to understand what &lt;code&gt;=&lt;/code&gt; does in Elixir.&lt;/p&gt;
&lt;h2&gt;The Match Operator&lt;/h2&gt;
&lt;p&gt;In case you haven&#39;t heard of it before, here is quick run through of how the equals sign work
in Elixir.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;iex(1)&amp;gt; a = 1
1
iex(2)&amp;gt; a
1
iex(3)&amp;gt; a = 2
2
iex(4)&amp;gt; a
2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Looks pretty standard right? Then what about this?&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;iex(1)&amp;gt; a = 1
1
iex(2)&amp;gt; a
1
iex(3)&amp;gt; 1 = a
1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What kind of black magic is &lt;code&gt;1 = a&lt;/code&gt;? Well, turns out the &lt;code&gt;=&lt;/code&gt; symbol in Elixir
kind of acts first as an assertion (&lt;code&gt;==&lt;/code&gt;), then if the assertion in not
downright false, it tries to act as an assignment (&lt;code&gt;:=&lt;/code&gt;). I like to think of it
this way:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Is the assertion true?&lt;/li&gt;
&lt;li&gt;If not, are there variables on the &lt;strong&gt;left&lt;/strong&gt; side whose value could be changed
to make the assertion pass? If so, bind that value to that variable.&lt;/li&gt;
&lt;li&gt;If all the above fail, blow up.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With this in mind let&#39;s run through the previous example.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;a = 1&lt;/code&gt; is false as &lt;code&gt;a&lt;/code&gt; is undefined. Can we assign a value to &lt;code&gt;a&lt;/code&gt; such that
the assertion would be true? In this case, yes, so let&#39;s bind the value &lt;code&gt;1&lt;/code&gt;
to the variable &lt;code&gt;a&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;What value is bound to &lt;code&gt;a&lt;/code&gt;? &lt;code&gt;1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Is &lt;code&gt;1 = a&lt;/code&gt;? Yes it is.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So what would happen, if we then asked &lt;code&gt;2 = a&lt;/code&gt;?&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;iex(4)&amp;gt; 2 = a
** (MatchError) no match of right hand side value: 1 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We get an error as no match between the left and the right-hand side were
possible. (Did I tell you how much I like the error messages in Elixir?).&lt;/p&gt;
&lt;p&gt;Why was Erlang (the language Elixir builds upon) designed like this? Because
this opens the door to pattern matching, which can allow you to do some
non-trivial assignments in a way that can be quite elegant. Here is a random
example (no elegance there).&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;iex(1)&amp;gt; [1,b,c]=[1,2,[3,4]]
[1, 2, [3, 4]]
iex(2)&amp;gt; b
2
iex(3)&amp;gt; c
[3, 4]
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Algebra Equality&lt;/h2&gt;
&lt;p&gt;As this behavior may differ from what some people are accustomed to, a common
metaphor used to explain it is the equality in Algebra.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Joe Armstrong, Erlang’s creator, compares the equals sign in Erlang to that used in algebra. When you write the equation x = a + 1, you are not assigning the value of a + 1 to x. Instead, you’re simply asserting that the expressions x and a + 1 have the same value. If you know the value of x, you can work out the value of a, and vice versa.&lt;/p&gt;
&lt;p&gt;-- &lt;cite&gt;Dave Thomas&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;While I think this is a good enough analogy and that the equals signs in Elixir
indeed allows to do some powerful things, it still falls short if compared to
the equality in Algebra, and &#92;(x = a + 1&#92;) is not really a good example to
showcase their similarities.&lt;/p&gt;
&lt;p&gt;In Algebra, the equality is a special binary relation called an equivalence
relation. For a binary relation to be an equivalence relation, it must be:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Reflexive&lt;/strong&gt;. &lt;code&gt;a&lt;/code&gt; must be equal to &lt;code&gt;a&lt;/code&gt;.&lt;br&gt;
$$
a = a
$$&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Symmetrical&lt;/strong&gt;. If &lt;code&gt;a&lt;/code&gt; equals &lt;code&gt;b&lt;/code&gt;, then &lt;code&gt;b&lt;/code&gt; equals &lt;code&gt;a&lt;/code&gt;.&lt;br&gt;
$$
a = b &#92;Longrightarrow b = a
$$&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Transitive&lt;/strong&gt;. If &lt;code&gt;a&lt;/code&gt; equals &lt;code&gt;b&lt;/code&gt;, and &lt;code&gt;b&lt;/code&gt; equals &lt;code&gt;c&lt;/code&gt;, then &lt;code&gt;a&lt;/code&gt; equals &lt;code&gt;c&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;$$
&#92;begin{cases}
a = b&#92;&#92;
b = c
&#92;end{cases}
&#92;Longrightarrow
a = c
$$&lt;/p&gt;
&lt;p&gt;Of those three, only the transitivity is assured by the match operator. This
means that with the quoted example &#92;(x = a + 1&#92;) Elixir will not be able to
determine the value of &lt;code&gt;a&lt;/code&gt; if it knows the value of &lt;code&gt;x&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;iex(1)&amp;gt; x = 1
1
iex(2)&amp;gt; x = a + 1
warning: variable &amp;quot;a&amp;quot; does not exist and is being expanded to &amp;quot;a()&amp;quot;, please use parentheses to remove the ambiguity or change the variable name
  iex:2

** (CompileError) iex:2: undefined function a/0
    (stdlib) lists.erl:1354: :lists.mapfoldl/3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As the undefined variable is on the &lt;strong&gt;right&lt;/strong&gt;-hand side of the match, Elixir
does not try to bind a value to it. Instead, here it assumes &lt;code&gt;a&lt;/code&gt; is a function,
which is obviously undefined, hence the &lt;code&gt;CompileError&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;But trying to determine the value of &lt;code&gt;x&lt;/code&gt; when the value of &lt;code&gt;a&lt;/code&gt; is known works.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;iex(1)&amp;gt; a = 3
3
iex(2)&amp;gt; x = a + 1
4
iex(3)&amp;gt; x
4
&lt;/code&gt;&lt;/pre&gt;
</content>
  </entry>
  <entry>
    <title>Integrating a rails blog with Facebook instant articles</title>
    <link href="https://codingontheroad.com/posts/integrating-a-rails-blog-with-facebook-instant-articles/" />
    <updated>2016-11-30T00:00:00Z</updated>
    <id>https://codingontheroad.com/posts/integrating-a-rails-blog-with-facebook-instant-articles/</id>
    <content type="html">&lt;p&gt;On a recent project, a client asked for a dynamic website and a blog. Since most
of their interaction with customers happened through their Facebook Page, they
asked for a number of integrations between their new site and Facebook. Aside
from the usual &lt;em&gt;like&lt;/em&gt;, &lt;em&gt;share&lt;/em&gt;, and &lt;em&gt;comment&lt;/em&gt; stuff, it was
an opportunity to play with the new &lt;a href=&quot;https://instantarticles.fb.com/&quot;&gt;Instant
Article&lt;/a&gt; format.&lt;/p&gt;
&lt;p&gt;After reading Facebook&#39;s documentation, it seemed the simplest way was to create a good old
RSS feed and hand it to the Facebook Page. &lt;a href=&quot;https://developers.facebook.com/docs/instant-articles/publishing/setup-rss-feed&quot;&gt;Here&lt;/a&gt; is the corresponding article from their documentation.&lt;/p&gt;
&lt;p&gt;In this post I will focus only on creating that feed from an existing blog. If you&#39;re interested, this minimal example is on &lt;a href=&quot;https://github.com/idabmat/rails-instant-articles&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Essentially the steps were:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create an &lt;code&gt;instant_articles&lt;/code&gt; controller with an &lt;code&gt;index&lt;/code&gt; and a &lt;code&gt;show&lt;/code&gt; action&lt;/li&gt;
&lt;li&gt;Create the &lt;code&gt;show&lt;/code&gt; template with all the markup necessary for Facebook to create an
Instant Article.&lt;/li&gt;
&lt;li&gt;Create an &lt;code&gt;index&lt;/code&gt; template for the RSS feed containing every article.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;The models&lt;/h2&gt;
&lt;p&gt;Before diving in, this example will use an &lt;code&gt;Article&lt;/code&gt; and an &lt;code&gt;Author&lt;/code&gt; model with
the following attributes:&lt;/p&gt;
&lt;h3&gt;Article&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;belongs_to&lt;/code&gt; an author&lt;/li&gt;
&lt;li&gt;Has a &lt;code&gt;title&lt;/code&gt;, a &lt;code&gt;subtitle&lt;/code&gt;, a &lt;code&gt;kicker&lt;/code&gt;, and a &lt;code&gt;body&lt;/code&gt;&lt;br&gt;
The &lt;code&gt;body&lt;/code&gt; should be in HTML, so you should probably use a WYSIWYG editor if you&#39;re building for a client. One caveat is
that Facebook basically only parses &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;figure&amp;gt;&lt;/code&gt; tags for the body of the article. In my case I used
&lt;a href=&quot;https://trix-editor.org&quot;&gt;trix&lt;/a&gt;, which defaults to using &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; tags for the
content. It took me some time to figure out why Facebook was complaining that the
Instant Articles were empty. The solution was to build trix from source with the
correct config flag. If you use another editor, YMMV.&lt;/li&gt;
&lt;li&gt;Has a &lt;code&gt;cover_url&lt;/code&gt; and a &lt;code&gt;cover_description&lt;/code&gt;&lt;br&gt;
For simplicity here, I defined a &lt;code&gt;cover_url&lt;/code&gt; method on the &lt;code&gt;Article&lt;/code&gt; model which
points to &lt;a href=&quot;https://unsplash.it&quot;&gt;unsplash.it&lt;/a&gt;. Attaching an image to a Rails
model is beyond the scope of this post. Checkout
&lt;a href=&quot;https://github.com/thoughtbot/paperclip&quot;&gt;Paperclip&lt;/a&gt; or
&lt;a href=&quot;https://github.com/carrierwaveuploader/carrierwave&quot;&gt;Carrierwave&lt;/a&gt; if you need that.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Author&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;has_many&lt;/code&gt; articles&lt;/li&gt;
&lt;li&gt;has a &lt;code&gt;name&lt;/code&gt; and a &lt;code&gt;bio&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;The controller&lt;/h2&gt;
&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# app/controllers/instant_articles&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;InstantArticlesController&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; ApplicationController
  &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token method-definition&quot;&gt;&lt;span class=&quot;token function&quot;&gt;index&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token variable&quot;&gt;@articles&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Article&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;all
  &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token method-definition&quot;&gt;&lt;span class=&quot;token function&quot;&gt;show&lt;/span&gt;&lt;/span&gt;
    article &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Article&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;find&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;params&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;:id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    render layout&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;locals&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;article&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; article &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Pretty conventional, except for the &lt;code&gt;show&lt;/code&gt; action. We need to pass the article
as a local variable to the render method instead of using an instance variable.
The reason for that will be clear in the &lt;code&gt;index.rss.builder&lt;/code&gt; template where we will need
to render the &lt;code&gt;show&lt;/code&gt; template again.&lt;/p&gt;
&lt;h2&gt;The show template&lt;/h2&gt;
&lt;p&gt;This is based on a sample code from Facebook docs. You can find it
&lt;a href=&quot;https://developers.facebook.com/docs/instant-articles/example-articles#example-markup&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- app/views/show.html.erb --&gt;&lt;/span&gt;`
&lt;span class=&quot;token doctype&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;!&lt;/span&gt;&lt;span class=&quot;token doctype-tag&quot;&gt;doctype&lt;/span&gt; &lt;span class=&quot;token name&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;html&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;en&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;prefix&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;op: http://media.facebook.com/op#&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;head&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;My Blog | &amp;lt;%= article.title %&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;charset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;utf-8&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;canonical&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&amp;lt;%= article_url(article.id) %&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;op:markup_version&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;v1.0&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;head&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;article&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;header&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&amp;lt;%= article.title %&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&amp;lt;%= article.subtitle %&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;time&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;op-published&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;datetime&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&amp;lt;%= article.created_at.iso8601 %&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
          &amp;lt;%= article.created_at %&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;time&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;address&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
          &amp;lt;%= link_to article.author.name, article.author %&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;address&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;figure&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&amp;lt;%= article.cover_url %&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&amp;lt;%= article.cover_description %&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;figcaption&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&amp;lt;%= article.cover_description %&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;figcaption&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;figure&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h3&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;op-kicker&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&amp;lt;%= article.kicker %&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;header&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &amp;lt;%= article.body.html_safe %&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;footer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;aside&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&amp;lt;%= article.author.name %&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
          &amp;lt;%= article.author.bio.html_safe %&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;aside&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;footer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;article&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A few things to note here. First, make sure there is a link to the original
content in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;. Second, Facebook expects &lt;code&gt;&amp;lt;time&amp;gt;&lt;/code&gt; to have its
&lt;code&gt;datetime&lt;/code&gt; attribute in a specific format (ISO 8601).&lt;/p&gt;
&lt;p&gt;Again, to make things simple here, I used the &lt;code&gt;created_at&lt;/code&gt; time stamp for the
date, but you&#39;ll probably want to create a &lt;code&gt;published_at&lt;/code&gt; attribute instead,
and add another time stamp for &lt;code&gt;updated_at&lt;/code&gt;, so that Facebook knows when an
article is modified.&lt;/p&gt;
&lt;p&gt;Now let&#39;s wrap this all together and create our RSS feed.&lt;/p&gt;
&lt;h2&gt;The index template&lt;/h2&gt;
&lt;p&gt;This is what we want. The goal is to create the same XML structure as
&lt;a href=&quot;https://developers.facebook.com/docs/instant-articles/publishing/setup-rss-feed#sample-feed&quot;&gt;this&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# app/views/index.rss.builder&lt;/span&gt;
xml&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;rss version&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;2.0&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;xmlns:content&#39;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;http://purl.org/rss/1.0/modules/content&#39;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
  xml&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;channel &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
    xml&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;My Blog&#39;&lt;/span&gt;&lt;/span&gt;
    xml&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;link articles_url
    xml&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;description &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Instant Articles from my blog.&#39;&lt;/span&gt;&lt;/span&gt;
    xml&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;language &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;en-us&#39;&lt;/span&gt;&lt;/span&gt;

    &lt;span class=&quot;token variable&quot;&gt;@articles&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;article&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
      xml&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;item &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
        xml&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title article&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title
        xml&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;link article_url&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;article&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        xml&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;content &lt;span class=&quot;token symbol&quot;&gt;:encoded&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
          xml&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cdata&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt; render&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;instant_articles/show&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;locals&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;article&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; article &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;formats&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;:html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;layout&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
        xml&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;guid article_url&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;article&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        xml&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;pubDate article&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;created_at&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;iso8601
        xml&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;author article&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;author&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name
      &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The magic happens at line &lt;code&gt;13&lt;/code&gt;, where we render the &lt;code&gt;show&lt;/code&gt; template above.&lt;/p&gt;
&lt;p&gt;Watch out for the format of the time stamps, ISO 8601 again.&lt;/p&gt;
&lt;h2&gt;Takeaway&lt;/h2&gt;
&lt;p&gt;There are more things you could/should do to complete the integration, such as
&lt;a href=&quot;https://developers.facebook.com/docs/instant-articles/guides/articlecreate#rich-media&quot;&gt;creating rich media
elements&lt;/a&gt;,
&lt;a href=&quot;https://developers.facebook.com/docs/instant-articles/guides/articlecreate#feed-preview&quot;&gt;configuring a newsfeed
preview&lt;/a&gt;, or &lt;a href=&quot;https://developers.facebook.com/docs/instant-articles/design/creating-styles&quot;&gt;creating a style&lt;/a&gt;. I definitely recommend checking the documentation, it&#39;s pretty extensive and it has code samples.&lt;/p&gt;
&lt;p&gt;Using the RSS feed to import articles is not optimal if you want immediate
feedback on the import process. For that you could use the Instant Articles API.
But the RSS feed integrates nicely with the publishing tools, giving you a nice
and easy way to edit your Instant Articles on Facebook and scheduling them to be shared on
the page.&lt;/p&gt;
</content>
  </entry>
</feed>