<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ricardo Ruwer</title>
    <description>The latest articles on DEV Community by Ricardo Ruwer (@ricardoruwer).</description>
    <link>https://dev.to/ricardoruwer</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F196623%2F8cdec03a-c13e-46b6-b127-682cbc938bda.jpeg</url>
      <title>DEV Community: Ricardo Ruwer</title>
      <link>https://dev.to/ricardoruwer</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ricardoruwer"/>
    <language>en</language>
    <item>
      <title>Load specific JS files in Elixir and Phoenix</title>
      <dc:creator>Ricardo Ruwer</dc:creator>
      <pubDate>Mon, 29 Jul 2019 18:51:01 +0000</pubDate>
      <link>https://dev.to/ricardoruwer/load-specific-js-files-in-elixir-and-phoenix-o57</link>
      <guid>https://dev.to/ricardoruwer/load-specific-js-files-in-elixir-and-phoenix-o57</guid>
      <description>&lt;p&gt;First of all, I'd like to say that this post is based on that one:&lt;br&gt;
&lt;a href="http://codeloveandboards.com/blog/2016/04/26/page-specific-javascript-in-phoenix-framework-pt-2/"&gt;http://codeloveandboards.com/blog/2016/04/26/page-specific-javascript-in-phoenix-framework-pt-2/&lt;/a&gt;&lt;br&gt;
But I made some changes to (IMO) simplify it...&lt;/p&gt;

&lt;p&gt;So, let's start:&lt;/p&gt;

&lt;p&gt;First, we can add in our file &lt;code&gt;assets/js/app.js&lt;/code&gt; this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Import specific page views&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./views/init&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now we'll create this &lt;code&gt;init.js&lt;/code&gt; file in &lt;code&gt;assets/js/views/init.js&lt;/code&gt; and add this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;loadView&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./loader&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;handleDOMContentLoaded&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;viewName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsViewPath&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;loadView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;viewName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mount&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentView&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;handleDocumentUnload&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentView&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;unmount&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DOMContentLoaded&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleDOMContentLoaded&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;unload&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleDocumentUnload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now we'll create this &lt;code&gt;loader.js&lt;/code&gt; file mentioned on the &lt;code&gt;import&lt;/code&gt;, so create the file &lt;code&gt;assets/js/views/loader.js&lt;/code&gt; and add this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;MainView&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./main&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;loadView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;viewPath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;viewPath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;MainView&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ViewClass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;viewPath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ViewClass&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now this other file called &lt;code&gt;main.js&lt;/code&gt; in &lt;code&gt;assets/js/views/main.js&lt;/code&gt; with this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;MainView&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// It will be executed when the document loads...&lt;/span&gt;
  &lt;span class="nx"&gt;mount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// It will be executed when the document unloads...&lt;/span&gt;
  &lt;span class="nx"&gt;unmount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nice! :)&lt;br&gt;
Now in our controller, we can return a new value to the view, informing the directory of our js file, something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;conn
&lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; assign&lt;span class="p"&gt;(:&lt;/span&gt;js_view&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"posts/index"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; render&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"index.html"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now in our layout file, that may be in &lt;code&gt;templates/layout/app.html.eex&lt;/code&gt; we can add this code in our &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; tag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;body&lt;/span&gt; &lt;span class="na"&gt;data-js-view-path=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;%= assigns[:js_view] %&amp;gt;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it's ready! :)&lt;br&gt;
So, we'll only try to fetch the JS file is we set the &lt;code&gt;js_view&lt;/code&gt; on the controller.&lt;/p&gt;

&lt;p&gt;Now, to use it, you can create a file in &lt;code&gt;assets/js/views/posts/index.js&lt;/code&gt; and add code similar to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;MainView&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../main&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;View&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;MainView&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;mount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Add your JS code here...&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;UHULL! It works!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mount&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;unmount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;unmount&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✨&lt;/p&gt;

</description>
      <category>specific</category>
      <category>javascript</category>
      <category>elixir</category>
      <category>phoenix</category>
    </item>
    <item>
      <title>Create a paginator using Elixir and Phoenix</title>
      <dc:creator>Ricardo Ruwer</dc:creator>
      <pubDate>Sun, 21 Jul 2019 21:48:27 +0000</pubDate>
      <link>https://dev.to/ricardoruwer/create-a-paginator-using-elixir-and-phoenix-1hnk</link>
      <guid>https://dev.to/ricardoruwer/create-a-paginator-using-elixir-and-phoenix-1hnk</guid>
      <description>&lt;p&gt;I'm writing this for the same reason I wrote about creating a sitemap.xml, I could find only solutions using libs, but it's simple, we don't need a lib to do this. So I made this solution and I hope it helps you.&lt;/p&gt;

&lt;p&gt;First, we can create a new file like &lt;code&gt;lib/myapp/paginator.ex&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;defmodule MyApp&lt;span class="p"&gt;.&lt;/span&gt;Paginator &lt;span class="k"&gt;do&lt;/span&gt;
  @moduledoc &lt;span class="s2"&gt;""&lt;/span&gt;"
  Paginate your Ecto queries&lt;span class="p"&gt;.&lt;/span&gt;

  Instead of using&lt;span class="p"&gt;:&lt;/span&gt; `Repo&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;query&lt;span class="p"&gt;)&lt;/span&gt;`&lt;span class="p"&gt;,&lt;/span&gt; you can use&lt;span class="p"&gt;:&lt;/span&gt; `Paginator&lt;span class="p"&gt;.&lt;/span&gt;page&lt;span class="p"&gt;(&lt;/span&gt;query&lt;span class="p"&gt;)&lt;/span&gt;`&lt;span class="p"&gt;.&lt;/span&gt;
  To &lt;span class="k"&gt;change&lt;/span&gt; the page you can pass the page &lt;span class="k"&gt;number&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; the second &lt;span class="k"&gt;argument&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

  ## Examples

      iex&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; Paginator&lt;span class="p"&gt;.&lt;/span&gt;paginate&lt;span class="p"&gt;(&lt;/span&gt;query&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;%Item&lt;span class="p"&gt;{&lt;/span&gt;id&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; %Item&lt;span class="p"&gt;{&lt;/span&gt;id&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; %Item&lt;span class="p"&gt;{&lt;/span&gt;id&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; %Item&lt;span class="p"&gt;{&lt;/span&gt;id&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; %Item&lt;span class="p"&gt;{&lt;/span&gt;id&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;

      iex&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; Paginator&lt;span class="p"&gt;.&lt;/span&gt;paginate&lt;span class="p"&gt;(&lt;/span&gt;query&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;%Item&lt;span class="p"&gt;{&lt;/span&gt;id&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;6&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; %Item&lt;span class="p"&gt;{&lt;/span&gt;id&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;7&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; %Item&lt;span class="p"&gt;{&lt;/span&gt;id&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; %Item&lt;span class="p"&gt;{&lt;/span&gt;id&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;9&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; %Item&lt;span class="p"&gt;{&lt;/span&gt;id&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;

  &lt;span class="c"&gt;"""&lt;/span&gt;

  &lt;span class="k"&gt;import&lt;/span&gt; Ecto&lt;span class="p"&gt;.&lt;/span&gt;Query

  alias MyApp&lt;span class="p"&gt;.&lt;/span&gt;Repo

  @results_per_page &lt;span class="m"&gt;12&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; paginate&lt;span class="p"&gt;(&lt;/span&gt;query&lt;span class="p"&gt;,&lt;/span&gt; page&lt;span class="p"&gt;)&lt;/span&gt; when is_nil&lt;span class="p"&gt;(&lt;/span&gt;page&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    paginate&lt;span class="p"&gt;(&lt;/span&gt;query&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  end

  &lt;span class="k"&gt;def&lt;/span&gt; paginate&lt;span class="p"&gt;(&lt;/span&gt;query&lt;span class="p"&gt;,&lt;/span&gt; page&lt;span class="p"&gt;)&lt;/span&gt; when is_binary&lt;span class="p"&gt;(&lt;/span&gt;page&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    paginate&lt;span class="p"&gt;(&lt;/span&gt;query&lt;span class="p"&gt;,&lt;/span&gt; String&lt;span class="p"&gt;.&lt;/span&gt;to_integer&lt;span class="p"&gt;(&lt;/span&gt;page&lt;span class="p"&gt;))&lt;/span&gt;
  end

  &lt;span class="k"&gt;def&lt;/span&gt; paginate&lt;span class="p"&gt;(&lt;/span&gt;query&lt;span class="p"&gt;,&lt;/span&gt; page&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    results &lt;span class="p"&gt;=&lt;/span&gt; execute_query&lt;span class="p"&gt;(&lt;/span&gt;query&lt;span class="p"&gt;,&lt;/span&gt; page&lt;span class="p"&gt;)&lt;/span&gt;
    total_results &lt;span class="p"&gt;=&lt;/span&gt; count_total_results&lt;span class="p"&gt;(&lt;/span&gt;query&lt;span class="p"&gt;)&lt;/span&gt;
    total_pages &lt;span class="p"&gt;=&lt;/span&gt; count_total_pages&lt;span class="p"&gt;(&lt;/span&gt;total_results&lt;span class="p"&gt;)&lt;/span&gt;

    %&lt;span class="p"&gt;{&lt;/span&gt;
      current_page&lt;span class="p"&gt;:&lt;/span&gt; page&lt;span class="p"&gt;,&lt;/span&gt;
      results_per_page&lt;span class="p"&gt;:&lt;/span&gt; @results_per_page&lt;span class="p"&gt;,&lt;/span&gt;
      total_pages&lt;span class="p"&gt;:&lt;/span&gt; total_pages&lt;span class="p"&gt;,&lt;/span&gt;
      total_results&lt;span class="p"&gt;:&lt;/span&gt; total_results&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="k"&gt;list&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; results
    &lt;span class="p"&gt;}&lt;/span&gt;
  end

  defp execute_query&lt;span class="p"&gt;(&lt;/span&gt;query&lt;span class="p"&gt;,&lt;/span&gt; page&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    query
    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; limit&lt;span class="p"&gt;(&lt;/span&gt;^@results_per_page&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; offset&lt;span class="p"&gt;((&lt;/span&gt;^page &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; * ^@results_per_page&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; Repo&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  end

  defp count_total_results&lt;span class="p"&gt;(&lt;/span&gt;query&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    Repo&lt;span class="p"&gt;.&lt;/span&gt;aggregate&lt;span class="p"&gt;(&lt;/span&gt;query&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;id&lt;span class="p"&gt;)&lt;/span&gt;
  end

  defp count_total_pages&lt;span class="p"&gt;(&lt;/span&gt;total_results&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    total_pages &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;ceil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;total_results / @results_per_page&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; total_pages &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; total_pages&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we'll create the logic to be used in the front-end. So we can create a file like &lt;code&gt;lib/myapp_web/helpers/paginator_helper.ex&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;defmodule MyAppWeb&lt;span class="p"&gt;.&lt;/span&gt;Helpers&lt;span class="p"&gt;.&lt;/span&gt;PaginatorHelper &lt;span class="k"&gt;do&lt;/span&gt;
  @moduledoc &lt;span class="s2"&gt;""&lt;/span&gt;"
  Renders the pagination with &lt;span class="k"&gt;a&lt;/span&gt; &lt;span class="k"&gt;previous&lt;/span&gt; button&lt;span class="p"&gt;,&lt;/span&gt; the pages&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;and&lt;/span&gt; the &lt;span class="k"&gt;next&lt;/span&gt; button&lt;span class="p"&gt;.&lt;/span&gt;
  &lt;span class="c"&gt;"""&lt;/span&gt;

  use Phoenix&lt;span class="p"&gt;.&lt;/span&gt;HTML

  &lt;span class="k"&gt;def&lt;/span&gt; render&lt;span class="p"&gt;(&lt;/span&gt;conn&lt;span class="p"&gt;,&lt;/span&gt; data&lt;span class="p"&gt;,&lt;/span&gt; class&lt;span class="p"&gt;:&lt;/span&gt; class&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="k"&gt;first&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; prev_button&lt;span class="p"&gt;(&lt;/span&gt;conn&lt;span class="p"&gt;,&lt;/span&gt; data&lt;span class="p"&gt;)&lt;/span&gt;
    pages &lt;span class="p"&gt;=&lt;/span&gt; page_buttons&lt;span class="p"&gt;(&lt;/span&gt;conn&lt;span class="p"&gt;,&lt;/span&gt; data&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;last&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; next_button&lt;span class="p"&gt;(&lt;/span&gt;conn&lt;span class="p"&gt;,&lt;/span&gt; data&lt;span class="p"&gt;)&lt;/span&gt;

    content_tag&lt;span class="p"&gt;(:&lt;/span&gt;&lt;span class="nb"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;first&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; pages&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;last&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; class&lt;span class="p"&gt;:&lt;/span&gt; class&lt;span class="p"&gt;)&lt;/span&gt;
  end

  defp prev_button&lt;span class="p"&gt;(&lt;/span&gt;conn&lt;span class="p"&gt;,&lt;/span&gt; data&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    page &lt;span class="p"&gt;=&lt;/span&gt; data&lt;span class="p"&gt;.&lt;/span&gt;current_page &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
    disabled &lt;span class="p"&gt;=&lt;/span&gt; data&lt;span class="p"&gt;.&lt;/span&gt;current_page &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
    params &lt;span class="p"&gt;=&lt;/span&gt; build_params&lt;span class="p"&gt;(&lt;/span&gt;conn&lt;span class="p"&gt;,&lt;/span&gt; page&lt;span class="p"&gt;)&lt;/span&gt;

    content_tag&lt;span class="p"&gt;(:&lt;/span&gt;li&lt;span class="p"&gt;,&lt;/span&gt; disabled&lt;span class="p"&gt;:&lt;/span&gt; disabled&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      link &lt;span class="k"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"?#{params}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; rel&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"prev"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="c"&gt;"&amp;lt;"&lt;/span&gt;
      end
    end
  end

  defp page_buttons&lt;span class="p"&gt;(&lt;/span&gt;conn&lt;span class="p"&gt;,&lt;/span&gt; data&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; page &lt;span class="p"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt;data&lt;span class="p"&gt;.&lt;/span&gt;total_pages &lt;span class="k"&gt;do&lt;/span&gt;
      class &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; data&lt;span class="p"&gt;.&lt;/span&gt;current_page &lt;span class="p"&gt;==&lt;/span&gt; page&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"active"&lt;/span&gt;
      disabled &lt;span class="p"&gt;=&lt;/span&gt; data&lt;span class="p"&gt;.&lt;/span&gt;current_page &lt;span class="p"&gt;==&lt;/span&gt; page
      params &lt;span class="p"&gt;=&lt;/span&gt; build_params&lt;span class="p"&gt;(&lt;/span&gt;conn&lt;span class="p"&gt;,&lt;/span&gt; page&lt;span class="p"&gt;)&lt;/span&gt;

      content_tag&lt;span class="p"&gt;(:&lt;/span&gt;li&lt;span class="p"&gt;,&lt;/span&gt; class&lt;span class="p"&gt;:&lt;/span&gt; class&lt;span class="p"&gt;,&lt;/span&gt; disabled&lt;span class="p"&gt;:&lt;/span&gt; disabled&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        link&lt;span class="p"&gt;(&lt;/span&gt;page&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"?#{params}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      end
    end
  end

  defp next_button&lt;span class="p"&gt;(&lt;/span&gt;conn&lt;span class="p"&gt;,&lt;/span&gt; data&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    page &lt;span class="p"&gt;=&lt;/span&gt; data&lt;span class="p"&gt;.&lt;/span&gt;current_page &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
    disabled &lt;span class="p"&gt;=&lt;/span&gt; data&lt;span class="p"&gt;.&lt;/span&gt;current_page &lt;span class="p"&gt;&amp;gt;=&lt;/span&gt; data&lt;span class="p"&gt;.&lt;/span&gt;total_pages
    params &lt;span class="p"&gt;=&lt;/span&gt; build_params&lt;span class="p"&gt;(&lt;/span&gt;conn&lt;span class="p"&gt;,&lt;/span&gt; page&lt;span class="p"&gt;)&lt;/span&gt;

    content_tag&lt;span class="p"&gt;(:&lt;/span&gt;li&lt;span class="p"&gt;,&lt;/span&gt; disabled&lt;span class="p"&gt;:&lt;/span&gt; disabled&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      link &lt;span class="k"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"?#{params}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; rel&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"next"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="c"&gt;"&amp;gt;"&lt;/span&gt;
      end
    end
  end

  defp build_params&lt;span class="p"&gt;(&lt;/span&gt;conn&lt;span class="p"&gt;,&lt;/span&gt; page&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    conn&lt;span class="p"&gt;.&lt;/span&gt;query_params &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; Map&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(:&lt;/span&gt;page&lt;span class="p"&gt;,&lt;/span&gt; page&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; URI&lt;span class="p"&gt;.&lt;/span&gt;encode_query&lt;span class="p"&gt;()&lt;/span&gt;
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it's basically all we need.&lt;/p&gt;

&lt;p&gt;When the page isn't available, it will be &lt;code&gt;disabled&lt;/code&gt;. I also added some CSS like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.paginator-list&lt;/span&gt; &lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;disabled&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;.4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;pointer-events&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So now let's suppose we have a method to list all the posts in a blog, it'll be something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;alias MyApp&lt;span class="p"&gt;.&lt;/span&gt;Paginator

&lt;span class="k"&gt;def&lt;/span&gt; list_paged_posts&lt;span class="p"&gt;(&lt;/span&gt;params&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  Paginator&lt;span class="p"&gt;.&lt;/span&gt;paginate&lt;span class="p"&gt;(&lt;/span&gt;Post&lt;span class="p"&gt;,&lt;/span&gt; params&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"page"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And in our Controller you can use this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nb"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;conn&lt;span class="p"&gt;,&lt;/span&gt; params&lt;span class="p"&gt;)&lt;/span&gt;
  posts &lt;span class="p"&gt;=&lt;/span&gt; Post&lt;span class="p"&gt;.&lt;/span&gt;list_paged_posts&lt;span class="p"&gt;(&lt;/span&gt;params&lt;span class="p"&gt;)&lt;/span&gt;

  render&lt;span class="p"&gt;(&lt;/span&gt;conn&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"index.html"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; posts&lt;span class="p"&gt;:&lt;/span&gt; posts&lt;span class="p"&gt;)&lt;/span&gt;
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And in our HTML you can use this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;%&lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; post &lt;span class="p"&gt;&amp;lt;-&lt;/span&gt; @posts&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;list&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; %&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;%&lt;span class="p"&gt;=&lt;/span&gt; post&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;title&lt;/span&gt; %&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;% end %&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;%&lt;span class="p"&gt;=&lt;/span&gt; MyApp&lt;span class="p"&gt;.&lt;/span&gt;Helpers&lt;span class="p"&gt;.&lt;/span&gt;PaginatorHelper&lt;span class="p"&gt;.&lt;/span&gt;render&lt;span class="p"&gt;(&lt;/span&gt;@conn&lt;span class="p"&gt;,&lt;/span&gt; @posts&lt;span class="p"&gt;,&lt;/span&gt; class&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"paginator-list"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; %&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's all :)&lt;/p&gt;

&lt;p&gt;But don't forget the tests! So, we can create the file &lt;code&gt;test/myapp/paginator_test.exs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;defmodule MyApp&lt;span class="p"&gt;.&lt;/span&gt;PaginatorTest &lt;span class="k"&gt;do&lt;/span&gt;
  use MyApp&lt;span class="p"&gt;.&lt;/span&gt;DataCase

  alias MyApp&lt;span class="p"&gt;.&lt;/span&gt;Post
  alias MyApp&lt;span class="p"&gt;.&lt;/span&gt;Paginator

  describe &lt;span class="s2"&gt;"when the page is nil"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    test &lt;span class="s2"&gt;"sets the page to the first page"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      create_posts&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      paginator &lt;span class="p"&gt;=&lt;/span&gt; Paginator&lt;span class="p"&gt;.&lt;/span&gt;paginate&lt;span class="p"&gt;(&lt;/span&gt;Post&lt;span class="p"&gt;,&lt;/span&gt; nil&lt;span class="p"&gt;)&lt;/span&gt;

      assert paginator&lt;span class="p"&gt;.&lt;/span&gt;current_page &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
    end
  end

  describe &lt;span class="s2"&gt;"when the page is a string"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    test &lt;span class="s2"&gt;"sets the page to an integer"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      create_posts&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      paginator &lt;span class="p"&gt;=&lt;/span&gt; Paginator&lt;span class="p"&gt;.&lt;/span&gt;paginate&lt;span class="p"&gt;(&lt;/span&gt;Post&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      assert paginator&lt;span class="p"&gt;.&lt;/span&gt;current_page &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
    end
  end

  test &lt;span class="s2"&gt;"paginate as 12 results per page"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    create_posts&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;15&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    paginator_first_page &lt;span class="p"&gt;=&lt;/span&gt; Paginator&lt;span class="p"&gt;.&lt;/span&gt;paginate&lt;span class="p"&gt;(&lt;/span&gt;Post&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    assert length&lt;span class="p"&gt;(&lt;/span&gt;paginator_first_page&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="m"&gt;12&lt;/span&gt;

    paginator_second_page &lt;span class="p"&gt;=&lt;/span&gt; Paginator&lt;span class="p"&gt;.&lt;/span&gt;paginate&lt;span class="p"&gt;(&lt;/span&gt;Post&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    assert length&lt;span class="p"&gt;(&lt;/span&gt;paginator_second_page&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
  end

  test &lt;span class="s2"&gt;"prints pagination info"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    posts &lt;span class="p"&gt;=&lt;/span&gt; create_posts&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    paginator &lt;span class="p"&gt;=&lt;/span&gt; Paginator&lt;span class="p"&gt;.&lt;/span&gt;paginate&lt;span class="p"&gt;(&lt;/span&gt;Post&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    assert paginator&lt;span class="p"&gt;.&lt;/span&gt;current_page &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
    assert paginator&lt;span class="p"&gt;.&lt;/span&gt;results_per_page &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="m"&gt;12&lt;/span&gt;
    assert paginator&lt;span class="p"&gt;.&lt;/span&gt;total_pages &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
    assert paginator&lt;span class="p"&gt;.&lt;/span&gt;total_results &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;

    Enum&lt;span class="p"&gt;.&lt;/span&gt;each&lt;span class="p"&gt;(&lt;/span&gt;posts&lt;span class="p"&gt;,&lt;/span&gt; fn post &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
      assert post &lt;span class="k"&gt;in&lt;/span&gt; paginator&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;list&lt;/span&gt;
    end&lt;span class="p"&gt;)&lt;/span&gt;
  end

  defp create_posts&lt;span class="p"&gt;(&lt;/span&gt;quantity&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;n&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt;quantity &lt;span class="k"&gt;do&lt;/span&gt;
      # Here you create &lt;span class="k"&gt;a&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; Post&lt;span class="p"&gt;!&lt;/span&gt;
      post_fixture&lt;span class="p"&gt;()&lt;/span&gt;
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And also the test file for the paginator_helper in &lt;code&gt;test/myapp_web/helpers/paginator_helper_test.exs&lt;/code&gt; with something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;defmodule MyAppWeb&lt;span class="p"&gt;.&lt;/span&gt;Helpers&lt;span class="p"&gt;.&lt;/span&gt;PaginatorHelperTest &lt;span class="k"&gt;do&lt;/span&gt;
  use MyAppWeb&lt;span class="p"&gt;.&lt;/span&gt;ConnCase

  &lt;span class="k"&gt;import&lt;/span&gt; Phoenix&lt;span class="p"&gt;.&lt;/span&gt;HTML&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;only&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;safe_to_string&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

  alias MyApp&lt;span class="p"&gt;.&lt;/span&gt;Post
  alias MyAppWeb&lt;span class="p"&gt;.&lt;/span&gt;Helpers&lt;span class="p"&gt;.&lt;/span&gt;PaginatorHelper

  describe &lt;span class="s2"&gt;"render/3"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    test &lt;span class="s2"&gt;"renders the paginator"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      conn &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;build_conn&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s2"&gt;"/?q=paginator+elixir"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      paginated_results &lt;span class="p"&gt;=&lt;/span&gt; Posts&lt;span class="p"&gt;.&lt;/span&gt;list_paged_posts&lt;span class="p"&gt;(&lt;/span&gt;%&lt;span class="p"&gt;{&lt;/span&gt;page&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

      paginator &lt;span class="p"&gt;=&lt;/span&gt;
        conn
        &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; PaginatorHelper&lt;span class="p"&gt;.&lt;/span&gt;render&lt;span class="p"&gt;(&lt;/span&gt;paginated_results&lt;span class="p"&gt;,&lt;/span&gt; class&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"paginator"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; safe_to_string&lt;span class="p"&gt;()&lt;/span&gt;

      assert paginator &lt;span class="p"&gt;==&lt;/span&gt;
               &lt;span class="c"&gt;"&amp;lt;ul class=\"paginator\"&amp;gt;" &amp;lt;&amp;gt;&lt;/span&gt;
                 &lt;span class="c"&gt;"&amp;lt;li disabled&amp;gt;" &amp;lt;&amp;gt;&lt;/span&gt;
                 &lt;span class="c"&gt;"&amp;lt;a href=\"?page=0&amp;amp;amp;q=paginator+elixir\" rel=\"prev\"&amp;gt;&amp;lt;&amp;lt;/a&amp;gt;" &amp;lt;&amp;gt;&lt;/span&gt;
                 &lt;span class="c"&gt;"&amp;lt;/li&amp;gt;" &amp;lt;&amp;gt;&lt;/span&gt;
                 &lt;span class="c"&gt;"&amp;lt;li class=\"active\" disabled&amp;gt;" &amp;lt;&amp;gt;&lt;/span&gt;
                 &lt;span class="c"&gt;"&amp;lt;a href=\"?page=1&amp;amp;amp;q=paginator+elixir\"&amp;gt;1&amp;lt;/a&amp;gt;" &amp;lt;&amp;gt;&lt;/span&gt;
                 &lt;span class="c"&gt;"&amp;lt;/li&amp;gt;" &amp;lt;&amp;gt;&lt;/span&gt;
                 &lt;span class="c"&gt;"&amp;lt;li disabled&amp;gt;" &amp;lt;&amp;gt;&lt;/span&gt;
                 &lt;span class="c"&gt;"&amp;lt;a href=\"?page=2&amp;amp;amp;q=paginator+elixir\" rel=\"next\"&amp;gt;&amp;gt;&amp;lt;/a&amp;gt;" &amp;lt;&amp;gt;&lt;/span&gt;
                 &lt;span class="c"&gt;"&amp;lt;/li&amp;gt;" &amp;lt;&amp;gt;&lt;/span&gt;
                 &lt;span class="c"&gt;"&amp;lt;/ul&amp;gt;"&lt;/span&gt;
    end
  end
end

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it. Hope it helps you :)&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>phoenix</category>
      <category>paginator</category>
    </item>
    <item>
      <title>Many to many associations in Elixir and Phoenix</title>
      <dc:creator>Ricardo Ruwer</dc:creator>
      <pubDate>Thu, 18 Jul 2019 13:01:46 +0000</pubDate>
      <link>https://dev.to/ricardoruwer/many-to-many-associations-in-elixir-and-phoenix-21pm</link>
      <guid>https://dev.to/ricardoruwer/many-to-many-associations-in-elixir-and-phoenix-21pm</guid>
      <description>&lt;p&gt;I was creating the website of a construction company, so I had 2 schemas: &lt;code&gt;properties&lt;/code&gt; and &lt;code&gt;amenities&lt;/code&gt;. One property can have many amenities (like pool, barbecue grill, playground, etc), one amenity can belong to many properties.&lt;/p&gt;

&lt;p&gt;Another popular example similar to this one is &lt;code&gt;posts&lt;/code&gt; and &lt;code&gt;tags&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So my idea was: I can create a lot of amenities, and in the property form I list these amenities in checkboxes to the user check which one the property has.&lt;/p&gt;

&lt;p&gt;I had some bad times trying to do that, so that's why I created this post, so I may help someone...&lt;/p&gt;

&lt;p&gt;OK, so I created this schema called &lt;code&gt;properties_amenities&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;defmodule MyApp&lt;span class="p"&gt;.&lt;/span&gt;PropertiesAmenities &lt;span class="k"&gt;do&lt;/span&gt;
  use Ecto&lt;span class="p"&gt;.&lt;/span&gt;Schema

  &lt;span class="k"&gt;import&lt;/span&gt; Ecto&lt;span class="p"&gt;.&lt;/span&gt;Changeset

  @primary_key false
  schema &lt;span class="s2"&gt;"properties_amenities"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    belongs_to &lt;span class="p"&gt;:&lt;/span&gt;property&lt;span class="p"&gt;,&lt;/span&gt; MyApp&lt;span class="p"&gt;.&lt;/span&gt;Properties&lt;span class="p"&gt;.&lt;/span&gt;Property
    belongs_to &lt;span class="p"&gt;:&lt;/span&gt;amenity&lt;span class="p"&gt;,&lt;/span&gt; MyApp&lt;span class="p"&gt;.&lt;/span&gt;Amenities&lt;span class="p"&gt;.&lt;/span&gt;Amenity
  end

  &lt;span class="k"&gt;def&lt;/span&gt; changeset&lt;span class="p"&gt;(&lt;/span&gt;struct&lt;span class="p"&gt;,&lt;/span&gt; params \\ %&lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    struct
    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; cast&lt;span class="p"&gt;(&lt;/span&gt;params&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[:&lt;/span&gt;property_id&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;amenity_id&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; validate_required&lt;span class="p"&gt;([:&lt;/span&gt;property_id&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;amenity_id&lt;span class="p"&gt;])&lt;/span&gt;
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then I added it to the &lt;code&gt;properties&lt;/code&gt; schema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;schema &lt;span class="s2"&gt;"properties"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  # &lt;span class="p"&gt;...&lt;/span&gt;

  many_to_many&lt;span class="p"&gt;(:&lt;/span&gt;amenities&lt;span class="p"&gt;,&lt;/span&gt; MyApp&lt;span class="p"&gt;.&lt;/span&gt;Amenities&lt;span class="p"&gt;.&lt;/span&gt;Amenity&lt;span class="p"&gt;,&lt;/span&gt; join_through&lt;span class="p"&gt;:&lt;/span&gt; MyApp&lt;span class="p"&gt;.&lt;/span&gt;PropertiesAmenities&lt;span class="p"&gt;)&lt;/span&gt;

  # &lt;span class="p"&gt;...&lt;/span&gt;
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the &lt;code&gt;amenities&lt;/code&gt; schema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;schema &lt;span class="s2"&gt;"amenities"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  # &lt;span class="p"&gt;...&lt;/span&gt;

  many_to_many&lt;span class="p"&gt;(:&lt;/span&gt;properties&lt;span class="p"&gt;,&lt;/span&gt; MyApp&lt;span class="p"&gt;.&lt;/span&gt;Properties&lt;span class="p"&gt;.&lt;/span&gt;Property&lt;span class="p"&gt;,&lt;/span&gt; join_through&lt;span class="p"&gt;:&lt;/span&gt; MyApp&lt;span class="p"&gt;.&lt;/span&gt;PropertiesAmenities&lt;span class="p"&gt;)&lt;/span&gt;

  # &lt;span class="p"&gt;...&lt;/span&gt;
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OK, now I created a helper to list all the amenities on the property form, so in the file &lt;code&gt;lib/myapp_web/helpers/checkbox_helper.ex&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;defmodule ConstrutoraLcHiertWeb&lt;span class="p"&gt;.&lt;/span&gt;Helpers&lt;span class="p"&gt;.&lt;/span&gt;CheckboxHelper &lt;span class="k"&gt;do&lt;/span&gt;
  use Phoenix&lt;span class="p"&gt;.&lt;/span&gt;HTML

  @doc &lt;span class="s2"&gt;""&lt;/span&gt;"
  Renders multiple checkboxes&lt;span class="p"&gt;.&lt;/span&gt;

  ## Example

      iex&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; multiselect_checkboxes&lt;span class="p"&gt;(&lt;/span&gt;
             &lt;span class="k"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
             &lt;span class="p"&gt;:&lt;/span&gt;amenities&lt;span class="p"&gt;,&lt;/span&gt;
             Enum&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;@amenities&lt;span class="p"&gt;,&lt;/span&gt; fn &lt;span class="k"&gt;c&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;name&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;id &lt;span class="p"&gt;}&lt;/span&gt; end&lt;span class="p"&gt;),&lt;/span&gt;
             selected&lt;span class="p"&gt;:&lt;/span&gt; Enum&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;@changeset&lt;span class="p"&gt;.&lt;/span&gt;data&lt;span class="p"&gt;.&lt;/span&gt;amenities&lt;span class="p"&gt;,&lt;/span&gt;&amp;amp;&lt;span class="p"&gt;(&lt;/span&gt;&amp;amp;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;id&lt;span class="p"&gt;))&lt;/span&gt;
           &lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;div class&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"checkbox"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;label&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;input&lt;/span&gt; name&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"property[amenities][]"&lt;/span&gt; id&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"property_amenities_1"&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"checkbox"&lt;/span&gt; value&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"1"&lt;/span&gt; checked&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;input&lt;/span&gt; name&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"property[amenities][]"&lt;/span&gt; id&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"property_amenities_2"&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"checkbox"&lt;/span&gt; value&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"2"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;/label&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;/div
  &lt;span class="c"&gt;"""&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; multiselect_checkboxes&lt;span class="p"&gt;(&lt;/span&gt;form&lt;span class="p"&gt;,&lt;/span&gt; field&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; opts \\ &lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;selected&lt;span class="p"&gt;,&lt;/span&gt; _&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; get_selected_values&lt;span class="p"&gt;(&lt;/span&gt;form&lt;span class="p"&gt;,&lt;/span&gt; field&lt;span class="p"&gt;,&lt;/span&gt; opts&lt;span class="p"&gt;)&lt;/span&gt;
    selected_as_strings &lt;span class="p"&gt;=&lt;/span&gt; Enum&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;selected&lt;span class="p"&gt;,&lt;/span&gt; &amp;amp;&lt;span class="s2"&gt;"#{&amp;amp;1}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;value&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;key&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="k"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; into&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      content_tag&lt;span class="p"&gt;(:&lt;/span&gt;label&lt;span class="p"&gt;,&lt;/span&gt; class&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"checkbox-inline"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="k"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;(:&lt;/span&gt;&lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            name&lt;span class="p"&gt;:&lt;/span&gt; input_name&lt;span class="p"&gt;(&lt;/span&gt;form&lt;span class="p"&gt;,&lt;/span&gt; field&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"[]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            id&lt;span class="p"&gt;:&lt;/span&gt; input_id&lt;span class="p"&gt;(&lt;/span&gt;form&lt;span class="p"&gt;,&lt;/span&gt; field&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;key&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"checkbox"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            value&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            checked&lt;span class="p"&gt;:&lt;/span&gt; Enum&lt;span class="p"&gt;.&lt;/span&gt;member?&lt;span class="p"&gt;(&lt;/span&gt;selected_as_strings&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"#{key}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="p"&gt;),&lt;/span&gt;
          value
        &lt;span class="p"&gt;]&lt;/span&gt;
      end
    end
  end

  defp get_selected_values&lt;span class="p"&gt;(&lt;/span&gt;form&lt;span class="p"&gt;,&lt;/span&gt; field&lt;span class="p"&gt;,&lt;/span&gt; opts&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;selected&lt;span class="p"&gt;,&lt;/span&gt; opts&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; Keyword&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;opts&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;selected&lt;span class="p"&gt;)&lt;/span&gt;
    param &lt;span class="p"&gt;=&lt;/span&gt; field_to_string&lt;span class="p"&gt;(&lt;/span&gt;field&lt;span class="p"&gt;)&lt;/span&gt;

    case form &lt;span class="k"&gt;do&lt;/span&gt;
      %&lt;span class="p"&gt;{&lt;/span&gt;params&lt;span class="p"&gt;:&lt;/span&gt; %&lt;span class="p"&gt;{&lt;/span&gt;^param &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; sent&lt;span class="p"&gt;}}&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;sent&lt;span class="p"&gt;,&lt;/span&gt; opts&lt;span class="p"&gt;}&lt;/span&gt;

      _ &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;selected &lt;span class="p"&gt;||&lt;/span&gt; input_value&lt;span class="p"&gt;(&lt;/span&gt;form&lt;span class="p"&gt;,&lt;/span&gt; field&lt;span class="p"&gt;),&lt;/span&gt; opts&lt;span class="p"&gt;}&lt;/span&gt;
    end
  end

  defp field_to_string&lt;span class="p"&gt;(&lt;/span&gt;field&lt;span class="p"&gt;)&lt;/span&gt; when is_atom&lt;span class="p"&gt;(&lt;/span&gt;field&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; Atom&lt;span class="p"&gt;.&lt;/span&gt;to_string&lt;span class="p"&gt;(&lt;/span&gt;field&lt;span class="p"&gt;)&lt;/span&gt;
  defp field_to_string&lt;span class="p"&gt;(&lt;/span&gt;field&lt;span class="p"&gt;)&lt;/span&gt; when is_binary&lt;span class="p"&gt;(&lt;/span&gt;field&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; field
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And added it to &lt;code&gt;lib/myapp_web.ex&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="k"&gt;view&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  quote &lt;span class="k"&gt;do&lt;/span&gt;
    # &lt;span class="p"&gt;...&lt;/span&gt;

    &lt;span class="k"&gt;import&lt;/span&gt; MyAppWeb&lt;span class="p"&gt;.&lt;/span&gt;Helpers&lt;span class="p"&gt;.&lt;/span&gt;CheckboxHelper

    # &lt;span class="p"&gt;...&lt;/span&gt;
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I returned the &lt;code&gt;amenities&lt;/code&gt; to the form of properties, so, in the &lt;code&gt;properties_controller#new&lt;/code&gt; I added:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;conn&lt;span class="p"&gt;,&lt;/span&gt; _params&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  # &lt;span class="p"&gt;...&lt;/span&gt;

  amenities &lt;span class="p"&gt;=&lt;/span&gt; Amenities&lt;span class="p"&gt;.&lt;/span&gt;list_amenities&lt;span class="p"&gt;()&lt;/span&gt;

  render&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"new.html"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; changeset&lt;span class="p"&gt;:&lt;/span&gt; changeset&lt;span class="p"&gt;,&lt;/span&gt; amenities&lt;span class="p"&gt;:&lt;/span&gt; amenities&lt;span class="p"&gt;)&lt;/span&gt;
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And used the new function to render multi-select checkboxes in the &lt;code&gt;new.html.eex&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"form-group"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt;
    &lt;span class="na"&gt;multiselect_checkboxes&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;
      &lt;span class="na"&gt;f&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;:amenities&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;Enum.map&lt;/span&gt;&lt;span class="err"&gt;(@&lt;/span&gt;&lt;span class="na"&gt;amenities&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="na"&gt;fn&lt;/span&gt; &lt;span class="na"&gt;a&lt;/span&gt; &lt;span class="na"&gt;-&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; { a.name, a.id } end),
      selected: Enum.map(@changeset.data.amenities,&lt;span class="err"&gt;&amp;amp;&lt;/span&gt;(&lt;span class="err"&gt;&amp;amp;&lt;/span&gt;1.id))
    )
  %&amp;gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the view is rendering the checkboxes :)&lt;/p&gt;

&lt;p&gt;OK, now we have to create a new function to create the association between properties and amenities, to do this, I created this function in the file containing all the function related to properties:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;defp maybe_put_amenities&lt;span class="p"&gt;(&lt;/span&gt;changeset&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; changeset

defp maybe_put_amenities&lt;span class="p"&gt;(&lt;/span&gt;changeset&lt;span class="p"&gt;,&lt;/span&gt; attrs&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  amenities &lt;span class="p"&gt;=&lt;/span&gt; Amenities&lt;span class="p"&gt;.&lt;/span&gt;get_amenities&lt;span class="p"&gt;(&lt;/span&gt;attrs&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"amenities"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

  Ecto&lt;span class="p"&gt;.&lt;/span&gt;Changeset&lt;span class="p"&gt;.&lt;/span&gt;put_assoc&lt;span class="p"&gt;(&lt;/span&gt;changeset&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;amenities&lt;span class="p"&gt;,&lt;/span&gt; amenities&lt;span class="p"&gt;)&lt;/span&gt;
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And this function in the file related to amenities:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; get_amenities&lt;span class="p"&gt;(&lt;/span&gt;nil&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; get_amenities&lt;span class="p"&gt;(&lt;/span&gt;ids&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  Repo&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;from &lt;span class="k"&gt;a&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; MyApp&lt;span class="p"&gt;.&lt;/span&gt;Amenities&lt;span class="p"&gt;.&lt;/span&gt;Amenity&lt;span class="p"&gt;,&lt;/span&gt; where&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;id &lt;span class="k"&gt;in&lt;/span&gt; ^ids&lt;span class="p"&gt;)&lt;/span&gt;
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And added this new method &lt;code&gt;maybe_put_amenities&lt;/code&gt; in the function that creates a new property, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; create_property&lt;span class="p"&gt;(&lt;/span&gt;attrs&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  %Property&lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; Property&lt;span class="p"&gt;.&lt;/span&gt;changeset&lt;span class="p"&gt;(&lt;/span&gt;attrs&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; maybe_put_amenities&lt;span class="p"&gt;(&lt;/span&gt;attrs&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; Repo&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So now, when the access the &lt;code&gt;properties/new&lt;/code&gt; page, it will render the form and all the amenities. When we select the amenities and click on the Submit button, it will go the &lt;code&gt;properties_controller#create&lt;/code&gt; and execute the code like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;Properties&lt;span class="p"&gt;.&lt;/span&gt;create_property&lt;span class="p"&gt;(&lt;/span&gt;params&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it will execute our function &lt;code&gt;maybe_put_amenities&lt;/code&gt; that will list all the amenities using the function &lt;code&gt;Amenities.get_amenities/1&lt;/code&gt; and &lt;code&gt;put_assoc&lt;/code&gt; in every amenity found. And then save it. And it's done. It works.&lt;/p&gt;

&lt;p&gt;But we still may have a problem when trying to submit the form but it got an error. For example, if the user selects some amenities, click on submit but it got an error, and we render again the &lt;code&gt;new&lt;/code&gt; page, the previously selected amenities will not be selected anymore, so to fix that, we can do this in the &lt;code&gt;properties_controller.ex&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; create&lt;span class="p"&gt;(&lt;/span&gt;conn&lt;span class="p"&gt;,&lt;/span&gt; %&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"property"&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; params&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  case Properties&lt;span class="p"&gt;.&lt;/span&gt;create_property&lt;span class="p"&gt;(&lt;/span&gt;params&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="p"&gt;{:&lt;/span&gt;ok&lt;span class="p"&gt;,&lt;/span&gt; property&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
      conn
      &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; put_flash&lt;span class="p"&gt;(:&lt;/span&gt;info&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Success!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; redirect&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="p"&gt;{:&lt;/span&gt;error&lt;span class="p"&gt;,&lt;/span&gt; changeset&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
      data &lt;span class="p"&gt;=&lt;/span&gt; Properties&lt;span class="p"&gt;.&lt;/span&gt;load_amenities&lt;span class="p"&gt;(&lt;/span&gt;changeset&lt;span class="p"&gt;.&lt;/span&gt;data&lt;span class="p"&gt;)&lt;/span&gt;
      amenities &lt;span class="p"&gt;=&lt;/span&gt; Amenities&lt;span class="p"&gt;.&lt;/span&gt;list_amenities&lt;span class="p"&gt;()&lt;/span&gt;

      conn
      &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; put_flash&lt;span class="p"&gt;(:&lt;/span&gt;error&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Error!"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; render&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"new.html"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; changeset&lt;span class="p"&gt;:&lt;/span&gt; %&lt;span class="p"&gt;{&lt;/span&gt;changeset &lt;span class="p"&gt;|&lt;/span&gt; data&lt;span class="p"&gt;:&lt;/span&gt; data&lt;span class="p"&gt;},&lt;/span&gt; amenities&lt;span class="p"&gt;:&lt;/span&gt; amenities&lt;span class="p"&gt;)&lt;/span&gt;
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And create this new method in the file responsible for properties:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; load_amenities&lt;span class="p"&gt;(&lt;/span&gt;property&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; Repo&lt;span class="p"&gt;.&lt;/span&gt;preload&lt;span class="p"&gt;(&lt;/span&gt;property&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;amenities&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's all. It looks like a lot of steps but I hope I can help someone :)&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>phoenix</category>
      <category>many</category>
      <category>association</category>
    </item>
    <item>
      <title>SVG icons in Elixir and Phoenix</title>
      <dc:creator>Ricardo Ruwer</dc:creator>
      <pubDate>Thu, 18 Jul 2019 12:51:06 +0000</pubDate>
      <link>https://dev.to/ricardoruwer/svg-icons-in-elixir-and-phoenix-1hi4</link>
      <guid>https://dev.to/ricardoruwer/svg-icons-in-elixir-and-phoenix-1hi4</guid>
      <description>&lt;p&gt;Here's the best way I can find to use SVG icons in Elixir and Phoenix framework:&lt;/p&gt;

&lt;p&gt;First, you can create a file &lt;code&gt;lib/myapp_web/helpers/icon_helper.ex&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;defmodule MyAppWeb&lt;span class="p"&gt;.&lt;/span&gt;Helpers&lt;span class="p"&gt;.&lt;/span&gt;IconHelper &lt;span class="k"&gt;do&lt;/span&gt;
  @moduledoc &lt;span class="s2"&gt;""&lt;/span&gt;"
  Give some icons &lt;span class="k"&gt;to&lt;/span&gt; be used &lt;span class="k"&gt;on&lt;/span&gt; templates&lt;span class="p"&gt;.&lt;/span&gt;
  &lt;span class="c"&gt;"""&lt;/span&gt;

  use Phoenix&lt;span class="p"&gt;.&lt;/span&gt;HTML

  alias MyAppWeb&lt;span class="p"&gt;.&lt;/span&gt;Router&lt;span class="p"&gt;.&lt;/span&gt;Helpers&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; Routes

  &lt;span class="k"&gt;def&lt;/span&gt; icon_tag&lt;span class="p"&gt;(&lt;/span&gt;conn&lt;span class="p"&gt;,&lt;/span&gt; name&lt;span class="p"&gt;,&lt;/span&gt; opts \\ &lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    classes &lt;span class="p"&gt;=&lt;/span&gt; Keyword&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;opts&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;class&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;" icon"&lt;/span&gt;

    content_tag&lt;span class="p"&gt;(:&lt;/span&gt;svg&lt;span class="p"&gt;,&lt;/span&gt; class&lt;span class="p"&gt;:&lt;/span&gt; classes&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="k"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;(:&lt;/span&gt;use&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"xlink:href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; Routes&lt;span class="p"&gt;.&lt;/span&gt;static_path&lt;span class="p"&gt;(&lt;/span&gt;conn&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"/images/icons.svg#"&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt; name&lt;span class="p"&gt;))&lt;/span&gt;
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then in your file &lt;code&gt;lib/myapp_web.ex&lt;/code&gt; you can import this helper:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="k"&gt;view&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  quote &lt;span class="k"&gt;do&lt;/span&gt;
    # &lt;span class="p"&gt;...&lt;/span&gt;

    &lt;span class="k"&gt;import&lt;/span&gt; MyAppWeb&lt;span class="p"&gt;.&lt;/span&gt;Helpers&lt;span class="p"&gt;.&lt;/span&gt;IconHelper

    # &lt;span class="p"&gt;...&lt;/span&gt;
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's create our icons in the file &lt;code&gt;assets/static/images/icons.svg&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;svg&lt;/span&gt; &lt;span class="na"&gt;version=&lt;/span&gt;&lt;span class="s"&gt;"1.1"&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2000/svg"&lt;/span&gt; &lt;span class="na"&gt;xmlns:xlink=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/1999/xlink"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;svg&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"active"&lt;/span&gt; &lt;span class="na"&gt;viewBox=&lt;/span&gt;&lt;span class="s"&gt;"0 0 426 426"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;"M213.333,0C95.518,0,0,95.514,0,213.333s95.518,213.333,213.333,213.333 c117.828,0,213.333-95.514,213.333-213.333S331.157,0,213.333,0z M174.199,322.918l-93.935-93.931l31.309-31.309l62.626,62.622 l140.894-140.898l31.309,31.309L174.199,322.918z"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;svg&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"right-arrow"&lt;/span&gt; &lt;span class="na"&gt;viewBox=&lt;/span&gt;&lt;span class="s"&gt;"0 0 31 31"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;"M21.205,5.007c-0.429-0.444-1.143-0.444-1.587,0c-0.429,0.429-0.429,1.143,0,1.571l8.047,8.047H1.111 C0.492,14.626,0,15.118,0,15.737c0,0.619,0.492,1.127,1.111,1.127h26.554l-8.047,8.032c-0.429,0.444-0.429,1.159,0,1.587 c0.444,0.444,1.159,0.444,1.587,0l9.952-9.952c0.444-0.429,0.444-1.143,0-1.571L21.205,5.007z"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I added 2 icons here, the &lt;code&gt;active&lt;/code&gt; and the &lt;code&gt;right-arrow&lt;/code&gt;, but you can add as many as you want.&lt;/p&gt;

&lt;p&gt;Now all your views will have the &lt;code&gt;icon_tag/3&lt;/code&gt; so you can use in your HTML:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;%&lt;span class="p"&gt;=&lt;/span&gt; icon_tag&lt;span class="p"&gt;(&lt;/span&gt;@conn&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; class&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"something"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; %&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;%&lt;span class="p"&gt;=&lt;/span&gt; icon_tag&lt;span class="p"&gt;(&lt;/span&gt;@conn&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"right-arrow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; class&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"something"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; %&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also add in your CSS file something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.icon&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;currentColor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then the SVG icon will be filled with the color used in your CSS :)&lt;br&gt;
(As long as you don't use one &lt;code&gt;fill="color"&lt;/code&gt; inside the &lt;code&gt;&amp;lt;path&amp;gt;&lt;/code&gt; in your &lt;code&gt;icons.svg&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;And now, to finish, we can create a test file for the &lt;code&gt;IconHelper&lt;/code&gt; module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;defmodule MyAppWeb&lt;span class="p"&gt;.&lt;/span&gt;Helpers&lt;span class="p"&gt;.&lt;/span&gt;IconHelperTest &lt;span class="k"&gt;do&lt;/span&gt;
  use MyAppWeb&lt;span class="p"&gt;.&lt;/span&gt;ConnCase&lt;span class="p"&gt;,&lt;/span&gt; async&lt;span class="p"&gt;:&lt;/span&gt; true

  &lt;span class="k"&gt;import&lt;/span&gt; Phoenix&lt;span class="p"&gt;.&lt;/span&gt;HTML&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;only&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;safe_to_string&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

  alias MyAppWeb&lt;span class="p"&gt;.&lt;/span&gt;Helpers&lt;span class="p"&gt;.&lt;/span&gt;IconHelper

  test &lt;span class="s2"&gt;"icon_tag/2 renders a svg icon"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    image &lt;span class="p"&gt;=&lt;/span&gt;
      MyAppWeb&lt;span class="p"&gt;.&lt;/span&gt;Endpoint
      &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; IconHelper&lt;span class="p"&gt;.&lt;/span&gt;icon_tag&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; class&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"something"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; safe_to_string&lt;span class="p"&gt;()&lt;/span&gt;

    assert image &lt;span class="p"&gt;==&lt;/span&gt;
             &lt;span class="c"&gt;"&amp;lt;svg class=\"something icon\"&amp;gt;" &amp;lt;&amp;gt;&lt;/span&gt;
               &lt;span class="c"&gt;"&amp;lt;use xlink:href=\"/images/icons.svg#active\"&amp;gt;" &amp;lt;&amp;gt;&lt;/span&gt;
               &lt;span class="c"&gt;"&amp;lt;/svg&amp;gt;"&lt;/span&gt;
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thank you &lt;a href="https://github.com/andrielfn"&gt;@andrielfn&lt;/a&gt; for teaching it to me :)&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>phoenix</category>
      <category>svg</category>
      <category>icon</category>
    </item>
    <item>
      <title>Create dynamic sitemap.xml in Elixir and Phoenix</title>
      <dc:creator>Ricardo Ruwer</dc:creator>
      <pubDate>Thu, 18 Jul 2019 12:37:50 +0000</pubDate>
      <link>https://dev.to/ricardoruwer/create-dynamic-sitemap-xml-in-elixir-and-phoenix-3eid</link>
      <guid>https://dev.to/ricardoruwer/create-dynamic-sitemap-xml-in-elixir-and-phoenix-3eid</guid>
      <description>&lt;p&gt;I created a website for a construction company where they can sell their properties, I built it using Elixir and the Phoenix framework.&lt;/p&gt;

&lt;p&gt;So I was searching on Google how to implement a sitemap.xml but all I can find was this lib called &lt;code&gt;sitemap&lt;/code&gt;, so I tried it but...&lt;/p&gt;

&lt;p&gt;On my website, I have a single page for each property that is created, and in this lib, I have to run a command to generate a new XML file every time I create a property. Also, I can't change the &lt;code&gt;&amp;lt;lastmod&amp;gt;&lt;/code&gt; because it always uses the date where I generated the sitemap.&lt;/p&gt;

&lt;p&gt;So I thought to create my own dynamic sitemap.xml and I will share with you how I did it, it's very simple :)&lt;/p&gt;

&lt;p&gt;First of all, I created my new route on the file &lt;code&gt;router.ex&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="nb"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"/sitemap.xml"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; SitemapController&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;index&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then I created a new file &lt;code&gt;lib/myapp_web/controllers/sitemap_controller.ex&lt;/code&gt; with this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;defmodule MyAppWeb&lt;span class="p"&gt;.&lt;/span&gt;SitemapController &lt;span class="k"&gt;do&lt;/span&gt;
  use MyAppWeb&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;controller

  plug &lt;span class="p"&gt;:&lt;/span&gt;put_layout&lt;span class="p"&gt;,&lt;/span&gt; false

  alias MyApp&lt;span class="p"&gt;.&lt;/span&gt;Properties

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nb"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;conn&lt;span class="p"&gt;,&lt;/span&gt; _params&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    properties &lt;span class="p"&gt;=&lt;/span&gt; Properties&lt;span class="p"&gt;.&lt;/span&gt;list_properties&lt;span class="p"&gt;()&lt;/span&gt;

    conn
    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; put_resp_content_type&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"text/xml"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; render&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"index.xml"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; properties&lt;span class="p"&gt;:&lt;/span&gt; properties&lt;span class="p"&gt;)&lt;/span&gt;
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cool :) Now we have to create the file &lt;code&gt;lib/myapp_web/templates/sitemap/index.xml.eex&lt;/code&gt; that will be our sitemap:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;urlset&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://www.sitemaps.org/schemas/sitemap/0.9"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;url&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;loc&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;%= Routes.home_url(@conn, :index) %&amp;gt;&lt;span class="nt"&gt;&amp;lt;/loc&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;changefreq&amp;gt;&lt;/span&gt;weekly&lt;span class="nt"&gt;&amp;lt;/changefreq&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;priority&amp;gt;&lt;/span&gt;0.5&lt;span class="nt"&gt;&amp;lt;/priority&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/url&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;url&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;loc&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;%= Routes.about_url(@conn, :index) %&amp;gt;&lt;span class="nt"&gt;&amp;lt;/loc&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;changefreq&amp;gt;&lt;/span&gt;never&lt;span class="nt"&gt;&amp;lt;/changefreq&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;priority&amp;gt;&lt;/span&gt;0.3&lt;span class="nt"&gt;&amp;lt;/priority&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/url&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;url&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;loc&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;%= Routes.apartment_url(@conn, :index) %&amp;gt;&lt;span class="nt"&gt;&amp;lt;/loc&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;changefreq&amp;gt;&lt;/span&gt;weekly&lt;span class="nt"&gt;&amp;lt;/changefreq&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;priority&amp;gt;&lt;/span&gt;0.8&lt;span class="nt"&gt;&amp;lt;/priority&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/url&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;url&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;loc&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;%= Routes.house_url(@conn, :index) %&amp;gt;&lt;span class="nt"&gt;&amp;lt;/loc&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;changefreq&amp;gt;&lt;/span&gt;weekly&lt;span class="nt"&gt;&amp;lt;/changefreq&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;priority&amp;gt;&lt;/span&gt;0.8&lt;span class="nt"&gt;&amp;lt;/priority&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/url&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;url&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;loc&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;%= Routes.lot_url(@conn, :index) %&amp;gt;&lt;span class="nt"&gt;&amp;lt;/loc&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;changefreq&amp;gt;&lt;/span&gt;weekly&lt;span class="nt"&gt;&amp;lt;/changefreq&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;priority&amp;gt;&lt;/span&gt;0.8&lt;span class="nt"&gt;&amp;lt;/priority&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/url&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;url&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;loc&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;%= Routes.contact_url(@conn, :index) %&amp;gt;&lt;span class="nt"&gt;&amp;lt;/loc&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;changefreq&amp;gt;&lt;/span&gt;never&lt;span class="nt"&gt;&amp;lt;/changefreq&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;priority&amp;gt;&lt;/span&gt;0.5&lt;span class="nt"&gt;&amp;lt;/priority&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/url&amp;gt;&lt;/span&gt;
  &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;%= for property &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;- @properties do %&amp;gt;
    &lt;span class="nt"&gt;&amp;lt;url&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;loc&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;%= Routes.property_url(@conn, :show, property.slug) %&amp;gt;&lt;span class="nt"&gt;&amp;lt;/loc&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;lastmod&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;%= format_date(property.updated_at) %&amp;gt;&lt;span class="nt"&gt;&amp;lt;/lastmod&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;changefreq&amp;gt;&lt;/span&gt;weekly&lt;span class="nt"&gt;&amp;lt;/changefreq&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;priority&amp;gt;&lt;/span&gt;1&lt;span class="nt"&gt;&amp;lt;/priority&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/url&amp;gt;&lt;/span&gt;
  &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;% end %&amp;gt;
&lt;span class="nt"&gt;&amp;lt;/urlset&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see that I added manually all the routes I have on my website: home, about, apartments, houses, lots and contact. And then I added all the dynamic pages for each property I have created.&lt;/p&gt;

&lt;p&gt;And I have the &lt;code&gt;&amp;lt;lastmod&amp;gt;&lt;/code&gt; with the correct date, using the &lt;code&gt;updated_at&lt;/code&gt;. But we still have to create this function called format_date so we create the file &lt;code&gt;lib/myapp_web/views/sitemap_view.ex&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;defmodule MyAppWeb&lt;span class="p"&gt;.&lt;/span&gt;SitemapView &lt;span class="k"&gt;do&lt;/span&gt;
  use MyAppWeb&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;view&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; format_date&lt;span class="p"&gt;(&lt;/span&gt;date&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    date
    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; DateTime&lt;span class="p"&gt;.&lt;/span&gt;from_naive&lt;span class="p"&gt;!(&lt;/span&gt;&lt;span class="s2"&gt;"Etc/UTC"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; DateTime&lt;span class="p"&gt;.&lt;/span&gt;to_date&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; to_string&lt;span class="p"&gt;()&lt;/span&gt;
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it! Now you can now add this URL: &lt;code&gt;yoursite.com/sitemap.xml&lt;/code&gt; on the Google Console and it'll just work fine :)&lt;/p&gt;

&lt;p&gt;But don't forget to add some tests for this! So we can do this on the file &lt;code&gt;test/myapp_web/controllers/sitemap_controller_test.exs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;defmodule MyAppWeb&lt;span class="p"&gt;.&lt;/span&gt;SitemapControllerTest &lt;span class="k"&gt;do&lt;/span&gt;
  use MyAppWeb&lt;span class="p"&gt;.&lt;/span&gt;ConnCase

  describe &lt;span class="s2"&gt;"GET /sitemap.xml"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    test &lt;span class="s2"&gt;"accesses the sitemap in format xml"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; %&lt;span class="p"&gt;{&lt;/span&gt;conn&lt;span class="p"&gt;:&lt;/span&gt; conn&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      property &lt;span class="p"&gt;=&lt;/span&gt; property_fixture&lt;span class="p"&gt;()&lt;/span&gt;

      conn &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;conn&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"/sitemap.xml"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      assert response_content_type&lt;span class="p"&gt;(&lt;/span&gt;conn&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;xml&lt;span class="p"&gt;)&lt;/span&gt;
      assert response&lt;span class="p"&gt;(&lt;/span&gt;conn&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=~&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt;&lt;span class="k"&gt;r&lt;/span&gt;&lt;span class="sr"&gt;/&amp;lt;loc&amp;gt;.*#{property.slug}&amp;lt;\/loc&amp;gt;/&lt;/span&gt;
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this function &lt;code&gt;property_fixture()&lt;/code&gt; you have to create a new property.&lt;/p&gt;

&lt;p&gt;And then a test to our view in &lt;code&gt;test/myapp_web/views/sitemap_view_test.exs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;defmodule MyAppWeb&lt;span class="p"&gt;.&lt;/span&gt;SitemapViewTest &lt;span class="k"&gt;do&lt;/span&gt;
  use MyAppWeb&lt;span class="p"&gt;.&lt;/span&gt;ConnCase&lt;span class="p"&gt;,&lt;/span&gt; async&lt;span class="p"&gt;:&lt;/span&gt; true

  alias MyAppWeb&lt;span class="p"&gt;.&lt;/span&gt;SitemapView

  test &lt;span class="s2"&gt;"format_date/1"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    assert SitemapView&lt;span class="p"&gt;.&lt;/span&gt;format_date&lt;span class="p"&gt;(~&lt;/span&gt;N&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;2019-07-08&lt;/span&gt; &lt;span class="m"&gt;13&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;15&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;00&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"2019-07-08"&lt;/span&gt;
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's all! :)&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>phoenix</category>
      <category>sitemap</category>
    </item>
  </channel>
</rss>
