Created
September 7, 2015 21:31
-
-
Save sebyx07/7b3528bef7a21ced302f to your computer and use it in GitHub Desktop.
elixirsips
This file has been truncated, but you can view the full file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?xml version="1.0" encoding="UTF-8"?> | |
| <rss xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" version="2.0"> | |
| <channel> | |
| <title>Elixir Sips</title> | |
| <link>https://elixirsips.dpdcart.com/</link> | |
| <description/> | |
| <pubDate>Mon, 07 Sep 2015 06:08:00 -0400</pubDate> | |
| <managingEditor>[email protected] (Josh Adams)</managingEditor> | |
| <language>en</language> | |
| <copyright>Copyright 2015 Elixir Sips</copyright> | |
| <generator>getdpd.com</generator> | |
| <itunes:summary>ElixirSips is a twice-weekly small dose of knowledge related to the Elixir programming language.</itunes:summary> | |
| <item> | |
| <title><![CDATA[191 - Interesting IO]]></title> | |
| <link>https://elixirsips.dpdcart.com/subscriber/post?id=951</link> | |
| <description><![CDATA[<div class="blog-entry"> | |
| <div class="blog-content"><h1 style="box-sizing: border-box; font-size: 2.25em; margin-right: 0px; margin-bottom: 16px; margin-left: 0px; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; margin-top: 0px !important;">Episode 191: Interesting IO</h1> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.48px;">Up until now I've not really done very much with terminal-based IO that was interesting. To rectify that, we're going to write an ANSI renderer for Tetris in the TTY. Let's get started.</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Project</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.48px;">I've tagged the extris project with <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">before_episode_191</code>. Let's start out by turning off the Wx and SDL renderers and starting a new TTY renderer.</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.48px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| vim lib/extris.ex</pre> | |
| </div> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.48px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| spawn(<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">fn</span>() <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Extris</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">TTY</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Window</span>.start(game) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span>)</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.48px;">Next we'll make an <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">Extris.TTY.Window</code> module:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.48px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| mkdir lib/extris/tty | |
| vim lib/extris/tty/window.ex</pre> | |
| </div> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.48px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">Extris.TTY.Window</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> start(game) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.48px;">Now we're going to follow our standard rendering model here - clear the screen and redraw it at some<code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">@refresh_interval</code>:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.48px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-smi" style="box-sizing: border-box;">@refresh_interval</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">100</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.48px;">Let's just define a loop that draws the board, waits for the refresh interval, and then loops:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.48px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> start(game) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| loop(game) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defp</span> loop(game) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| clear_screen | |
| draw_board | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:timer</span>.sleep <span class="pl-smi" style="box-sizing: border-box;">@refresh_interval</span> | |
| loop(game) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.48px;">Now I actually made clearing the screen and drawing the board 2 bare functions here for my pseudo code, but really they're going to return iolists that have ANSI escape sequences in them, and we're going to print them to IO with <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">IO.write</code>. Let's change this code up a bit.</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.48px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defp</span> loop(game) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| state <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Extris</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Game</span>.get_state(game) | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">IO</span>.write [ | |
| clear_screen, | |
| draw_board(state.board) | |
| ] | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:timer</span>.sleep <span class="pl-smi" style="box-sizing: border-box;">@refresh_interval</span> | |
| loop(game) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defp</span> clear_screen <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| [ | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">IO</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ANSI</span>.home, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">IO</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ANSI</span>.clear | |
| ] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defp</span> draw_board(board) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>board goes here...<span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.48px;">OK, now let's run it. I've got that mapped to <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">,.</code></p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.48px;">((( do it )))</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.48px;">Alright so now we want to go ahead and draw the board. Remember that the board is just a list of lists, where the inner lists are numbers that correspond to the pixel color for a given block. Let's look at what drawing a line might look like:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.48px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defp</span> draw_board(board) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Enum</span>.map(board, <span class="pl-smi" style="box-sizing: border-box;">&</span>draw_line<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">/</span><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defp</span> draw_line(line) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Enum</span>.map(line, <span class="pl-smi" style="box-sizing: border-box;">&</span>draw_cell<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">/</span><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1</span>), <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-cce" style="box-sizing: border-box;">\n</span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defp</span> draw_cell(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span>), <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span>: <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span> <span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defp</span> draw_cell(x), <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span>: x</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.48px;">((( run it )))</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.48px;">OK, so we have something like a tty renderer now. But numbers are boring, right? Let's draw these as little blocks instead. I've linked to the ANSI block characters, if you want to dig in. I'll define some as module attributes so we can refer to them by name:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.48px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">Extris.TTY.Window</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-smi" style="box-sizing: border-box;">@block</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-cce" style="box-sizing: border-box;">\x</span>{2588}<span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defp</span> draw_cell(x), <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span>: <span class="pl-smi" style="box-sizing: border-box;">@block</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.48px;">((( run it )))</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.48px;">OK, so that looks kind of silly. We need 2 block characters side by side for each of pixels if we want to be square:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.48px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-smi" style="box-sizing: border-box;">@block</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-cce" style="box-sizing: border-box;">\x</span>{2588}<span class="pl-cce" style="box-sizing: border-box;">\x</span>{2588}<span class="pl-pds" style="box-sizing: border-box;">"</span></span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.48px;">We also need to make the empty block 2 spaces:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.48px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defp</span> draw_cell(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span>), <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span>: <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span> <span class="pl-pds" style="box-sizing: border-box;">"</span></span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.48px;">((( run it )))</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.48px;">Alright, now our pieces look a bit more proper. Obviously we want them to be colored. Let's start by making every pixel bright yellow:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.48px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defp</span> draw_cell(x), <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span>: [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">IO</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ANSI</span>.bright, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">IO</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ANSI</span>.yellow, <span class="pl-smi" style="box-sizing: border-box;">@block</span>]</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.48px;">Awesome. But if you see the blinking cursor and the exit text, it was bright yellow too. We need to reset after we draw our cell:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.48px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defp</span> draw_cell(x), <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span>: [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">IO</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ANSI</span>.bright, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">IO</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ANSI</span>.yellow, <span class="pl-smi" style="box-sizing: border-box;">@block</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">IO</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ANSI</span>.reset]</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.48px;">OK, so that fixes that issue. Now we'd like each block to be rendered with a different color, obviously. First, let's define the colors by shape:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.48px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defp</span> color(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:ell</span>), <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span>: <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:yellow</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defp</span> color(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:jay</span>), <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span>: [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:bright</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:red</span>] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defp</span> color(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:ess</span>), <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span>: <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:red</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defp</span> color(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:zee</span>), <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span>: <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:green</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defp</span> color(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:bar</span>), <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span>: [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:bright</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:cyan</span>] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defp</span> color(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:oh</span>), <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span>: [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:bright</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:yellow</span>] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defp</span> color(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:tee</span>), <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span>: <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:magenta</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.48px;">Now we'll define <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">draw_cell</code> such that it knows how to use this data:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.48px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defp</span> draw_cell(n) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| n | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Extris</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Shapes</span>.by_number | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> color | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> draw_block | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.48px;">Go ahead and run it, and we can see the game rendering nicely. Of course we can add some decorations to it if we wish, using the box drawing characters:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.48px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-smi" style="box-sizing: border-box;">@vert_line</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-cce" style="box-sizing: border-box;">\x</span>{2502}<span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| <span class="pl-smi" style="box-sizing: border-box;">@mid_bar</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-cce" style="box-sizing: border-box;">\x</span>{2500}<span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| <span class="pl-smi" style="box-sizing: border-box;">@top_left</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-cce" style="box-sizing: border-box;">\x</span>{250c}<span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| <span class="pl-smi" style="box-sizing: border-box;">@top_right</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-cce" style="box-sizing: border-box;">\x</span>{2510}<span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| <span class="pl-smi" style="box-sizing: border-box;">@bottom_left</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-cce" style="box-sizing: border-box;">\x</span>{2514}<span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| <span class="pl-smi" style="box-sizing: border-box;">@bottom_right</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-cce" style="box-sizing: border-box;">\x</span>{2518}<span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defp</span> draw_board(board) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| width <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Enum</span>.count hd(board) | |
| [ | |
| top_bar(width), | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Enum</span>.map(board, <span class="pl-smi" style="box-sizing: border-box;">&</span>draw_line<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">/</span><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1</span>), | |
| bottom_bar(width) | |
| ] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> top_bar(width) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| [<span class="pl-smi" style="box-sizing: border-box;">@top_left</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">String</span>.duplicate(<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-s1" style="box-sizing: border-box; color: rgb(51, 51, 51);"><span class="pl-pse" style="box-sizing: border-box;">#{</span><span class="pl-smi" style="box-sizing: border-box;">@mid_bar</span><span class="pl-pse" style="box-sizing: border-box;">}#{</span><span class="pl-smi" style="box-sizing: border-box;">@mid_bar</span><span class="pl-pse" style="box-sizing: border-box;">}</span></span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>, width), <span class="pl-smi" style="box-sizing: border-box;">@top_right</span>, <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-cce" style="box-sizing: border-box;">\n</span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> bottom_bar(width) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| [<span class="pl-smi" style="box-sizing: border-box;">@bottom_left</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">String</span>.duplicate(<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-s1" style="box-sizing: border-box; color: rgb(51, 51, 51);"><span class="pl-pse" style="box-sizing: border-box;">#{</span><span class="pl-smi" style="box-sizing: border-box;">@mid_bar</span><span class="pl-pse" style="box-sizing: border-box;">}#{</span><span class="pl-smi" style="box-sizing: border-box;">@mid_bar</span><span class="pl-pse" style="box-sizing: border-box;">}</span></span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>, width), <span class="pl-smi" style="box-sizing: border-box;">@bottom_right</span>, <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-cce" style="box-sizing: border-box;">\n</span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defp</span> draw_line(line) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| [<span class="pl-smi" style="box-sizing: border-box;">@vert_line</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Enum</span>.map(line, <span class="pl-smi" style="box-sizing: border-box;">&</span>draw_cell<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">/</span><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1</span>), <span class="pl-smi" style="box-sizing: border-box;">@vert_line</span>, <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-cce" style="box-sizing: border-box;">\n</span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Summary</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.48px;">Alright, so that's a functioning TTY-based Tetris renderer. I'm pretty happy with this. Of course, there's no user facing interaction from the terminal, because it's impossible to get user input character-by-character in the elixir repl. In a future episode, we'll look at how we can use a port driver that ships in Erlang to get character-based user input. See you soon!</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Resources</h2> | |
| <ul style="box-sizing: border-box; padding-right: 0px; padding-left: 2em; margin-top: 0px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.48px; margin-bottom: 0px !important;"> | |
| <li style="box-sizing: border-box;"><a href="https://github.com/knewter/extris" style="box-sizing: border-box; color: rgb(64, 120, 192); text-decoration: none; background-color: transparent;">knewter/extris</a></li> | |
| <li style="box-sizing: border-box;"><a href="http://prog21.dadgum.com/70.html" style="box-sizing: border-box; color: rgb(64, 120, 192); text-decoration: none; background-color: transparent;">A Ramble Through Erlang IO Lists</a></li> | |
| <li style="box-sizing: border-box;"><a href="https://en.wikipedia.org/wiki/Box-drawing_character" style="box-sizing: border-box; color: rgb(64, 120, 192); text-decoration: none; background-color: transparent;">Box-Drawing Characters</a></li> | |
| <li style="box-sizing: border-box;"><a href="https://en.wikipedia.org/wiki/Block_Elements" style="box-sizing: border-box; color: rgb(64, 120, 192); text-decoration: none; background-color: transparent;">Block Elements</a></li> | |
| </ul> | |
| </div> | |
| <h3>Attached Files</h3> | |
| <ul> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=58314">191_Interesting_IO.mp4</a></li> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=58315">191_Interesting_IO.markdown</a></li> | |
| </ul></div>]]></description> | |
| <guid isPermaLink="false">dpd-94dc410788098bf49298acc56f95c8850a2ef79e</guid> | |
| <pubDate>Mon, 07 Sep 2015 06:08:00 -0400</pubDate> | |
| <enclosure url="https://elixirsips.dpdcart.com/feed/download/58314/191_Interesting_IO.mp4" length="58745898" type="video/mp4"/> | |
| </item> | |
| <item> | |
| <title><![CDATA[190 - Testing Phoenix Channels]]></title> | |
| <link>https://elixirsips.dpdcart.com/subscriber/post?id=918</link> | |
| <description><![CDATA[<div class="blog-entry"> | |
| <div class="blog-content"><h1 style="box-sizing: border-box; font-size: 2.25em; margin-right: 0px; margin-bottom: 16px; margin-left: 0px; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; margin-top: 0px !important;">Episode 190: Testing Phoenix Channels</h1> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Testing is one of those things that I really need to do to be happy with software, but until now I haven't written any tests around Phoenix Channels. Today I decided that needed to change, so I figured I'd share what I learned with you. Let's write some channel tests...</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Project</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">We'll just use the ElixirFriends project again. The channel here is very simple, but since it's my first channel test that's actually a benefit I suppose.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">First off, we'll open up a test in <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">test/channels</code>:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| vim <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">test</span>/channels/posts_channel_test.exs</pre> | |
| </div> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">ElixirFriends.PostsChannelTest</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Phoenix creates a ChannelCase for you</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">use</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ElixirFriends</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ChannelCase</span> | |
| test <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>new posts are pushed to the posts channel on the posts:new topic<span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Before we move on, let's look at the ChannelCase that the phoenix generator made for us.</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| vim <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">test</span>/support/channel_case.ex</pre> | |
| </div> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">ElixirFriends.ChannelCase</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">@moduledoc """</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> This module defines the test case to be used by</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> channel tests.</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> Such tests rely on `Phoenix.ChannelTest` and also</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> imports other functionality to make it easier</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> to build and query models.</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> Finally, if the test case interacts with the database,</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> it cannot be async. For this reason, every test runs</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> inside a transaction which is reset at the beginning</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> of the test unless the test case is marked as async.</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> """</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">use</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ExUnit</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">CaseTemplate</span> | |
| using <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">quote</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Import conveniences for testing with channels</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">use</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Phoenix</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ChannelTest</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Alias the data repository and import query/model functions</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ElixirFriends</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Repo</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">import</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Ecto</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Model</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">import</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Ecto</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Query</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">only:</span> [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">from:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">2</span>] | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # The default endpoint for testing</span> | |
| <span class="pl-smi" style="box-sizing: border-box;">@endpoint</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ElixirFriends</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Endpoint</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| setup tags <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">unless</span> tags[<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:async</span>] <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Ecto</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Adapters</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">SQL</span>.restart_test_transaction(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ElixirFriends</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Repo</span>, []) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:ok</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">So this isn't that exciting, but it's good to know what's happening in your code. Now, back to the test.</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">ElixirFriends.PostsChannelTest</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">use</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ElixirFriends</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ChannelCase</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ElixirFriends</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ImageTweetStreamer</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ElixirFriends</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Post</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ElixirFriends</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">UserSocket</span> | |
| test <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>new posts are pushed to the posts channel on the posts:new topic<span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # We'll just connect to the socket and join a topic. These are some nice</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # helpers that phoenix provides in the ChannelTest module</span> | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:ok</span>, socket} <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> connect(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">UserSocket</span>, %{}) | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:ok</span>, _, socket} <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> subscribe_and_join(socket, <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>posts:new<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, %{}) | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Now we'd like to just make sure we're broadcast any new posts that the</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # ImageTweetStreamer stores. We'll set up the post we'd like to see</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # broadcast</span> | |
| post <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Post</span>{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">content:</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>foo<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">image_url:</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>bar<span class="pl-pds" style="box-sizing: border-box;">"</span></span>} | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Then we assert that it is broadcast</span> | |
| assert_broadcast <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>new:post<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, post | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">If we run the tests now they fail of course, because nothing occurs in our system to cause this to be broadcast. We'll open up the image tweet streamer and make the <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">store_post</code> function public just so we can use it from here, for now, and confirm that the post is broadcast when we use that function:</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">((( publicize that function )))</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">ElixirFriends.PostsChannelTest</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">use</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ElixirFriends</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ChannelCase</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ElixirFriends</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ImageTweetStreamer</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ElixirFriends</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Post</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ElixirFriends</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">UserSocket</span> | |
| test <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>new posts are pushed to the posts channel on the posts:new topic<span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:ok</span>, socket} <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> connect(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">UserSocket</span>, %{}) | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:ok</span>, _, socket} <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> subscribe_and_join(socket, <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>posts:new<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, %{}) | |
| post <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Post</span>{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">content:</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>foo<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">image_url:</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>bar<span class="pl-pds" style="box-sizing: border-box;">"</span></span>} | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Now we'll use that function to store a post</span> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ImageTweetStreamer</span>.store_post(post) | |
| assert_broadcast <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>new:post<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, post | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">If everything went well, our test should be passing now.</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Summary</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">This was a very basic example, but it has all of the pieces in it that matter for you to be able to test your channels. I hope it was helpful. See you soon!</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Resources</h2> | |
| <ul style="box-sizing: border-box; padding-right: 0px; padding-left: 2em; margin-top: 0px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; margin-bottom: 0px !important;"> | |
| <li style="box-sizing: border-box;"><a href="http://hexdocs.pm/phoenix/Phoenix.ChannelTest.html" style="box-sizing: border-box; color: rgb(64, 120, 192); text-decoration: none; background-color: transparent;">ChannelTest</a></li> | |
| </ul> | |
| </div> | |
| <h3>Attached Files</h3> | |
| <ul> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=58050">190_Testing_Phoenix_Channels.mp4</a></li> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=58051">190_Testing_Phoenix_Channels.markdown</a></li> | |
| </ul></div>]]></description> | |
| <guid isPermaLink="false">dpd-7d94f18844d4318246f69d82a437f7f0f544eca7</guid> | |
| <pubDate>Wed, 02 Sep 2015 07:07:00 -0400</pubDate> | |
| <enclosure url="https://elixirsips.dpdcart.com/feed/download/58050/190_Testing_Phoenix_Channels.mp4" length="20439337" type="video/mp4"/> | |
| </item> | |
| <item> | |
| <title><![CDATA[189 - .iex.exs]]></title> | |
| <link>https://elixirsips.dpdcart.com/subscriber/post?id=912</link> | |
| <description><![CDATA[<div class="blog-entry"> | |
| <div class="blog-content"><h1 style="box-sizing: border-box; font-size: 2.25em; margin-right: 0px; margin-bottom: 16px; margin-left: 0px; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; margin-top: 0px !important;">Episode 189: .iex.exs</h1> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">In this episode we'll look at the .iex.exs file, which gives you a nice way to customize your iex prompt. Let's get started.</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Project</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">I'm using the ElixirFriends project to show off some of the stuff you can do here. Let's start off with a really basic use for this:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| iex -S mix</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">OK, so we want to get a Post from our Repo. Let's do that.</p> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 16px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; background-color: rgb(247, 247, 247);"> | |
| <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0px; margin: 0px; border-radius: 3px; word-break: normal; white-space: pre; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;">iex> ElixirFriends.Repo.get(ElixirFriends.Post, 1) | |
| </code></pre> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Oh. My. God. That was a lot of typing to just fetch a record from our database. That's why I usually start off by adding a couple of aliases.</p> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 16px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; background-color: rgb(247, 247, 247);"> | |
| <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0px; margin: 0px; border-radius: 3px; word-break: normal; white-space: pre; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;">iex> alias ElixirFriends.Repo | |
| iex> alias ElixirFriends.Post | |
| iex> Repo.get Post, 1 | |
| </code></pre> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">OK, that's nicer, but we had to type even more to get to the short version. So we'll add a .iex.exs file to our project that prepares these aliases for us:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| vim .iex.exs</pre> | |
| </div> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ElixirFriends</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Repo</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ElixirFriends</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Post</span></pre> | |
| </div> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| iex -S mix</pre> | |
| </div> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 16px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; background-color: rgb(247, 247, 247);"> | |
| <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0px; margin: 0px; border-radius: 3px; word-break: normal; white-space: pre; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;">iex> Repo.get Post, 1 | |
| </code></pre> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">OK, so that's a much nicer experience. What else could we do? Well, any valid Elixir expression is fair game - this file is just run after iex starts up. You can also define a global one in your home directory:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| vim <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">~</span>/.iex.exs</pre> | |
| </div> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">IO</span>.puts <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>Zomg let's get some Elixir on...<span class="pl-pds" style="box-sizing: border-box;">"</span></span></pre> | |
| </div> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| iex -S mix</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Huh. So it turns out that a project-specific .iex.exs file will completely override your global one. First, let's confirm that our global one works if we don't have one in our project:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">cd</span> .. | |
| iex</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">OK, so our global .iex.exs file works. What if we had defined some stuff we wanted in every project, and now we get screwed if we add a project-specific .iex.exs file? Well, you can just load the global one in your project:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">cd</span> elixir_friends | |
| vim .iex.exs</pre> | |
| </div> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| import_file <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>~/.iex.exs<span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">#...</span></pre> | |
| </div> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| iex -S mix</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Alright, so what else might you want to do with this file? Maybe you want to always have the result of an expression show up in glorious color?</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| vim .iex.exs</pre> | |
| </div> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">IEx</span>.configure(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">colors:</span> [ <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">eval_result:</span> [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:red</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:bright</span>] ])</pre> | |
| </div> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| iex -S mix</pre> | |
| </div> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 16px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; background-color: rgb(247, 247, 247);"> | |
| <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0px; margin: 0px; border-radius: 3px; word-break: normal; white-space: pre; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;">iex> Repo.get Post, 1 | |
| </code></pre> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Of course that's terrible because it looks like everything's an error, but hey, neato. What else can we configure?</p> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 16px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; background-color: rgb(247, 247, 247);"> | |
| <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0px; margin: 0px; border-radius: 3px; word-break: normal; white-space: pre; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;">iex> h IEx.configure/1 | |
| </code></pre> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">So there are a few options here, but I found the last one, regarding prompts, kind of interesting. Let's change the iex prompt itself:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| vim .iex.exs</pre> | |
| </div> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">IEx</span>.configure(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">default_prompt:</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>ElixirFriends (%counter)><span class="pl-pds" style="box-sizing: border-box;">"</span></span>)</pre> | |
| </div> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| iex -S mix</pre> | |
| </div> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Summary</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">So that's fun. In today's episode, we saw how you can configure IEx to be more fitting for your style or to ease development on your project by injecting frequent aliases. You can go crazy with this, as it's just Elixir code, so have at it. If you have a tweak you're particularly proud of it, feel free to share it in the Episode's comments. I'd love to see what you do. See you soon!</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Resources</h2> | |
| <ul style="box-sizing: border-box; padding-right: 0px; padding-left: 2em; margin-top: 0px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; margin-bottom: 0px !important;"> | |
| <li style="box-sizing: border-box;"><a href="http://elixir-lang.org/docs/stable/iex/" style="box-sizing: border-box; color: rgb(64, 120, 192); text-decoration: none; background-color: transparent;">IEx documentation</a> - this mentions the .iex.exs file.</li> | |
| <li style="box-sizing: border-box;"><a href="https://github.com/nathanl/.dotfiles/blob/master/iex.exs" style="box-sizing: border-box; color: rgb(64, 120, 192); text-decoration: none; background-color: transparent;">An example .iex.exs file I found on GitHub</a></li> | |
| </ul> | |
| </div> | |
| <h3>Attached Files</h3> | |
| <ul> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=57821">189_.iex.exs.mp4</a></li> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=57822">189_.iex.exs.markdown</a></li> | |
| </ul></div>]]></description> | |
| <guid isPermaLink="false">dpd-a639075ee9a5152488fbd3772f07830689b2486e</guid> | |
| <pubDate>Fri, 28 Aug 2015 21:47:00 -0400</pubDate> | |
| <enclosure url="https://elixirsips.dpdcart.com/feed/download/57821/189_.iex.exs.mp4" length="16469685" type="video/mp4"/> | |
| </item> | |
| <item> | |
| <title><![CDATA[188 - ElixirScript]]></title> | |
| <link>https://elixirsips.dpdcart.com/subscriber/post?id=910</link> | |
| <description><![CDATA[<div class="blog-entry"> | |
| <div class="blog-content"><h1 style="box-sizing: border-box; font-size: 2.25em; margin-right: 0px; margin-bottom: 16px; margin-left: 0px; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; margin-top: 0px !important;">Episode 188: ElixirScript</h1> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Last night at NashFP I saw Jonathan Boston talk again about ClojureScript, which dovetailed pretty nicely into a project I'm working on and some frustrations we had converting data structures between Elixir and JSON. Then today, Sonny Scroggins reminded me about ElixirScript, which is a project that allows you to write JavaScript programs in Elixir. I checked out the project, and it's actually made a ton of headway since I last saw it. Let's check it out.</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Project</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">I started out by fetching the release itself from GitHub and placing it at /usr/local, then adding it to my PATH. Let's have a look at some of the basic features that it gives you.</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| mkdir elixirscript_playground | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">cd</span> elixirscript_playground | |
| mkdir app</pre> | |
| </div> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| vim app/calc.ex</pre> | |
| </div> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">Calc</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> add(first, second) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| first <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">+</span> second | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">So this is not a complicated Elixir module, obviously. We can use <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">ex2js</code> to transpile it into ES6-flavored JavaScript:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| ex2js app/calc.ex</pre> | |
| </div> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 16px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; background-color: rgb(247, 247, 247);"> | |
| <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0px; margin: 0px; border-radius: 3px; word-break: normal; white-space: pre; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;"> import Erlang from '__lib/erlang'; | |
| import Kernel from '__lib/kernel'; | |
| import Tuple from '__lib/tuple'; | |
| import fun from '__lib/funcy/fun'; | |
| const __MODULE__ = Erlang.atom('Calc'); | |
| let add = fun([[fun.parameter, fun.parameter], function(first,second) { | |
| return first + second; | |
| }]); | |
| export default { | |
| add: add | |
| }; | |
| </code></pre> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">You run ex2js against a list of elixir files, and it produces an output string. You can tell it to output javascript files themselves:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| ex2js app/calc.ex -o app/ | |
| view app/calc.js</pre> | |
| </div> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 16px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; background-color: rgb(247, 247, 247);"> | |
| <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0px; margin: 0px; border-radius: 3px; word-break: normal; white-space: pre; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;"> import Erlang from '__lib/erlang'; | |
| import Kernel from '__lib/kernel'; | |
| import Tuple from '__lib/tuple'; | |
| import fun from '__lib/funcy/fun'; | |
| const __MODULE__ = Erlang.atom('Calc'); | |
| let add = fun([[fun.parameter, fun.parameter], function(first,second) { | |
| return first + second; | |
| }]); | |
| export default { | |
| add: add | |
| }; | |
| </code></pre> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">OK, so here it's outputting files for the standard lib into this <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">__lib</code> directory and then just using ES6 modules to import those. That feels kind of normal. It's also worth noticing that the generated JavaScript is using <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">funcy.js</code> to support pattern matching in the generated JavaScript.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">You'll notice that the JavaScript being output is ES6. Since I don't have any real environments that <em style="box-sizing: border-box;">run</em>ES6 natively, I'm going to fiddle with Babel to wrap this up into something I can run in the browser fairly trivially.</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| vim package.json</pre> | |
| </div> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 16px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; background-color: rgb(247, 247, 247);"> | |
| <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0px; margin: 0px; border-radius: 3px; word-break: normal; white-space: pre; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;">{ | |
| "repository": {}, | |
| "dependencies": { | |
| "brunch": "^1.8.1", | |
| "babel-brunch": "^5.1.1" | |
| } | |
| } | |
| </code></pre> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| vim brunch-config.coffee</pre> | |
| </div> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 16px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; background-color: rgb(247, 247, 247);"> | |
| <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0px; margin: 0px; border-radius: 3px; word-break: normal; white-space: pre; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;">module.exports = config: | |
| files: | |
| javascripts: | |
| joinTo: 'app.js' | |
| conventions: | |
| ignored: -> false # We have to add this ignored bit because brunch will ignore elixirscript's underscore-prefixed libs dir by default | |
| </code></pre> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">OK so now if I just run <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">brunch build</code> it will build this into a module that I can actually use from the browser. To see the elixirscript evaluated, we'll use the calc module we built from a webpage:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| mkdir app/assets | |
| vim app/assets/index.html</pre> | |
| </div> | |
| <div class="highlight highlight-html" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">html</span>> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">head</span>> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">title</span>>Testing ElixirScript</<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">title</span>> | |
| </<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">head</span>> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">body</span>> | |
| <span class="pl-s1" style="box-sizing: border-box;"> <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">script</span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">src</span>=<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>app.js<span class="pl-pds" style="box-sizing: border-box;">"</span></span>></<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">script</span>></span> | |
| <span class="pl-s1" style="box-sizing: border-box;"> <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">script</span>></span> | |
| <span class="pl-s1" style="box-sizing: border-box;"> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">var</span> calc <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">require</span>(<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">'</span>calc<span class="pl-pds" style="box-sizing: border-box;">'</span></span>);</span> | |
| <span class="pl-s1" style="box-sizing: border-box;"> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">alert</span>(calc.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">add</span>(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">2</span>));</span> | |
| <span class="pl-s1" style="box-sizing: border-box;"> </<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">script</span>></span> | |
| </<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">body</span>> | |
| </<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">html</span>></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">So that's got it working, but it would really be cool if brunch just took care of compiling our ElixirScript for us. I went ahead and wrote a very small brunch plugin called elixirscript-brunch that takes care of this. Let's add it and see what changes:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| vim package.json</pre> | |
| </div> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 16px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; background-color: rgb(247, 247, 247);"> | |
| <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0px; margin: 0px; border-radius: 3px; word-break: normal; white-space: pre; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;"> "elixirscript-brunch": "^0.0.3" | |
| </code></pre> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| npm install | |
| rm app/calc.js | |
| rm -fr app/__lib | |
| brunch watch --server</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">We'll try it again, and everything Just Works. Of course it can't be that easy; right now my plugin actually puts the <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">__lib</code> and <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">calc.js</code> files into the app directory, so that's super awkward. I'm hoping that the creator of ElixirScript can help me sort out the last little bits to make this a perfect brunch plugin. I think it requires a couple of changes to the ex2js script.</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Summary</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">So that's it. In today's episode we saw ElixirScript and saw how we can write our JavaScript in Elixir and call it from the browser. See you soon!</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Resources</h2> | |
| <ul style="box-sizing: border-box; padding-right: 0px; padding-left: 2em; margin-top: 0px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; margin-bottom: 0px !important;"> | |
| <li style="box-sizing: border-box;"><a href="https://github.com/bryanjos/elixirscript" style="box-sizing: border-box; color: rgb(64, 120, 192); text-decoration: none; background-color: transparent;">bryanjos/elixirscript</a></li> | |
| <li style="box-sizing: border-box;"><a href="https://github.com/bryanjos/elixirscript/releases" style="box-sizing: border-box; color: rgb(64, 120, 192); text-decoration: none; background-color: transparent;">ElixirScript release</a></li> | |
| <li style="box-sizing: border-box;"><a href="https://github.com/bramstein/funcy" style="box-sizing: border-box; color: rgb(64, 120, 192); text-decoration: none; background-color: transparent;">bramstein/funcy</a></li> | |
| <li style="box-sizing: border-box;"><a href="https://babeljs.io/docs/setup/#babel_cli" style="box-sizing: border-box; color: rgb(64, 120, 192); text-decoration: none; background-color: transparent;">babel</a></li> | |
| <li style="box-sizing: border-box;"><a href="https://www.npmjs.com/package/elixirscript-brunch" style="box-sizing: border-box; color: rgb(64, 120, 192); text-decoration: none; background-color: transparent;">elixirscript-brunch</a></li> | |
| </ul> | |
| </div> | |
| <h3>Attached Files</h3> | |
| <ul> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=57778">188_ElixirScript.markdown</a></li> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=57779">188_ElixirScript.mp4</a></li> | |
| </ul></div>]]></description> | |
| <guid isPermaLink="false">dpd-53debfa67e8b0a7170bb01b9ec97f4d8300ceea5</guid> | |
| <pubDate>Thu, 27 Aug 2015 18:34:00 -0400</pubDate> | |
| <enclosure url="https://elixirsips.dpdcart.com/feed/download/57779/188_ElixirScript.mp4" length="32814809" type="video/mp4"/> | |
| </item> | |
| <item> | |
| <title><![CDATA[187 - Compiling a Custom AST Into Elixir Functions]]></title> | |
| <link>https://elixirsips.dpdcart.com/subscriber/post?id=897</link> | |
| <description><![CDATA[<div class="blog-entry"> | |
| <div class="blog-content"><h1 style="box-sizing: border-box; font-size: 2.25em; margin-right: 0px; margin-bottom: 16px; margin-left: 0px; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; margin-top: 0px !important;">Episode 187: Compiling a Custom AST Into Elixir Functions</h1> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;">One of the nicest things Elixir has going for it is its extremely good metaprogramming support. Today we'll look at defining a custom AST and compiling it into Elixir functions. Let's get started.</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Project</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;">We'll use the rules engine project as our starting point. I've tagged the repo with <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">before_episode_187</code>.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;">Let's reacquaint ourselves with the underlying rule we'll be compiling our custom language to.</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| vim <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">test</span>/rules_engine_test.exs</pre> | |
| </div> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">quote</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">case</span> var!(patient).bmi <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| x <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">when</span> x <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">>=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">40</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Guidance</span>{ | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">diagnosis:</span> %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Diagnosis</span>{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">id:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1111</span>}, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">text:</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>Consider the following...<span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| } | |
| x <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">when</span> x <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"><</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">18</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Guidance</span>{ | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">diagnosis:</span> %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Diagnosis</span>{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">id:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">2222</span>}, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">text:</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>Consider the following...<span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| } | |
| _ <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">nil</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;">OK, so we'd like to build a little AST that compiles down to this. First, let's have a look at what the Elixir AST for this looks like:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| iex -S mix</pre> | |
| </div> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 16px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; background-color: rgb(247, 247, 247);"> | |
| <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0px; margin: 0px; border-radius: 3px; word-break: normal; white-space: pre; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;">iex> quote do | |
| case var!(patient).bmi do | |
| x when x >= 40 -> | |
| %Guidance{ | |
| diagnosis: %Diagnosis{id: 1111}, | |
| text: "Consider the following..." | |
| } | |
| x when x < 18 -> | |
| %Guidance{ | |
| diagnosis: %Diagnosis{id: 2222}, | |
| text: "Consider the following..." | |
| } | |
| _ -> | |
| nil | |
| end | |
| end | |
| => {:case, [], | |
| [{{:., [], | |
| [{:var!, [context: Elixir, import: Kernel], [{:patient, [], Elixir}]}, | |
| :bmi]}, [], []}, | |
| [do: [{:->, [], | |
| [[{:when, [], | |
| [{:x, [], Elixir}, | |
| {:>=, [context: Elixir, import: Kernel], [{:x, [], Elixir}, 40]}]}], | |
| {:%, [], | |
| [{:__aliases__, [alias: false], [:Guidance]}, | |
| {:%{}, [], | |
| [diagnosis: {:%, [], | |
| [{:__aliases__, [alias: false], [:Diagnosis]}, | |
| {:%{}, [], [id: 1111]}]}, text: "Consider the following..."]}]}]}, | |
| {:->, [], | |
| [[{:when, [], | |
| [{:x, [], Elixir}, | |
| {:<, [context: Elixir, import: Kernel], [{:x, [], Elixir}, 18]}]}], | |
| {:%, [], | |
| [{:__aliases__, [alias: false], [:Guidance]}, | |
| {:%{}, [], | |
| [diagnosis: {:%, [], | |
| [{:__aliases__, [alias: false], [:Diagnosis]}, | |
| {:%{}, [], [id: 2222]}]}, text: "Consider the following..."]}]}]}, | |
| {:->, [], [[{:_, [], Elixir}], nil]}]]]} | |
| </code></pre> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;">This structure's a bit complicated for us to get started with, so let's not start there exactly. How about this:</p> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 16px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; background-color: rgb(247, 247, 247);"> | |
| <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0px; margin: 0px; border-radius: 3px; word-break: normal; white-space: pre; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;">iex(4)> quote do | |
| ...(4)> if var!(bmi) > 40 do | |
| ...(4)> true | |
| ...(4)> else | |
| ...(4)> false | |
| ...(4)> end | |
| ...(4)> end | |
| {:if, [context: Elixir, import: Kernel], | |
| [{:>, [context: Elixir, import: Kernel], | |
| [{:var!, [context: Elixir, import: Kernel], [{:bmi, [], Elixir}]}, 40]}, | |
| [do: true, else: false]]} | |
| </code></pre> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;">That is a bit simpler. Now we're going to build something we'll call a Transformer, that will transform a custom AST we design into quoted Elixir.</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| vim <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">test</span>/transformer_test.exs</pre> | |
| </div> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">TransformerTest</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">use</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ExUnit</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Case</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # So we'll define a simple representation of a program we'd like to be able to</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # compile to elixir. This is very similar to the underlying Elixir AST at</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # present, but at least it's something custom.</span> | |
| <span class="pl-smi" style="box-sizing: border-box;">@ast</span> {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:if</span>, { | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:></span>, | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:var</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:bmi</span>}, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">40</span> | |
| }, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">true</span>, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">false</span> | |
| } | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # And here's the elixir we want this to compile to.</span> | |
| <span class="pl-smi" style="box-sizing: border-box;">@elixir_ast</span> {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:if</span>, [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">context:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Elixir</span>, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">import</span>: <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Kernel</span>], | |
| [{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:></span>, [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">context:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Elixir</span>, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">import</span>: <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Kernel</span>], | |
| [ | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:var!</span>, [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">context:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Elixir</span>, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">import</span>: <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Kernel</span>], | |
| [{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:bmi</span>, [], <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Elixir</span>}] | |
| }, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">40</span> | |
| ] | |
| }, | |
| [<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span>: <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">true</span>, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">else</span>: <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">false</span>]]} | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Now we'll write a test that confirms that our transformer can generate an</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Elixir AST from our custom AST</span> | |
| test <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>we can compile our AST into the Elixir AST<span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| compiled <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-smi" style="box-sizing: border-box;">@ast</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Transformer</span>.generate_elixir | |
| assert compiled <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">==</span> <span class="pl-smi" style="box-sizing: border-box;">@elixir_ast</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;">We can run the tests, but of course they fail because there's no <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">Transformer</code> module. We'll define it at the top of the test here.</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">Transformer</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> generate_elixir(ast) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:nope</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;">Run the tests, and we get a useful error message. Next, let's just hardcode the first part of the AST as a response.</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">Transformer</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> generate_elixir(ast) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:if</span>, [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">context:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Elixir</span>, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">import</span>: <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Kernel</span>], <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:some_condition</span>, [<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span>: <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">true</span>, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">else</span>: <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">false</span>]} | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;">Now we can run the tests, and we're looking a little bit closer. Let's pattern match this function against our<code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">if</code> AST:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">Transformer</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> generate_elixir({<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:if</span>, condition, first, second}) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:if</span>, [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">context:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Elixir</span>, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">import</span>: <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Kernel</span>], condition, [<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span>: first, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">else</span>: second]} | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;">So here we can extract our condition, our first, and our second. We'll run the tests:</p> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 16px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; background-color: rgb(247, 247, 247);"> | |
| <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0px; margin: 0px; border-radius: 3px; word-break: normal; white-space: pre; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;"> 1) test we can compile our AST into the Elixir AST (TransformerTest) | |
| test/transformer_test.exs:36 | |
| Assertion with == failed | |
| code: compiled == @elixir_ast | |
| lhs: {:if, [context: Elixir, import: Kernel], {:>, {:var, :bmi}, 40}, [do: true, else: false]} | |
| rhs: {:if, [context: Elixir, import: Kernel], [{:>, [context: Elixir, import: Kernel], [{:var!, [context: Elixir, import: Kernel], [{:bmi, [], Elixir}]}, 40]}, [do: true, else: false]]} | |
| stacktrace: | |
| test/transformer_test.exs:38 | |
| </code></pre> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;">OK, so now we'll just wrap each of our values with a call to <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">generate_elixir</code> as well:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">Transformer</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> generate_elixir({<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:if</span>, condition, first, second}) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:if</span>, [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">context:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Elixir</span>, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">import</span>: <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Kernel</span>], | |
| generate_elixir(condition), | |
| [<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span>: generate_elixir(first), <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">else</span>: generate_elixir(second)]} | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;">Now if we run the tests, they'll tell us that we don't know how to generate the Elixir ASTs for our var statement, greater than, true or false. Let's define placeholders for each of those:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">Transformer</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> generate_elixir({<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:if</span>, condition, first, second}) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:if</span>, [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">context:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Elixir</span>, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">import</span>: <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Kernel</span>], | |
| generate_elixir(condition), | |
| [<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span>: generate_elixir(first), <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">else</span>: generate_elixir(second)]} | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # true and false are easy enough</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> generate_elixir(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">true</span>), <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span>: <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">true</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> generate_elixir(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">false</span>), <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span>: <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">false</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # We can see from the @elixir_ast what our var tuple should turn into</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> generate_elixir({<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:var</span>, var_name}) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:var!</span>, [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">context:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Elixir</span>, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">import</span>: <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Kernel</span>], [{var_name, [], <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Elixir</span>}]} | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # similarly we can see what our greater than comparison should turn into</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> generate_elixir({<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:></span>, first, second}) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:></span>, [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">context:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Elixir</span>, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">import</span>: <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Kernel</span>], [generate_elixir(first), generate_elixir(second)]} | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # And our '40' needs to be handled as well</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> generate_elixir(x) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">when</span> is_integer(x), <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span>: x | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;">If we run the tests now we can see that we goofed up on the if statement a little bit - we should wrap the third element of the tuple in a list, since it's the arguments list for the <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">if</code>:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> generate_elixir({<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:if</span>, condition, first, second}) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:if</span>, [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">context:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Elixir</span>, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">import</span>: <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Kernel</span>], | |
| [ | |
| generate_elixir(condition), | |
| [<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span>: generate_elixir(first), <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">else</span>: generate_elixir(second)] | |
| ] | |
| } | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;">OK, run the tests now, and they pass. So we've built a custom AST that we can compile into Elixir quoteds. From here, it's easy to actually compile this and test it, so let's do that. First, let's extract the transformer to its own module.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;">((( do it )))</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;">Next, we'll add a new test for a compiler. It will just take an Elixir AST and turn it into a function we can call.</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| vim <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">test</span>/compiler_test.exs</pre> | |
| </div> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">CompilerTest</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">use</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ExUnit</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Case</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # We'll copy over the same AST we used in the transformer test</span> | |
| <span class="pl-smi" style="box-sizing: border-box;">@ast</span> {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:if</span>, { | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:></span>, | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:var</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:bmi</span>}, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">40</span> | |
| }, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">true</span>, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">false</span> | |
| } | |
| <span class="pl-smi" style="box-sizing: border-box;">@input</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">41</span> | |
| <span class="pl-smi" style="box-sizing: border-box;">@bad_input</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">40</span> | |
| test <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>we can evaluate some AST<span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| compiled <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-smi" style="box-sizing: border-box;">@ast</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Compiler</span>.compile | |
| assert compiled.(<span class="pl-smi" style="box-sizing: border-box;">@input</span>) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">==</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">true</span> | |
| assert compiled.(<span class="pl-smi" style="box-sizing: border-box;">@bad_input</span>) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">==</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">false</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;">We can run the tests, and we know the compiler module doesn't exist. Let's add it at the top.</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">Compiler</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> compile(ast) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # We just generate the elixir AST</span> | |
| quoted <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Transformer</span>.generate_elixir(ast) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">fn</span>(input) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # We'll put the input into the environment for the quoted function as the</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # 'bmi' variable, then return the result of the evaluation, in the</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # function that we return.</span> | |
| {val, _binding} <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Code</span>.eval_quoted(quoted, [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">bmi:</span> input]) | |
| val | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;">Go ahead and run the tests, and they pass.</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Summary</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;">In today's episode, we built a custom AST and a module to transform it into elixir quoted form, followed by a compiler that compiled that quoted form into an anonymous function that we could call. I hope you enjoyed it - metaprogramming in Elixir feels so awesome to me. See you soon!</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Resources</h2> | |
| <ul style="box-sizing: border-box; padding-right: 0px; padding-left: 2em; margin-top: 0px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px; margin-bottom: 0px !important;"> | |
| <li style="box-sizing: border-box;"><a href="http://github.com/knewter/rules_engine" style="box-sizing: border-box; color: rgb(64, 120, 192); text-decoration: none; background-color: transparent;"><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">knewter/rules_engine</code></a></li> | |
| </ul> | |
| </div> | |
| <h3>Attached Files</h3> | |
| <ul> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=57466">187_Compiling_a_Custom_AST_Into_Elixir_Functions.markdown</a></li> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=57467">187_Compiling_a_Custom_AST_Into_Elixir_Functions.mp4</a></li> | |
| </ul></div>]]></description> | |
| <guid isPermaLink="false">dpd-c83ac55d587a5a1bd73373be1f02ad315cb1fc0c</guid> | |
| <pubDate>Sat, 22 Aug 2015 12:23:00 -0400</pubDate> | |
| <enclosure url="https://elixirsips.dpdcart.com/feed/download/57467/187_Compiling_a_Custom_AST_Into_Elixir_Functions.mp4" length="48819193" type="video/mp4"/> | |
| </item> | |
| <item> | |
| <title><![CDATA[186 - Automatically Connecting Nodes]]></title> | |
| <link>https://elixirsips.dpdcart.com/subscriber/post?id=892</link> | |
| <description><![CDATA[<div class="blog-entry"> | |
| <div class="blog-content"><h1 style="box-sizing: border-box; font-size: 2.25em; margin-right: 0px; margin-bottom: 16px; margin-left: 0px; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; margin-top: 0px !important;">Episode 186: Automatically Connecting Nodes</h1> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">In Episode 045, we connected a couple of nodes together manually. But what if you want to have them automatically connect to each other? Surpise, I'm going to show you how to do it. Let's get started.</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Project</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">I'm going to use the ElixirFriends project for this, so you can also see that Phoenix takes advantage of distribution to make channels work across nodes. We're going to run 2 nodes, only one of which is running the phoenix server, and only one of which is looking for new tweets.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">First, we'll make a <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">sys.config</code> file. This is an erlang configuration file that you can use to pass configuration options to the VM.</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| vim sys.config</pre> | |
| </div> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| [{kernel, | |
| [ | |
| {sync_nodes_optional, [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);"><span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">'</span>[email protected]<span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">'</span></span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);"><span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">'</span>[email protected]<span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">'</span></span>]}, | |
| {sync_nodes_timeout, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">150000</span>} | |
| ]} | |
| ].</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">So this tells the VM to try to connect to that list of nodes, and to continue booting in 150 seconds if it can't connect to them.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Now let's boot up the app but we won't start the phoenix endpoint on this one:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| iex --cookie secret --name [email protected] --erl <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>-config sys.config<span class="pl-pds" style="box-sizing: border-box;">"</span></span> -S mix</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Remember that we had to set a cookie so that the nodes could see one another. Alright, before we start the second node, we're going to modify the app so that it doesn't start the tweet streamer:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| vim lib/elixir_friends.ex</pre> | |
| </div> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> #worker(Task, [fn -> ElixirFriends.ImageTweetStreamer.stream(@term) |> Enum.to_list end])</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Right, now we'll start the phoenix app.</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| iex --cookie secret --name [email protected] --erl <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>-config sys.config<span class="pl-pds" style="box-sizing: border-box;">"</span></span> -S mix phoenix.server</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">OK, so let's visit it at port 4000 and then look at the console from the first node.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">((( do it )))</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">((( wait for a nintendo post to get put into the database )))</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Alright, and there we have it, proof that phoenix channels will take advantage of erlang distribution out of the box. See you soon!</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Resources</h2> | |
| <ul style="box-sizing: border-box; padding-right: 0px; padding-left: 2em; margin-top: 0px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; margin-bottom: 0px !important;"> | |
| <li style="box-sizing: border-box;"><a href="https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!msg/elixir-lang-talk/VLN2l3AKPxA/qWKH_8XZAgAJ" style="box-sizing: border-box; color: rgb(64, 120, 192); text-decoration: none; background-color: transparent;">The mailing list post where I learned this</a></li> | |
| </ul> | |
| </div> | |
| <h3>Attached Files</h3> | |
| <ul> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=57291">186_Automatically_Connecting_Nodes.mp4</a></li> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=57292">186_Automatically_Connecting_Nodes.markdown</a></li> | |
| </ul></div>]]></description> | |
| <guid isPermaLink="false">dpd-9385ab631fa6147ddb16c4b4839d09a043f85d1f</guid> | |
| <pubDate>Tue, 18 Aug 2015 19:22:00 -0400</pubDate> | |
| <enclosure url="https://elixirsips.dpdcart.com/feed/download/57291/186_Automatically_Connecting_Nodes.mp4" length="30582896" type="video/mp4"/> | |
| </item> | |
| <item> | |
| <title><![CDATA[185 - Mix Archives]]></title> | |
| <link>https://elixirsips.dpdcart.com/subscriber/post?id=881</link> | |
| <description><![CDATA[<div class="blog-entry"> | |
| <div class="blog-content"><h1 style="box-sizing: border-box; font-size: 2.25em; margin-right: 0px; margin-bottom: 16px; margin-left: 0px; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; margin-top: 0px !important;">Episode 185: Mix Archives</h1> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Erlang defines something called the Erlang Archive Format. There's a mix task that knows how to build an application into one of these archives. Let's learn a little bit about it.</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Project</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">We built a custom mix task that just upcases the input in Episode 059. In this episode we'll build that into an archive and then examine it a bit.</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">cd</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">~</span>/elixir/custom_mix</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">OK, so let's review this project. It adds a mix task in <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">lib/scream.ex</code></p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">Mix.Tasks.Scream</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">use</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Mix</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Task</span> | |
| <span class="pl-smi" style="box-sizing: border-box;">@shortdoc</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>Scream the input<span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">@moduledoc """</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> Given a particular input, scream it.</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> """</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> run(args) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| { _opts, args, _ } <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">OptionParser</span>.parse(args) | |
| string <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Enum</span>.join(args, <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span> <span class="pl-pds" style="box-sizing: border-box;">"</span></span>) | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Mix</span>.shell.info(string <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">String</span>.upcase) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">We can run it with <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">mix scream foo</code></p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">If we go out of this project, that mix task is not available to us:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">cd</span> .. | |
| mix scream foo | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">cd</span> custom_mix</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">So what if we want this task to be available all the time? We can install it as a local archive. The archive format is not only useful for mix tasks, but it is how persistent mix tasks can be added to your system. Mix comes with a way to build an application into an archive:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| mix archive.build</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">This just generates a .ez file. Before we move on, let's look at this file. It's just a zip file, so you can unzip it:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| unzip custom_mix-0.0.1.ez | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">cd</span> custom_mix-0.0.1 | |
| tree | |
| vim ebin/custom_mix.app</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">So this is just a directory with our beam files in it and an app file. The names of the .ez file and the parent directory have to match, but mix takes care of that for us. So a mix archive is really just an erlang application, bundled in a zip.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Let's go ahead and install this archive locally.</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| rm -fr custom_mix-0.0.1 | |
| mix archive.install</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Now we can run this mix task from anywhere.</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">cd</span> .. | |
| mix scream foo</pre> | |
| </div> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Summary</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">In this episode, we saw how to build a mix archive and install it, and we explored what an Erlang Archive really is. There's a bit more to them, inasmuch as you can also embed an Erlang Archive directly into an escript file, but that's it for today. See you soon!</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Resources</h2> | |
| <ul style="box-sizing: border-box; padding-right: 0px; padding-left: 2em; margin-top: 0px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; margin-bottom: 0px !important;"> | |
| <li style="box-sizing: border-box;"><a href="http://www.erlang.org/doc/man/code.html" style="box-sizing: border-box; color: rgb(64, 120, 192); text-decoration: none; background-color: transparent;">Erlang Archive Format</a> - The Erlang Archive Format is discussed in the <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">code</code> module documentation.</li> | |
| <li style="box-sizing: border-box;"><a href="http://elixir-lang.org/docs/master/mix/Mix.Tasks.Archive.Build.html" style="box-sizing: border-box; color: rgb(64, 120, 192); text-decoration: none; background-color: transparent;">Mix.Tasks.Archive.Build Documentation</a> - Docs for the module responsible for <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">mix archive.build</code></li> | |
| <li style="box-sizing: border-box;"><a href="https://github.com/phoenixframework/phoenix/tree/master/installer" style="box-sizing: border-box; color: rgb(64, 120, 192); text-decoration: none; background-color: transparent;">Here's the phoenix installer archive application</a></li> | |
| </ul> | |
| </div> | |
| <h3>Attached Files</h3> | |
| <ul> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=57000">185_Mix_Archives.mp4</a></li> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=57001">185_Mix_Archives.markdown</a></li> | |
| </ul></div>]]></description> | |
| <guid isPermaLink="false">dpd-ee6e4eadcf88ba5b6db52f0228c9a099166ac6f8</guid> | |
| <pubDate>Thu, 13 Aug 2015 19:17:00 -0400</pubDate> | |
| <enclosure url="https://elixirsips.dpdcart.com/feed/download/57000/185_Mix_Archives.mp4" length="9201491" type="video/mp4"/> | |
| </item> | |
| <item> | |
| <title><![CDATA[184 - React with Phoenix Channels]]></title> | |
| <link>https://elixirsips.dpdcart.com/subscriber/post?id=878</link> | |
| <description><![CDATA[<div class="blog-entry"> | |
| <div class="blog-content"><h1 style="box-sizing: border-box; font-size: 2.25em; margin-right: 0px; margin-bottom: 16px; margin-left: 0px; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; margin-top: 0px !important;">Episode 184: React with Phoenix Channels</h1> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">In the last episode we added react to render the posts in the ElixirFriends application. In this episode we're going to push new posts to the frontend using Phoenix channels. Let's get started.</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Project</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Since the last episode, I upgraded most of the dependencies to the latest version. This includes all the phoenix and ecto dependencies as well. I also modified our brunch configuration to fetch the phoenix javascript dependency from the phoenix dependency, so we no longer need to bring updates in manually.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">((( show the updated brunch config )))</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">However, we do need to remove our vendored phoenix.js so it doesn't confuse us.</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| git rm web/static/vendor/phoenix.js</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Now let's go ahead and add a channel that new posts will be published to. This has changed as well in recent Phoenix releases. Now instead of putting the channel into the router, we define our own socket module and connect the socket to it in our endpoint.</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| vim web/channels/user_socket.ex</pre> | |
| </div> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">ElixirFriends.UserSocket</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">use</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Phoenix</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Socket</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # We'll be creating a PostsChannel to handle our post updates</span> | |
| channel <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>posts:*<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ElixirFriends</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">PostsChannel</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Here's the rest of the boilerplate that sockets need.</span> | |
| transport <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:websocket</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Phoenix</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Transports</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">WebSocket</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> connect(_params, socket) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:ok</span>, socket} | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> id(_socket), <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span>: <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">nil</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Now let's wire it up in our endpoint:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">ElixirFriends.Endpoint</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">use</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Phoenix</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Endpoint</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">otp_app:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:elixir_friends</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> #...</span> | |
| socket <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>/socket<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ElixirFriends</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">UserSocket</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Next we just need to implement the PostsChannel.</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| vim web/channels/posts_channel.ex</pre> | |
| </div> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">ElixirFriends.PostsChannel</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">use</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Phoenix</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Channel</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> join(<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>posts:new<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, _auth_msg, socket) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:ok</span>, socket} | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">So our frontend will subscribe to the <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">posts:new</code> topic, and we'll publish new posts to it when they get created. Let's open up the tweet streamer and make it publish new posts to this channel.</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">ElixirFriends.ImageTweetStreamer</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> #...</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defp</span> store_tweet(%<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ExTwitter</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Model</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Tweet</span>{}<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span>tweet) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> #...</span> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ElixirFriends</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Repo</span>.insert(post) | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Phoenix has changed a little bit since I last used it here. Now you just</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # broadcast a message to a topic</span> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ElixirFriends</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Endpoint</span>.broadcast! <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>posts:new<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>new:post<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, post | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> #...</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">OK, so now new tweets will be broadcast on our <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">posts:new</code> topic as a <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">new:post</code> event. Now let's open up the frontend and make our react application subscribe to these messages and shove them into the state when new posts occur:</p> | |
| <div class="highlight highlight-javascript" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">let</span> PostList <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> React.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">createClass</span>({ | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">//...</span> | |
| <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">componentDidMount</span>() { | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// Get the new posts, and set our state</span> | |
| $.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">get</span>(<span class="pl-v" style="box-sizing: border-box; color: rgb(237, 106, 67);">this</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">props</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">source</span>, result <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=></span> { | |
| result <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">JSON</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">parse</span>(result) | |
| <span class="pl-v" style="box-sizing: border-box; color: rgb(237, 106, 67);">this</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">setState</span>({ | |
| posts<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">:</span> result.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">entries</span> | |
| }) | |
| }) | |
| <span class="pl-v" style="box-sizing: border-box; color: rgb(237, 106, 67);">this</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">subscribeToNewPosts</span>(); | |
| }, | |
| <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">subscribeToNewPosts</span>() { | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">let</span> socket <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">new</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">Socket</span>(<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>/socket<span class="pl-pds" style="box-sizing: border-box;">"</span></span>) | |
| socket.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">connect</span>() | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">let</span> channel <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> socket.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">channel</span>(<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>posts:new<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, {}) | |
| channel.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">join</span>().<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">receive</span>(<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>ok<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, chan <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=></span> { | |
| <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">console</span><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">.log</span>(<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>joined<span class="pl-pds" style="box-sizing: border-box;">"</span></span>) | |
| }) | |
| channel.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">on</span>(<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>new:post<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, post <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=></span> { | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// For now we'll just log the posts to make sure we're getting them in the</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// frontend</span> | |
| <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">console</span><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">.log</span>(post) | |
| }) | |
| },</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Now let's open it in the browser and look at the posts coming in. We'll also want to change the configuration to search for something with more traffic on it. "nintendo" is my go to here.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">((( do it )))</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">OK, so we can see the posts coming in now. The only thing left to do is to shove them into our application state as they arrive. Let's do that:</p> | |
| <div class="highlight highlight-javascript" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">subscribeToNewPosts</span>() { | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">//...</span> | |
| channel.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">on</span>(<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>new:post<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, post <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=></span> { | |
| <span class="pl-v" style="box-sizing: border-box; color: rgb(237, 106, 67);">this</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">injectNewPost</span>(post) | |
| }) | |
| }, | |
| <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">injectNewPost</span>(<span class="pl-smi" style="box-sizing: border-box;">post</span>) { | |
| <span class="pl-v" style="box-sizing: border-box; color: rgb(237, 106, 67);">this</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">setState</span>({ | |
| posts<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">:</span> [post].<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">concat</span>(<span class="pl-v" style="box-sizing: border-box; color: rgb(237, 106, 67);">this</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">state</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">posts</span>) | |
| }) | |
| },</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">With that, we'll just push the new post into the front of the current list of posts in the React state. Let's open up the browser and check it out.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">((( do it )))</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Summary</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">And it works! In today's episode, we added realtime updates to elixirfriends using Phoenix's channels. See you soon!</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Resources</h2> | |
| <ul style="box-sizing: border-box; padding-right: 0px; padding-left: 2em; margin-top: 0px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; margin-bottom: 0px !important;"> | |
| <li style="box-sizing: border-box;"><a href="http://www.phoenixframework.org/docs/channels" style="box-sizing: border-box; color: rgb(64, 120, 192); text-decoration: none; background-color: transparent;">Phoenix Channel Guides</a></li> | |
| </ul> | |
| </div> | |
| <h3>Attached Files</h3> | |
| <ul> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=56891">184_React_Phoenix_Channels.mp4</a></li> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=56892">184_React_Phoenix_Channels.markdown</a></li> | |
| </ul></div>]]></description> | |
| <guid isPermaLink="false">dpd-31d7d9944e3b5c56bc257fc5746a50cfaca1bc00</guid> | |
| <pubDate>Wed, 12 Aug 2015 01:02:00 -0400</pubDate> | |
| <enclosure url="https://elixirsips.dpdcart.com/feed/download/56891/184_React_Phoenix_Channels.mp4" length="48482818" type="video/mp4"/> | |
| </item> | |
| <item> | |
| <title><![CDATA[183 - React with Phoenix]]></title> | |
| <link>https://elixirsips.dpdcart.com/subscriber/post?id=872</link> | |
| <description><![CDATA[<div class="blog-entry"> | |
| <div class="blog-content"><h1 style="box-sizing: border-box; font-size: 2.25em; margin-right: 0px; margin-bottom: 16px; margin-left: 0px; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; margin-top: 0px !important;">Episode 183: React with Phoenix</h1> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">React is a pretty nice JavaScript library from Facebook that makes it easy to build complex User Interfaces that are easy to reason about. Today we'll integrate it with our ElixirFriends application. Let's get started.</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Project</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">First, we'll just install react with Bower. By default, Brunch will include your bower dependencies in your application automatically, so this is all we have to do to include React.</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| bower init | |
| bower install react --save</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Now we'll restart the webserver and open up the app.js file to introduce our first React component:</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">((( restart )))</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| vim web/static/js/app.js</pre> | |
| </div> | |
| <div class="highlight highlight-javascript" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// We'll make a new React component</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">let</span> PostList <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> React.createClass({ | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// Here we're using the ES6 notation for defining a function property called</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// render</span> | |
| <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">render</span>() { | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// And React uses something called JSX, which if you haven't seen it before</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// looks extremely weird - you include html that's not in a string,</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// basically, and there's a precompiler parser that handles making it into</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// javascript for you. Brunch supports jsx out of the box if you have a</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// file ending in .js</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">return</span>(<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"><</span>p<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span>The app goes here...<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"><</span>/p<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span>) | |
| } | |
| }) | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// Then onload we'll just render the PostList on our app element. This isn't</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// ideal - we should have a function we call in that template to start it,</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// really...but it gets us going.</span> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">window</span>.onload <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> ()<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"> =></span> { | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">var</span> element <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">document</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">getElementById</span>(<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>app<span class="pl-pds" style="box-sizing: border-box;">"</span></span>) | |
| React.render(<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"><</span>PostList /<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span>, element) | |
| }</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Next, we'll just replace the entire index template with a div with id "app". We'll actually not replace it all quite yet, so I can crib the html from it later on.</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| vim web/templates/post/index.html.eex</pre> | |
| </div> | |
| <div class="highlight highlight-html" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">div</span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">id</span>=<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>app<span class="pl-pds" style="box-sizing: border-box;">"</span></span>></<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">div</span>></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">We can open the app, and it should work. So this is all it takes to get react working in your Phoenix application. The next step is to start to mock out what we want the React application to actually do. For this, we'll have a root component, the PostList, and a component for each Post. First, we'll define the Post:</p> | |
| <div class="highlight highlight-javascript" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// Here, we'll just make a new react class, copy in the template, and</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// replace the values with jsx interpolation. Also, every reference to `class`</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// should now be `className` - you can read the docs linked in the resources</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// section for more on the JSX API.</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">let</span> Post <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> React.createClass({ | |
| <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">render</span>() { | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">return</span>( | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"><</span>div className<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span><span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>four wide column<span class="pl-pds" style="box-sizing: border-box;">"</span></span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"><</span>div className<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span><span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>ui card<span class="pl-pds" style="box-sizing: border-box;">"</span></span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"><</span>div className<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span><span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>image<span class="pl-pds" style="box-sizing: border-box;">"</span></span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"><</span>img src<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span>{<span class="pl-v" style="box-sizing: border-box; color: rgb(237, 106, 67);">this</span>.props.imageUrl} /<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"><</span>/div<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"><</span>div className<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span><span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>content<span class="pl-pds" style="box-sizing: border-box;">"</span></span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"><</span>div className<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span><span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>header<span class="pl-pds" style="box-sizing: border-box;">"</span></span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| {<span class="pl-v" style="box-sizing: border-box; color: rgb(237, 106, 67);">this</span>.props.username} | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"><</span>/div<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"><</span>div className<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span><span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>meta<span class="pl-pds" style="box-sizing: border-box;">"</span></span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"><</span>span className<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span><span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>date<span class="pl-pds" style="box-sizing: border-box;">"</span></span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span>{<span class="pl-v" style="box-sizing: border-box; color: rgb(237, 106, 67);">this</span>.props.insertedAt}<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"><</span>/span<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"><</span>/div<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"><</span>div className<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span><span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>description<span class="pl-pds" style="box-sizing: border-box;">"</span></span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| {<span class="pl-v" style="box-sizing: border-box; color: rgb(237, 106, 67);">this</span>.props.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">content</span>} | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"><</span>/div<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"><</span>/div<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"><</span>/div<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"><</span>/div<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| ) | |
| } | |
| })</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Next, we'll modify the PostList component a bit. It will have a list of posts as its state, and we'll hardcode a mock post inside the list to give it something to render. This goes into the<code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">getInitialState</code> function in the React lifecycle.</p> | |
| <div class="highlight highlight-javascript" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">let</span> PostList <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> React.createClass({ | |
| <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">getInitialState</span>() { | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">return</span> { | |
| posts<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">:</span> [ | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// Here we'll mock what our API returns for a post</span> | |
| { | |
| image_url<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">:</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">'</span>http://placekitten.com/g/200/300<span class="pl-pds" style="box-sizing: border-box;">'</span></span>, | |
| username<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">:</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">'</span>knewter<span class="pl-pds" style="box-sizing: border-box;">'</span></span>, | |
| inserted_at<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">:</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">'</span>July 25, 2015<span class="pl-pds" style="box-sizing: border-box;">'</span></span>, | |
| content<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">:</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">'</span>zomg a kitty<span class="pl-pds" style="box-sizing: border-box;">'</span></span> | |
| } | |
| ] | |
| } | |
| }, | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// Next, we'll just render each post by mapping it to a Post component,</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// explicitly passing the values in</span> | |
| <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">render</span>() { | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">return</span>( | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"><</span>div className<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span><span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>ui grid stackable<span class="pl-pds" style="box-sizing: border-box;">"</span></span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| {<span class="pl-v" style="box-sizing: border-box; color: rgb(237, 106, 67);">this</span>.state.posts.map(<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">function</span>(<span class="pl-smi" style="box-sizing: border-box;">post</span>) { | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">return</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"><</span>Post imageUrl<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span>{post.image_url} username<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span>{post.username} insertedAt<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span>{post.inserted_at} content<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span>{post.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">content</span>} /<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| })} | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"><</span>/div<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| ) | |
| } | |
| })</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Now let's set the state when the component mounts - this is what we'll do when we perform our API call, but for now we're just going to explicitly set the state:</p> | |
| <div class="highlight highlight-javascript" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">let</span> PostList <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> React.createClass({ | |
| <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">getInitialState</span>() { | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">return</span> { | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// So now we start out with a shell of our state, with no posts...</span> | |
| posts<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">:</span> [] | |
| } | |
| }, | |
| <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">componentDidMount</span>() { | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// And when our component is mounted on the page, we set its state to our</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// mock values. This gets us a good place to put our API call in the next</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// iteration.</span> | |
| <span class="pl-v" style="box-sizing: border-box; color: rgb(237, 106, 67);">this</span>.setState({ | |
| posts<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">:</span> [ | |
| { | |
| imageUrl<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">:</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">'</span>http://placekitten.com/g/200/300<span class="pl-pds" style="box-sizing: border-box;">'</span></span>, | |
| username<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">:</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">'</span>knewter<span class="pl-pds" style="box-sizing: border-box;">'</span></span>, | |
| insertedAt<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">:</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">'</span>July 25, 2015<span class="pl-pds" style="box-sizing: border-box;">'</span></span>, | |
| content<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">:</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">'</span>zomg a kitty<span class="pl-pds" style="box-sizing: border-box;">'</span></span> | |
| } | |
| ] | |
| }) | |
| }, | |
| <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">render</span>() { | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">return</span>( | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"><</span>div className<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span><span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>ui grid stackable<span class="pl-pds" style="box-sizing: border-box;">"</span></span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| {<span class="pl-v" style="box-sizing: border-box; color: rgb(237, 106, 67);">this</span>.state.posts.map(<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">function</span>(<span class="pl-smi" style="box-sizing: border-box;">post</span>) { | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">return</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"><</span>Post imageUrl<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span>{post.image_url} username<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span>{post.username} insertedAt<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span>{post.inserted_at} content<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span>{post.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">content</span>} /<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| })} | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"><</span>/div<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| ) | |
| } | |
| })</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Alright, so this works. Now if we just ask for the list of posts from the API and show that, that should work as well. Let's try it:</p> | |
| <div class="highlight highlight-javascript" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">let</span> PostList <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> React.createClass({ | |
| <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">getInitialState</span>() { | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">return</span> { | |
| posts<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">:</span> [] | |
| } | |
| }, | |
| <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">componentDidMount</span>() { | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// We'll use jquery to get the result. We'll also modify the bottom of our</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// file so that we can specify the API endpoint when inserting our component</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// with the `source` property</span> | |
| $.get(<span class="pl-v" style="box-sizing: border-box; color: rgb(237, 106, 67);">this</span>.props.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">source</span>, result <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=></span> { | |
| result <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">JSON</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">parse</span>(result) <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// No idea why this is necessary here...</span> | |
| <span class="pl-v" style="box-sizing: border-box; color: rgb(237, 106, 67);">this</span>.setState({posts<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">:</span> result.entries}) | |
| }) | |
| }, | |
| <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">render</span>() { | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">return</span>( | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"><</span>div className<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span><span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>ui grid stackable<span class="pl-pds" style="box-sizing: border-box;">"</span></span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| {<span class="pl-v" style="box-sizing: border-box; color: rgb(237, 106, 67);">this</span>.state.posts.map(<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">function</span>(<span class="pl-smi" style="box-sizing: border-box;">post</span>) { | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">return</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"><</span>Post imageUrl<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span>{post.image_url} username<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span>{post.username} insertedAt<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span>{post.inserted_at} content<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span>{post.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">content</span>} /<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| })} | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"><</span>/div<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| ) | |
| } | |
| }) | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">window</span>.onload <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> ()<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"> =></span> { | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">var</span> element <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">document</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">getElementById</span>(<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>app<span class="pl-pds" style="box-sizing: border-box;">"</span></span>) | |
| React.render(<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"><</span>PostList source<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span><span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>/api/posts<span class="pl-pds" style="box-sizing: border-box;">"</span></span>/<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span>, element) | |
| }</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Go ahead and refresh the page - and it's working.</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Summary</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">In today's episode, we bootstrapped a React application that talks to our API to fetch the posts and rendered them with JavaScript. Of course, this doesn't include pagination. We should add that, but let's not do too much today. Also, talking through pagination logic again would make for an extremely boring episode for you viewers, I would think. See you soon!</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Resources</h2> | |
| <ul style="box-sizing: border-box; padding-right: 0px; padding-left: 2em; margin-top: 0px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; margin-bottom: 0px !important;"> | |
| <li style="box-sizing: border-box;"><a href="http://facebook.github.io/react/" style="box-sizing: border-box; color: rgb(64, 120, 192); text-decoration: none; background-color: transparent;">React</a></li> | |
| <li style="box-sizing: border-box;"><a href="http://www.jonathanbirkholz.com/add-react-to-your-phoenix-app/" style="box-sizing: border-box; color: rgb(64, 120, 192); text-decoration: none; background-color: transparent;">Jonathan Birkholz on using React with Phoenix</a></li> | |
| <li style="box-sizing: border-box;"><a href="https://facebook.github.io/react/docs/jsx-in-depth.html" style="box-sizing: border-box; color: rgb(64, 120, 192); text-decoration: none; background-color: transparent;">JSX in Depth</a></li> | |
| </ul> | |
| </div> | |
| <h3>Attached Files</h3> | |
| <ul> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=56770">183_React_with_Phoenix.mp4</a></li> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=56771">183_React_with_Phoenix.markdown</a></li> | |
| </ul></div>]]></description> | |
| <guid isPermaLink="false">dpd-9eb2bad9c64bdf62382ea83895ec7c0cdf39e797</guid> | |
| <pubDate>Sun, 09 Aug 2015 16:01:00 -0400</pubDate> | |
| <enclosure url="https://elixirsips.dpdcart.com/feed/download/56770/183_React_with_Phoenix.mp4" length="48293841" type="video/mp4"/> | |
| </item> | |
| <item> | |
| <title><![CDATA[182 - Phoenix API]]></title> | |
| <link>https://elixirsips.dpdcart.com/subscriber/post?id=867</link> | |
| <description><![CDATA[<div class="blog-entry"> | |
| <div class="blog-content"><h1 style="box-sizing: border-box; font-size: 2.25em; margin-right: 0px; margin-bottom: 16px; margin-left: 0px; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; margin-top: 0px !important;">Episode 182: Phoenix API</h1> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Today we're going to add an API to our ElixirFriends application so that we can build a frontend on top of it. Let's get started.</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Project</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">The first thing we're going to do is build a test:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| mkdir <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">test</span>/controllers/api | |
| vim <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">test</span>/controllers/api/post_controller_test.exs</pre> | |
| </div> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">ElixirFriends.API.PostControllerTest</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">use</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ElixirFriends</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ConnCase</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ElixirFriends</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Post</span> | |
| setup <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # We're going to only accept json from the server</span> | |
| conn <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> conn() <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> put_req_header(<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>accept<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>application/json<span class="pl-pds" style="box-sizing: border-box;">"</span></span>) | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:ok</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">conn:</span> conn} | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| test <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>lists all posts<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, %{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">conn:</span> conn} <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # We'll insert a post to get back in our api call</span> | |
| post <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Post</span>{ | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">image_url:</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>http://elixirfriends.com<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">content:</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>this is some content<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">username:</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>knewter<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">source_url:</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>http://elixirfriends.com<span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| } | |
| post <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ElixirFriends</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Repo</span>.insert! | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Now let's get the posts from the API</span> | |
| conn <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> get conn, <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>/api/posts<span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # We'll define what we expect to receive</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Remember we'll have our data wrapped in a scrivener pagination map</span> | |
| expected_response <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> %{ | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">total_pages:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1</span>, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">total_entries:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1</span>, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">page_size:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">20</span>, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">page_number:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1</span>, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">entries:</span> [post] | |
| } <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Poison</span>.encode! | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Now let's assert that we receive what we expected</span> | |
| assert json_response(conn, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">200</span>) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">==</span> expected_response | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">If we go ahead and run the tests, we'll get a 404 because there's no route for this. ((( do it )))</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">We could just use the phoenix generators to build out our json api, but I prefer to do this sort of thing manually to make sure I don't start thinking things are magic. With that said, let's define a controller:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| mkdir web/controllers/api | |
| vim web/controllers/api/post_controller.ex</pre> | |
| </div> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">ElixirFriends.API.PostController</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">use</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ElixirFriends</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Web</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:controller</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">import</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Ecto</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Query</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ElixirFriends</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Post</span> | |
| plug <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:action</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> index(conn, params) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| posts_page <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Post</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> order_by([p], <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">desc:</span> p.inserted_at) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ElixirFriends</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Repo</span>.paginate(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">page:</span> params[<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>page<span class="pl-pds" style="box-sizing: border-box;">"</span></span>]) | |
| render(conn, <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>index.json<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">posts_page:</span> posts_page) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">We could have just returned json directly here, but I'm opting for a view. Let's make the view:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| mkdir web/views/api | |
| vim web/views/api/post_view.ex</pre> | |
| </div> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">ElixirFriends.API.PostView</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">use</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ElixirFriends</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Web</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:view</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> render(<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>index.json<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, %{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">posts_page:</span> posts_page}) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| posts_page | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Poison</span>.encode! | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">With that, we're ready with the exception of our route. Let's add that now:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| vim web/router.ex</pre> | |
| </div> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| scope <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>/api<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ElixirFriends</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| pipe_through <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:api</span> | |
| resources <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>/posts<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">API</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">PostController</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">only:</span> [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:index</span>] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Alright, let's run the test now and see if it works.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">((( do it )))</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">OK, so that almost works. Notice we've got some extra data in our post - both in our expectation, which describes the post as built, and in our response, which describes the post as loaded. We don't want to expose that data. We'll solve it with an implementation of the <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">Poison.Encoder</code> for our <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">Post</code> model.</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| vim web/models/post.ex</pre> | |
| </div> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defimpl</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Poison</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Encoder</span>, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">for</span>: <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ElixirFriends</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Post</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> encode(post, _options) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| post | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Map</span>.from_struct | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Map</span>.delete(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:__meta__</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Poison</span>.encode! | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Now if we run our tests, they'll fail again because our inserted post doesn't have an <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">inserted_at</code>attribute as we didn't load it out of the Repo. However, I'm glad we ran into the other issue so that we could easily see that we were getting that extra metadata in our JSON that we didn't want. Now let's go back to our test and fetch the post from the repo:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| test <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>lists all posts<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, %{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">conn:</span> conn} <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| post <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Post</span>{ | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">image_url:</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>http://elixirfriends.com<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">content:</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>this is some content<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">username:</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>knewter<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">source_url:</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>http://elixirfriends.com<span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| } | |
| inserted_post <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> post <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ElixirFriends</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Repo</span>.insert! | |
| conn <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> get conn, <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>/api/posts<span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| expected_response <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> %{ | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">total_pages:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1</span>, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">total_entries:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1</span>, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">page_size:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">20</span>, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">page_number:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1</span>, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">entries:</span> [inserted_post] | |
| } <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Poison</span>.encode! | |
| assert json_response(conn, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">200</span>) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">==</span> expected_response | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Run the tests, and it works.</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Summary</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Now we can see that our API is giving the expected response. This is the only API function that we care about for our use case, which is going to be rendering the posts with a bit of javascript at page load and as they stream in via a channel later. That's the next episode. See you soon!</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Resources</h2> | |
| <ul style="box-sizing: border-box; padding-right: 0px; padding-left: 2em; margin-top: 0px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; margin-bottom: 0px !important;"> | |
| <li style="box-sizing: border-box;"><a href="http://blog.rokkincat.com/json-views-in-phoenix/" style="box-sizing: border-box; color: rgb(64, 120, 192); text-decoration: none; background-color: transparent;">JSON Views in Phoenix</a> - This article suggests not using the Encode protocol to solve your encoding problems, and instead suggests being more explicit with your JSON views.</li> | |
| <li style="box-sizing: border-box;"><a href="https://github.com/devinus/poison/blob/master/lib/poison/encoder.ex" style="box-sizing: border-box; color: rgb(64, 120, 192); text-decoration: none; background-color: transparent;">Poison.Encoder</a></li> | |
| </ul> | |
| </div> | |
| <h3>Attached Files</h3> | |
| <ul> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=56640">182_Phoenix_API.mp4</a></li> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=56641">182_Phoenix_API.markdown</a></li> | |
| </ul></div>]]></description> | |
| <guid isPermaLink="false">dpd-4ea00b2d6cc1a97b2d720a78e2cd0cecc09c8fad</guid> | |
| <pubDate>Thu, 06 Aug 2015 21:23:00 -0400</pubDate> | |
| <enclosure url="https://elixirsips.dpdcart.com/feed/download/56640/182_Phoenix_API.mp4" length="30761017" type="video/mp4"/> | |
| </item> | |
| <item> | |
| <title><![CDATA[181 - Native Compilation with HiPE]]></title> | |
| <link>https://elixirsips.dpdcart.com/subscriber/post?id=861</link> | |
| <description><![CDATA[<div class="blog-entry"> | |
| <div class="blog-content"><h1 style="box-sizing: border-box; font-size: 2.25em; margin-right: 0px; margin-bottom: 16px; margin-left: 0px; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; margin-top: 0px !important;">Episode 181: Native Compilation with HiPE</h1> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Elixir's greatest strength is Erlang. There's a lot of great research that goes into the BEAM that makes it extremely powerful. One of those research projects was something called HiPE, which has been included in the OTP release for quite a while now.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">HiPE translates BEAM instructions into an assembly-like language, optimizes it, and translates it into machine code. This machine code will obviously be architecture-specific, but it's baked into the existing BEAM files, so that if you compile on x86 and then run your application on ARM, it will still work just fine - it will just fall back to using the existing BEAM code on a different architecture.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">With that introduction out of the way, let's get on to the show.</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Project</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">I'm using the <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">rules_engine</code> project from before. I've tagged it with <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">before_episode_181</code>. Remember we have some benchmarks. I'll go ahead and run those to get a baseline performance number with our BEAM modules:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| mix bench</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">((( make note of the number, put it in a vim buffer for comparison )))</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">So in general, we should expect to have better results if we compile to machine code, right? It's faster to execute code directly on the machine than via a Virtual Machine. Let's try it out and see how much faster it is.</p> | |
| <h3 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.43; font-size: 1.5em; position: relative; font-weight: bold; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Compiling our project using HiPE</h3> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">It's really simple to compile your modules and dependencies with HiPE. Let's do it:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| ERL_COMPILER_OPTIONS=<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>[native,{hipe, [verbose, o3]}]<span class="pl-pds" style="box-sizing: border-box;">"</span></span> mix compile --force</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Now that is just the an example of compiling with HiPE using the o3 optimization level, which is the fanciest. I added the verbose option so you could see the HiPE compiler was working.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Now that we're compiled with HiPE, let's see our performance gains:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| mix bench</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Huh...that's slower. Why would machine code run slower than virtual machine code? Well, for this I had to ask in the #erlang IRC channel, and then I followed it up by reading Kostis' paper on "All you wanted to know about the HiPE compiler (but might have been afraid to ask)". It explains that you should avoid calling BEAM-code functions from native-code functions. This causes two mode switches for the VM, which are relatively expensive. We compiled all our code with HiPE, so what do we think the problem is?</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Well, the biggest problem is Elixir. Not the language, but our current runtime. We're using Elixir features (Structs, other parts of the Standard Library) and those Elixir modules aren't compiled with HiPE. So that explains the lack of performance benefits. So how do we fix this? Obviously, we compile Elixir itself using HiPE.</p> | |
| <h3 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.43; font-size: 1.5em; position: relative; font-weight: bold; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Compiling Elixir using HiPE</h3> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">So let's go ahead and do that.</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">cd</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">~</span>/elixir/elixir</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">I've got the master of Elixir pulled down. I had quite a bit of trouble compiling Elixir using HiPE, until I reached out to Jose on twitter and he helped me out. You actually have to presently compile Elixir itself, then compile it again using HiPE. Let's do that:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| make clean | |
| make compile | |
| touch lib/elixir/lib/kernel.ex | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"># Now we'll compile elixir using HiPE</span> | |
| ERL_COMPILER_OPTIONS=<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>[native,{hipe, [verbose, o2]}]<span class="pl-pds" style="box-sizing: border-box;">"</span></span> make compile | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"># And install it</span> | |
| sudo make install</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">It's also worth pointing out that I wasn't able to compile it using o3. Both of these issues point to bugs in HiPE that I'm not sure were known before, because I've not heard of people having these sorts of problems with it before. At any rate, I'm trying to file a bug for it. In the meantime, let's go see if this helped anyway.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Before we do that though, I want to show you something I learned about how to find out if you have a HiPE-compiled module or not:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| iex</pre> | |
| </div> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Kernel</span>.module_info(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:compile</span>)</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">So here we can see that this module was compiled, with o2. This is pretty cool. Anyway, moving on.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">We'll go back to our project and run the benchmark again:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">cd</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">~</span>/elixir/rules_engine | |
| mix bench</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">And this time it was around 25% faster (if it was like my previous tests). That's pretty good performance increase for a really minimal effort.</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Summary</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">In this episode we learned that the Erlang developer community loves us and wants our code to run faster for free. All hail Kostis! See you soon!</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Resources</h2> | |
| <ul style="box-sizing: border-box; padding-right: 0px; padding-left: 2em; margin-top: 0px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; margin-bottom: 0px !important;"> | |
| <li style="box-sizing: border-box;"><a href="http://erlang.org/doc/man/HiPE_app.html" style="box-sizing: border-box; color: rgb(64, 120, 192); text-decoration: none; background-color: transparent;">HiPE</a> - The HiPE Application manual. Very sparing with information...</li> | |
| <li style="box-sizing: border-box;"><a href="http://www.erlang.org/workshop/2003/paper/p36-sagonas.pdf" style="box-sizing: border-box; color: rgb(64, 120, 192); text-decoration: none; background-color: transparent;">All you wanted to know about the HiPE compiler (but might have been afraid to ask)</a> - this is a paper authored by Kostis Sagonas and the rest of the HiPE team he led at his university.</li> | |
| <li style="box-sizing: border-box;"><a href="http://github.com/knewter/rules_engine" style="box-sizing: border-box; color: rgb(64, 120, 192); text-decoration: none; background-color: transparent;">knewter/rules_engine</a></li> | |
| <li style="box-sizing: border-box;"><a href="https://en.wikipedia.org/wiki/Warren_Abstract_Machine" style="box-sizing: border-box; color: rgb(64, 120, 192); text-decoration: none; background-color: transparent;">WAM - Warren's Abstract Machine</a> - This is an abstract machine that the BEAM is conceptually very similar to.</li> | |
| <li style="box-sizing: border-box;"><a href="https://groups.google.com/forum/#!topic/elixir-lang-talk/hPTVt638Lgs" style="box-sizing: border-box; color: rgb(64, 120, 192); text-decoration: none; background-color: transparent;">I had a problem at first, but got past it</a></li> | |
| <li style="box-sizing: border-box;"><a href="https://www.google.com/url?q=https%3A%2F%2Ftwitter.com%2Fjosevalim%2Fstatus%2F626469688780976132&sa=D&sntz=1&usg=AFQjCNEv-LokEbAsKs_ViNK3-_87rS00ug" style="box-sizing: border-box; color: rgb(64, 120, 192); text-decoration: none; background-color: transparent;">Jose helped me compile Elixir itself with HiPE</a></li> | |
| <li style="box-sizing: border-box;"><a href="https://erllvm.softlab.ntua.gr/files/ErLLVM.pdf" style="box-sizing: border-box; color: rgb(64, 120, 192); text-decoration: none; background-color: transparent;">The Future - HiPE on LLVM - ErLLVM</a></li> | |
| <li style="box-sizing: border-box;"><a href="http://erlang.org/pipermail/erlang-questions/2015-July/085360.html" style="box-sizing: border-box; color: rgb(64, 120, 192); text-decoration: none; background-color: transparent;">I'm trying to file a bug with HiPE re the problems with compiling Elixir itself</a></li> | |
| </ul> | |
| </div> | |
| <h3>Attached Files</h3> | |
| <ul> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=56123">181_Native_Compilation_with_HiPE.mp4</a></li> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=56124">181_Native_Compilation_with_HiPE.markdown</a></li> | |
| </ul></div>]]></description> | |
| <guid isPermaLink="false">dpd-29837ddace5123c8214cbbc2a54e2b438f0e09c9</guid> | |
| <pubDate>Thu, 30 Jul 2015 21:32:00 -0400</pubDate> | |
| <enclosure url="https://elixirsips.dpdcart.com/feed/download/56123/181_Native_Compilation_with_HiPE.mp4" length="76882258" type="video/mp4"/> | |
| </item> | |
| <item> | |
| <title><![CDATA[180 - Collectable]]></title> | |
| <link>https://elixirsips.dpdcart.com/subscriber/post?id=854</link> | |
| <description><![CDATA[<div class="blog-entry"> | |
| <div class="blog-content"><h1 style="box-sizing: border-box; font-size: 2.25em; margin-right: 0px; margin-bottom: 16px; margin-left: 0px; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; margin-top: 0px !important;">Episode 180: Collectable</h1> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">In the last episode, we implemented a basic rules engine. In today's episode we're going to clean some of the code up by implementing the Collectable protocol for our RulesOutput struct that collects the results of applying the rules. Let's get started.</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Project</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">I've tagged the <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">rules_engine</code> project with <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">before_episode_180</code>. Now let's have a look at the<code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">apply_rules</code> function and talk about Collectable:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">RulesEngine</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesEngine</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Document</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesEngine</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesOutput</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesEngine</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Guidance</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> apply_rules(document<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span>%<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Document</span>{}, rules) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| apply_rules(document, rules, %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesOutput</span>{}) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> apply_rules(document<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span>%<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Document</span>{}, [{mod, fun}<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span>rest], rules_output) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| output <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> apply(mod, fun, [document]) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">case</span> output <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">nil</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> apply_rules(document, rest, rules_output) | |
| guidance <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Guidance</span>{} <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| apply_rules(document, rest, %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesOutput</span>{rules_output<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">guidances:</span> [guidance<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span>rules_output.guidances]}) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> apply_rules(document<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span>%<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Document</span>{}, [rule<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span>rest], rules_output) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| {output, _binding} <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Code</span>.eval_quoted(rule, [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">document:</span> document, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">patient:</span> document.patient], <span class="pl-v" style="box-sizing: border-box; color: rgb(237, 106, 67);">__ENV__</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">case</span> output <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">nil</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> apply_rules(document, rest, rules_output) | |
| guidance <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Guidance</span>{} <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| apply_rules(document, rest, %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesOutput</span>{rules_output<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">guidances:</span> [guidance<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span>rules_output.guidances]}) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> apply_rules(_document, [], rules_output), <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span>: rules_output | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">So here's the dealio: we commonly implement this sort of pattern. We'll define a tail-call function and then iterate through a collection. This is fine, and it's one of the most powerful things functional programming affords you, but it's also a pattern that can be simplified in Elixir.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Elixir provides Protocols. We haven't talked about them very much, but they provide a means of polymorphism. We're going to take advantage of the Collectable protocol to clean this code up.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Essentially, Collectable pairs very nicely with list comprehensions. We're going to essentially reduce our list of rules into a RulesOutput. The pattern for the reduction is that when a rule outputs a guidance, we'll collect it into the guidances field in the struct. This is what we're already doing, but we've rolled our own.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Let's look at how we want <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">apply_rules</code> to look, then we'll look at implementing Collectable so that it will work.</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> apply_rules(%<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Document</span>{}<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span>document, rules) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Alright, so we'll use a list comprehension to reduce the rules into a</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # RulesOutput struct.</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">for</span> rule <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"><</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span> rules, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">into:</span> %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesOutput</span>{} <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Depending on the rule, we'll just return its output inside the</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # comprehension</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">case</span> rule <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| {mod, fun} <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| apply(mod, fun, [document]) | |
| rule <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| {output, _binding} <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Code</span>.eval_quoted(rule, [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">document:</span> document, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">patient:</span> document.patient], <span class="pl-v" style="box-sizing: border-box; color: rgb(237, 106, 67);">__ENV__</span>) | |
| output | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">So that's it for applying the rules. I think it reads very nicely, and it certainly helps us clean up tons of code. Now let's look at implementing the Collectable protocol. We'll move up to the RulesOutput module. First, let's move it down below the other modules - if it were in its own file, it wouldn't matter, but it isn't and we'll need to reference the Guidance module inside its body, so we need to put it after the declaration of the Guidance module.</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">RulesEngine.Document</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defstruct</span> [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:patient</span>] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">RulesEngine.Patient</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defstruct</span> [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:bmi</span>] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">RulesEngine.Guidance</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defstruct</span> [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:diagnosis</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:text</span>] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">RulesEngine.Diagnosis</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defstruct</span> [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:id</span>] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">RulesEngine.RulesOutput</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defstruct</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">guidances:</span> [] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Next, we'll add a definition of our implementation of Collectable for a RulesOutput:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defimpl</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Collectable</span>, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">for</span>: <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesEngine</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesOutput</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defdelegate</span> into(original), <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">to:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesEngine</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesOutput</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Here we're just delegating to a function in the RulesOutput module, because I think it's nice to keep those functions in the module we're implementing the protocol for. You don't have to do that, though.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Now, let's look at how you implement Collectable.</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">RulesEngine.RulesOutput</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defstruct</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">guidances:</span> [] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> into(original) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| {original, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">fn</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Here's the shell of the implementation of this protocol. We define an</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # `into` function that can pattern match on the input, and we return a</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # 2-tuple that contains the original `into` value and a function that will</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # be applied each iteration through the comprehension.</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # The first pattern we care about is a `cont` tuple. This is just a</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # continuation of the Collectable, and it will provide the new value to</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # your function. We'll deal with that later</span> | |
| source, {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:cont</span>, value} <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:deal_with_it</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # The next pattern we care about is `done`, which is what is called when</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # the collection is complete. We'll just return the source here.</span> | |
| source, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:done</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> source | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # You should also handle the `halt` case, which can happen if a collection</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # is stopped before completing. I can't think through all of the reasons</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # this might happen, but basically your return value isn't used so you</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # just define this clause so that you adhere to the protocol.</span> | |
| source, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:halt</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:ok</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span>} | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">So this is the standard implementation. Now let's go back and fill out the clause for our <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">cont</code>instructions:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">RulesEngine.RulesOutput</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defstruct</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">guidances:</span> [] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> into(original) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| {original, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">fn</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # OK, so rules that don't match just return nil. In this case, we don't</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # modify the RulesOutput at all</span> | |
| source, {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:cont</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">nil</span>} <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> source | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # A rule can also return a Guidance. If this happens, we want to add it</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # to the RulesOutput's `guidances` field.</span> | |
| source, {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:cont</span>, guidance<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span>%<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesEngine</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Guidance</span>{}} <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| %<span class="pl-v" style="box-sizing: border-box; color: rgb(237, 106, 67);">__MODULE__</span>{source <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">guidances:</span> [guidance<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span>source.guidances]} | |
| source, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:done</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> source | |
| source, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:halt</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:ok</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span>} | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">And that's it. With this and our list-comprehension change for the <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">apply_rules</code> function, we've modified our code to be a lot more succinct and to take advantage of Elixir's protocols. Let's go ahead and run the benchmarks to make sure everything is still working.</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| mix bench</pre> | |
| </div> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Summary</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">In today's episode, we saw how to simplify a common pattern using the Collectable protocol. I think it makes the code read a lot better, and it will do me a lot of good to keep this in mind since my code has a lot of this pattern and I should really stop hand-rolling the same thing over and over again. I hope it helps you clean up your code too. See you soon!</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Resources</h2> | |
| <ul style="box-sizing: border-box; padding-right: 0px; padding-left: 2em; margin-top: 0px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; margin-bottom: 0px !important;"> | |
| <li style="box-sizing: border-box;"><a href="http://elixir-lang.org/docs/v1.0/elixir/Collectable.html" style="box-sizing: border-box; color: rgb(64, 120, 192); text-decoration: none; background-color: transparent;">Collectable</a></li> | |
| <li style="box-sizing: border-box;"><a href="http://github.com/knewter/rules_engine" style="box-sizing: border-box; color: rgb(64, 120, 192); text-decoration: none; background-color: transparent;">knewter/rules_engine</a></li> | |
| </ul> | |
| </div> | |
| <h3>Attached Files</h3> | |
| <ul> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=55601">180_Collectable.mp4</a></li> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=55602">180_Collectable.markdown</a></li> | |
| </ul></div>]]></description> | |
| <guid isPermaLink="false">dpd-700dca27a67e3b1f15f27ea9cd222981597fd648</guid> | |
| <pubDate>Sun, 26 Jul 2015 11:19:00 -0400</pubDate> | |
| <enclosure url="https://elixirsips.dpdcart.com/feed/download/55601/180_Collectable.mp4" length="34977089" type="video/mp4"/> | |
| </item> | |
| <item> | |
| <title><![CDATA[179 - Rules Engine]]></title> | |
| <link>https://elixirsips.dpdcart.com/subscriber/post?id=853</link> | |
| <description><![CDATA[<div class="blog-entry"> | |
| <div class="blog-content"><h1 style="box-sizing: border-box; font-size: 2.25em; margin-right: 0px; margin-bottom: 16px; margin-left: 0px; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; margin-top: 0px !important;">Episode 179: Rules Engine</h1> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;">It's common to want to break Business Logic apart from the rest of a given application. This is reasonable, as things that change at different paces should be distinct, and Business Logic certainly changes at a different pace than Application Logic.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;">However, often Business Logic is decoupled by way of a Business Rules Engine, which can also be referred to as a Production System. While this isn't a bad idea at heart, a recent survey of smart people suggested that implementing a generic Rules Engine is a woeful thing. With that in mind, let's see what it looks like to prototype our own Rules Engine.</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Project</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;">We'll start a new project:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| mix new rules_engine | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">cd</span> rules_engine | |
| vim <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">test</span>/rules_engine_test.exs</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;">And we'll start out with a test.</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">RulesEngineTest</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">use</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">ExUnit</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Case</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Alright so imagine we have a client that has provided some pseudocode for</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # an example rule that looks roughly like the following. This is</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # a rule for suggesting Diagnoses of a patient based on some</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # information from their visit.</span> | |
| <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);">"""</span> | |
| <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"> //Patient based rule introducing diagnoses</span> | |
| <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"> For patient,</span> | |
| <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"> if patient.bmi >= 40,</span> | |
| <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"> then event.guidance.diagnosis == [diagnosis.id(1111)] && event.guidance.text == "Consider the following..."</span> | |
| <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"> else if patient.bmi < 18,</span> | |
| <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"> then event.guidance.diagnosis == [diagnosis.id(2222)] && event.guidance.text == "Consider the following..."</span> | |
| <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"> """</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # So from this we know they expect to be able to make some determinations</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # based on information that belongs to the patient.</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # For now let's just write a basic test that assumes we've implemented this</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # logic.</span> | |
| test <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>basic output<span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # I can assume a particular format for our document so far</span> | |
| document <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Document</span>{ | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">patient:</span> %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Patient</span>{ | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">bmi:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">40</span> | |
| } | |
| } | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # We'll imagine we have an `apply_rules` function that returns a RulesOutput</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # that has some guidances, based on our pseudocode</span> | |
| %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesOutput</span>{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">guidances:</span> [guidance<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span>_rest]} <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> apply_rules(document, rules) | |
| assert guidance.diagnosis <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">==</span> %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Diagnosis</span>{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">id:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1111</span>} | |
| assert guidance.text <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">==</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>Consider the following...<span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;">OK obviously this won't run yet, but we have a test to start with. If we run it it will tell us what's missing.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;">((( do it )))</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;">OK so we need to add a <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">Document</code> struct. Let's do that:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">RulesEngine.Document</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defstruct</span> [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:patient</span>] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"># We also know we need a Patient struct just from building the document, so</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"># we'll add that</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">RulesEngine.Patient</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defstruct</span> [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:bmi</span>] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"># and alias them...</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">RulesEngineTest</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesEngine</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Document</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesEngine</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Patient</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> #...</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;">Run them again, and we're missing a <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">RulesOutput</code> struct...let's add that:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">RulesEngine.RulesOutput</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defstruct</span> [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:guidances</span>] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"># So that tells us we need a Guidance struct</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">RulesEngine.Guidance</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defstruct</span> [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:diagnosis</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:text</span>] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"># And from that we know we need a Diagnosis</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">RulesEngine.Diagnosis</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defstruct</span> [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:id</span>] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">RulesEngineTest</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> #...</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesEngine</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesOutput</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesEngine</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Guidance</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesEngine</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Diagnosis</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> #...</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;">Alright, with those in place, let's try to run the tests...and they fail because there's no<code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">apply_rules</code> function. Let's change this to <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">RulesEngine.apply_rules</code> and figure out where our rules come from:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesOutput</span>{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">guidance:</span> [guidance<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span>_rest]} <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesEngine</span>.apply_rules(document, <span class="pl-smi" style="box-sizing: border-box;">@rules</span>)</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;">Alright so we're going to take a first stab at our rules now. We already have the pseudo code we want to implement. Let's assume for now that we're going to provide some DSL that will output a normal elixir AST, and that's what our rules will look like. If that's the case, we can mock them out with the <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">quote</code> macro:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-smi" style="box-sizing: border-box;">@rules</span> [ | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">quote</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # So here we'll just use the patient var from our binding, and we'll actually output the whole RulesOutput to start with</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">if</span> var!(patient).bmi <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">>=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">40</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| guidance <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Guidance</span>{ | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">diagnosis:</span> %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Diagnosis</span>{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">id:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1111</span>}, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">text:</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>Consider the following...<span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| } | |
| %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesOutput</span>{ | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">guidances:</span> [guidance] | |
| } | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| ]</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;">Alright, so now we have a rule of sorts. If we try to run it, it will fail because we haven't implemented <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">apply_rules</code>. Let's move all of the structs into the main <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">rules_engine.ex</code> file for now and then implement this function:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">RulesEngine</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesEngine</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Document</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # So we'll just take the first rule off the top for now</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> apply_rules(document<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span>%<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Document</span>{}, [rule<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span>_rest]) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Now we want to eval the rule. We'll provide a document and a patient</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # variable for our rules to work with</span> | |
| {output, _binding} <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Code</span>.eval_quoted(rule, [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">document:</span> document, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">patient:</span> document.patient], <span class="pl-v" style="box-sizing: border-box; color: rgb(237, 106, 67);">__ENV__</span>) | |
| output | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;">OK, so if we run this...it will pass. So here's our first pass at having something like a rules engine of our own. Of course, it's not going to work to run multiple rules yet, and we haven't implemented the rest of our initial rule's pseudocode. Let's do that:</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;">First we'll add the new tests:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| test <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>basic output<span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| document_40 <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Document</span>{ | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">patient:</span> %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Patient</span>{ | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">bmi:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">40</span> | |
| } | |
| } | |
| document_30 <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Document</span>{ | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">patient:</span> %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Patient</span>{ | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">bmi:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">30</span> | |
| } | |
| } | |
| document_17 <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Document</span>{ | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">patient:</span> %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Patient</span>{ | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">bmi:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">17</span> | |
| } | |
| } | |
| %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesOutput</span>{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">guidances:</span> [guidance<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span>_rest]} <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesEngine</span>.apply_rules(document_40, <span class="pl-smi" style="box-sizing: border-box;">@rules</span>) | |
| assert guidance.diagnosis <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">==</span> %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Diagnosis</span>{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">id:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1111</span>} | |
| assert guidance.text <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">==</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>Consider the following...<span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| assert %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesOutput</span>{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">guidances:</span> []} <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesEngine</span>.apply_rules(document_30, <span class="pl-smi" style="box-sizing: border-box;">@rules</span>) | |
| %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesOutput</span>{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">guidances:</span> [guidance<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span>_rest]} <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesEngine</span>.apply_rules(document_17, <span class="pl-smi" style="box-sizing: border-box;">@rules</span>) | |
| assert guidance.diagnosis <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">==</span> %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Diagnosis</span>{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">id:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">2222</span>} | |
| assert guidance.text <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">==</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>Consider the following...<span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;">Then we'll define the more complex rule:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-smi" style="box-sizing: border-box;">@rules</span> [ | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">quote</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">case</span> var!(patient).bmi <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| x <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">when</span> x <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">>=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">40</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Guidance</span>{ | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">diagnosis:</span> %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Diagnosis</span>{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">id:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1111</span>}, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">text:</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>Consider the following...<span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| } | |
| x <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">when</span> x <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"><</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">18</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Guidance</span>{ | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">diagnosis:</span> %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Diagnosis</span>{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">id:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">2222</span>}, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">text:</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>Consider the following...<span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| } | |
| _ <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">nil</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| ]</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;">Another change here is that we're no longer building out the RulesOutput in the rule, since it makes no sense. Here we're just returning an output based on the rules that were passed in. Let's modify the <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">apply_rules</code> function to wrap this output in a RulesOutput struct, as well as support running multiple rules:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"># Let's make the default value of a RulesOutput guidances key the empty list</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">RulesEngine.RulesOutput</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defstruct</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">guidances:</span> [] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">RulesEngine</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesEngine</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Document</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesEngine</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesOutput</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesEngine</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Guidance</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Then we'll define the 2-arity version of our apply_rules function, which just</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # initializes a RulesOutput for us to accumulate into and then calls a 3-arity version</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> apply_rules(document<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span>%<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Document</span>{}, rules) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| apply_rules(document, rules, %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesOutput</span>{}) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Our main 3-arity version just recurses through the rules</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> apply_rules(document<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span>%<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Document</span>{}, [rule<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span>rest], rules_output<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span>%<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesOutput</span>{}) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| {output, _binding} <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Code</span>.eval_quoted(rule, [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">document:</span> document, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">patient:</span> document.patient], <span class="pl-v" style="box-sizing: border-box; color: rgb(237, 106, 67);">__ENV__</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">case</span> output <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # If this output yields nothing new, we just move on to the next rules</span> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">nil</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> apply_rules(document, rest, rules_output) | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # If it yields a Guidance, we add that to our RulesOutput</span> | |
| guidance <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Guidance</span>{} <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| apply_rules(document, rest, %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesOutput</span>{rules_output <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">guidances:</span> [guidance<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span>rules_output.guidances]}) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Once we're out of rules, we return the rules output</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> apply_rules(_document, [], rules_output<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span>%<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesOutput</span>{}), <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span>: rules_output | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;">Let's run the tests...and they pass (I hope!)</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;">OK, so this is a more complete implementation. It supports an arbitrary number of rules and rules are just elixir AST. We would expect this to be not exceedingly fast, because we're having to use the Code module to evaluate the AST and it's not compiled into bytecode yet. Let's get a feel for how fast it is though. We're going to pull in benchfella and run some benchmarks:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| vim mix.exs</pre> | |
| </div> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defp</span> deps <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| [ | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:benchfella</span>, <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>~> 0.2.0<span class="pl-pds" style="box-sizing: border-box;">"</span></span>} | |
| ] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| mix deps.get | |
| mkdir bench | |
| vim bench/rules_timing_bench.exs</pre> | |
| </div> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">RulesTimingBench</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">use</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Benchfella</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesEngine</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Document</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesEngine</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Patient</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesEngine</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Guidance</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesEngine</span>.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Diagnosis</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # We'll run this a certain number of times</span> | |
| <span class="pl-smi" style="box-sizing: border-box;">@num1</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">100</span> | |
| <span class="pl-smi" style="box-sizing: border-box;">@rule</span> ( | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">quote</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">case</span> var!(patient).bmi <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| x <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">when</span> x <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">>=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">40</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Guidance</span>{ | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">diagnosis:</span> %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Diagnosis</span>{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">id:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">5426</span>}, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">text:</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>Consider the following...<span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| } | |
| x <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">when</span> x <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"><</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">18</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Guidance</span>{ | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">diagnosis:</span> %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Diagnosis</span>{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">id:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">2376</span>}, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">text:</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>Consider the following...<span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| } | |
| _ <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">nil</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| ) | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # We'll build a rules list that contains the number of rules defined in num1</span> | |
| <span class="pl-smi" style="box-sizing: border-box;">@rules1</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Stream</span>.repeatedly(<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">fn</span>() <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-smi" style="box-sizing: border-box;">@rule</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span>) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Enum</span>.take(<span class="pl-smi" style="box-sizing: border-box;">@num1</span>) | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Let's use a standard document</span> | |
| <span class="pl-smi" style="box-sizing: border-box;">@document_40</span> %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Document</span>{ | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">patient:</span> %<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Patient</span>{ | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">bmi:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">40</span> | |
| } | |
| } | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # And let's benchmark running this many rules against that document</span> | |
| bench <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>running <span class="pl-s1" style="box-sizing: border-box; color: rgb(51, 51, 51);"><span class="pl-pse" style="box-sizing: border-box;">#{</span><span class="pl-smi" style="box-sizing: border-box;">@num1</span><span class="pl-pse" style="box-sizing: border-box;">}</span></span> rules<span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesEngine</span>.apply_rules(<span class="pl-smi" style="box-sizing: border-box;">@document_40</span>, <span class="pl-smi" style="box-sizing: border-box;">@rules1</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;">Now we can run the benchmark with <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">mix bench</code> and see how it performs.</p> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 16px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; background-color: rgb(247, 247, 247);"> | |
| <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0px; margin: 0px; border-radius: 3px; word-break: normal; white-space: pre; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;">:!mix bench | |
| Settings: | |
| duration: 1.0 s | |
| ## RulesTimingBench | |
| [21:20:04] 1/1: running 100 rules | |
| Finished in 2.83 seconds | |
| ## RulesTimingBench | |
| running 100 rules 100 25377.81 µs/op | |
| </code></pre> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;">On this run it took 25 milliseconds to run 100 rules. I expect our production system to contain more like 10s of thousands of rules. I can already tell that this doesn't look so hot, but let's modify our benchmark to see what that looks like:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;"> | |
| <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">RulesTimingBench</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> #...</span> | |
| <span class="pl-smi" style="box-sizing: border-box;">@num1</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">100</span> | |
| <span class="pl-smi" style="box-sizing: border-box;">@num2</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">10_000</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> #...</span> | |
| <span class="pl-smi" style="box-sizing: border-box;">@rules1</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Stream</span>.repeatedly(<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">fn</span>() <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-smi" style="box-sizing: border-box;">@rule</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span>) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Enum</span>.take(<span class="pl-smi" style="box-sizing: border-box;">@num1</span>) | |
| <span class="pl-smi" style="box-sizing: border-box;">@rules2</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Stream</span>.repeatedly(<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">fn</span>() <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-smi" style="box-sizing: border-box;">@rule</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span>) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Enum</span>.take(<span class="pl-smi" style="box-sizing: border-box;">@num2</span>) | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> #...</span> | |
| bench <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>running <span class="pl-s1" style="box-sizing: border-box; color: rgb(51, 51, 51);"><span class="pl-pse" style="box-sizing: border-box;">#{</span><span class="pl-smi" style="box-sizing: border-box;">@num1</span><span class="pl-pse" style="box-sizing: border-box;">}</span></span> rules<span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesEngine</span>.apply_rules(<span class="pl-smi" style="box-sizing: border-box;">@document_40</span>, <span class="pl-smi" style="box-sizing: border-box;">@rules1</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| bench <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>running <span class="pl-s1" style="box-sizing: border-box; color: rgb(51, 51, 51);"><span class="pl-pse" style="box-sizing: border-box;">#{</span><span class="pl-smi" style="box-sizing: border-box;">@num2</span><span class="pl-pse" style="box-sizing: border-box;">}</span></span> rules<span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">RulesEn | |
| </div> | |
| <h3>Attached Files</h3> | |
| <ul> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=55445">179_Rules_Engine.markdown</a></li> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=55597">179_Rules_Engine.mp4</a></li> | |
| </ul></div>]]></description> | |
| <guid isPermaLink="false">dpd-0ec9bd87adf7d6eb447a5e21976a814038387e5e</guid> | |
| <pubDate>Wed, 22 Jul 2015 22:20:00 -0400</pubDate> | |
| <enclosure url="https://elixirsips.dpdcart.com/feed/download/55597/179_Rules_Engine.mp4" length="96301511" type="video/mp4"/> | |
| </item> | |
| <item> | |
| <title><![CDATA[178 - Memory Leaks]]></title> | |
| <link>https://elixirsips.dpdcart.com/subscriber/post?id=848</link> | |
| <description><![CDATA[<div class="blog-entry"> | |
| <div class="blog-content"><h1 style="box-sizing: border-box; font-size: 2.25em; margin-right: 0px; margin-bottom: 16px; margin-left: 0px; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; margin-top: 0px !important;">Episode 178: Memory Leaks</h1> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">In the last episode we built an Audio Visualizer. We stored the data coming from a port in an agent, sampling the most recent 16 thousand values and pushing them into our visualization. But we also introduced a memory leak. It was pretty straightforward, so I'm not going to act like it was a big secret, but I did kind of put it there as an easter egg.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Let's look at how we could diagnose where the leak is.</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Project</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">I've tagged the repo with <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">before_episode_178</code>. The only difference from the last episode is that I've extracted the GetAudio example into a module of its own so that we can trivially run it and an instance of observer in the same VM.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">I'll run it for a while here, but the moral of the story is that we've got a memory leak:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| iex -S mix</pre> | |
| </div> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| spawn(<span class="pl-vo" style="box-sizing: border-box;">&</span><span class="pl-vo" style="box-sizing: border-box;">AudioVisualizer</span>.<span class="pl-vo" style="box-sizing: border-box;">GetAudio</span>.start<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">/</span><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span>) | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:observer</span>.start</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Let's sort the processes by memory used.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">((( do it )))</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">OK, so we can see that the agent server is taking up all of this memory. If I had built this as an actual OTP application, which I should have, I would have nice names and links to show me which process exactly this was, but I already know which one it is because we only have one agent. Let's have a look at the code.</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> loop(data_agent) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">receive</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| {_, {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:data</span>, data}} <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| <span class="pl-vo" style="box-sizing: border-box;">Agent</span>.update(data_agent, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">fn</span>(existing_data) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| data <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">++</span> existing_data <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"># YUP There's our memory leak!</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span>) | |
| other <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-vo" style="box-sizing: border-box;">IO</span>.inspect <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>got other: <span class="pl-s2" style="box-sizing: border-box; color: rgb(51, 51, 51);"><span class="pl-pse" style="box-sizing: border-box;">#{</span>inspect other<span class="pl-pse" style="box-sizing: border-box;">}</span></span><span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| loop(data_agent) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Alright, so if we look at this we're basically shoving a megabyte of data into this list every second, unbounded. Wooooooops.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">So all we do later is grab the first 16 thousand samples out of this agent. What if we just piped this into<code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">Enum.take</code> here to truncate the agent's state to only include the data we need? There's no reason to store all the other crap - that's literally the definition of a memory leak, right?</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">OK, so let's make that change...</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> loop(data_agent) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">receive</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| {_, {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:data</span>, data}} <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| <span class="pl-vo" style="box-sizing: border-box;">Agent</span>.update(data_agent, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">fn</span>(existing_data) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| data <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">++</span> existing_data | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-vo" style="box-sizing: border-box;">Enum</span>.take(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">16_000</span>) <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"># <-- there we go, truncate it</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span>) | |
| other <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-vo" style="box-sizing: border-box;">IO</span>.inspect <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>got other: <span class="pl-s2" style="box-sizing: border-box; color: rgb(51, 51, 51);"><span class="pl-pse" style="box-sizing: border-box;">#{</span>inspect other<span class="pl-pse" style="box-sizing: border-box;">}</span></span><span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| loop(data_agent) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">OK, so now we're no longer growing unbounded, right? Let's use <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">observer</code> to verify that:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| spawn(<span class="pl-vo" style="box-sizing: border-box;">&</span><span class="pl-vo" style="box-sizing: border-box;">AudioVisualizer</span>.<span class="pl-vo" style="box-sizing: border-box;">GetAudio</span>.start<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">/</span><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span>) | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:observer</span>.start</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">OK, so we'll sort by memory, and we can inspect this process and refresh it from time to time. You'll note it's no longer growing, basically. That's what we want.</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Summary</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">So this was a very easy memory leak to catch. I knew it was a problem when I wrote it, but opted not to fix it because it intrigued me to see what would happen to my machine if I just let it run for a long time. I didn't actually mean to run it for as long as I did, but some food was delivered and I got distracted, and I learned something that I didn't think I would learn.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">I saw a single elixir process have its heap grow to 32 gigabytes. I only have 22 gigabytes of RAM. There's no reason for me to have a single elixir process using that much memory, but it turns out if you do that my linux kernel has a bit of an issue and user input becomes a no go.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">It also might have something to do with the fact that I was accessing the first 16k of that memory 100 times per second, but at any rate the kernel's Out of Memory Killer didn't fire in any reasonable time frame and I totally had to reboot this sucker. So that's my first reboot forced by an Elixir memory leak, in service of this episode! Thanks for making that possible. See you soon!</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">NOTE: I am aware that growing at a pace of 1M/second means it will take a Long Time to get to 32G of memory usage. I am not sure what series of events led to what I'm assuming was an exponential growth at the end of a bad situation, but there it is.</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Resources</h2> | |
| <ul class="task-list" style="box-sizing: border-box; padding-right: 0px; padding-left: 2em; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <li style="box-sizing: border-box;"><a href="https://github.com/knewter/audio_visualizer" rel="noreferrer" style="box-sizing: border-box; color: rgb(65, 131, 196); text-decoration: none;">knewter/audio_visualizer</a></li> | |
| </ul> | |
| </div> | |
| <h3>Attached Files</h3> | |
| <ul> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=54713">178_Memory_Leaks.mp4</a></li> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=54714">178_Memory_Leaks.markdown</a></li> | |
| </ul></div>]]></description> | |
| <guid isPermaLink="false">dpd-d8a59be3df4f3c949006912c6e73fbe58aecb951</guid> | |
| <pubDate>Wed, 15 Jul 2015 21:22:00 -0400</pubDate> | |
| <enclosure url="https://elixirsips.dpdcart.com/feed/download/54713/178_Memory_Leaks.mp4" length="36505476" type="video/mp4"/> | |
| </item> | |
| <item> | |
| <title><![CDATA[177 - Audio Visualizer]]></title> | |
| <link>https://elixirsips.dpdcart.com/subscriber/post?id=847</link> | |
| <description><![CDATA[<div class="blog-entry"> | |
| <div class="blog-content"><h1 style="box-sizing: border-box; font-size: 2.25em; margin-right: 0px; margin-bottom: 16px; margin-left: 0px; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; margin-top: 0px !important;">Episode 177: Audio Visualizer</h1> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">In today's episode we're taking a drastic departure from web-related stuff. It's another project episode, and we're going to build an audio visualizer this time using wx. Let's get started.</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Project</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">I've got a github repo in the resources, and I tagged the first commit with <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">before_episode_177</code>. It just has a basic rendering platform in place so we don't have to set up wx from scratch, because that's extremely boring.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">We're going to listen to audio and draw lines on a canvas representing the PCM amplitude at various points. To get a sort of mockup of what we'll be dealing with, we'll start out with some sample data.</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| mkdir examples | |
| vim examples/basic.exs</pre> | |
| </div> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-vo" style="box-sizing: border-box;">AudioRenderer</span>.<span class="pl-vo" style="box-sizing: border-box;">Window</span>.start([ | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">100</span>}, | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">99</span>}, | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">2</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">50</span>}, | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">3</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">20</span>}, | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">4</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">100</span>} | |
| ])</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">So here we have a few point samples. They consist of a position and an amplitude. Let's tell our renderer how to draw a line for each of these.</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| vim lib/audio_visualizer/renderer.ex</pre> | |
| </div> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">AudioVisualizer.Renderer</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # We want to add a y position on the canvas that we'll start from</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">@center_y</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">100</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> render(canvas, data) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| draw_lines(canvas, data) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> draw_lines(canvas, [head<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span>rest]) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| draw_line(canvas, head) | |
| draw_lines(canvas, rest) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> draw_lines(canvas, []), <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span>: <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:ok</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> draw_line(canvas, {position, amplitude}) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">IO</span>.puts amplitude | |
| pen <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:wxPen</span>.new({<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">255</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">255</span>}) | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:wxGraphicsContext</span>.setPen(canvas, pen) | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Then we want to draw a line for each amplitude, in its x position,</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # starting from the center_y point</span> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:wxGraphicsContext</span>.drawLines(canvas, [{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">+</span> position, <span class="pl-vo" style="box-sizing: border-box;">@center_y</span>}, {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">+</span> position, amplitude}]) | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:ok</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> #...</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">OK, let's run that and see what it looks like.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">((( do it )))</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Alright, now that we're past that we're going to want to get some audio.</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| vim examples/get_audio.exs</pre> | |
| </div> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"># We're going to use an agent to store the state that comes in from the audio</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"># source. When we finish there will be a big memory leak, and this is where</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"># you'd want to solve that for your homework :)</span> | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:ok</span>, data_agent} <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-vo" style="box-sizing: border-box;">Agent</span>.start_link(<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">fn</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> [] <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">AudioReceiver</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> start(data_agent) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Let's open a port to gather audio data.</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # I'm going to grab audio from my microphone using the pulseaudio program `parec`.</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # If you have a different audio stack, you will want to replace that bit with a</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # corresponding program. In general, you want a program that outputs 16 kilohertz</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # PCM audio using 8 bit unsigned values.</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">Port</span>.open({<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:spawn</span>, <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>parec --rate=16000 --format=u8<span class="pl-pds" style="box-sizing: border-box;">"</span></span>}, []) | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Once we've opened that port, we'll just loop, passing the data agent into</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # the loop function</span> | |
| loop(data_agent) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> loop(data_agent) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Our port will be sending us messages regularly with the data from stdout.</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Let's catch that and push it into the agent.</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">receive</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| {_, {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:data</span>, data}} <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| <span class="pl-vo" style="box-sizing: border-box;">Agent</span>.update(data_agent, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">fn</span>(existing_data) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| data <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">++</span> existing_data | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span>) | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # If we get data we aren't expecting, it'd be nice to not crash.</span> | |
| other <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-vo" style="box-sizing: border-box;">IO</span>.inspect <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>got other: <span class="pl-s2" style="box-sizing: border-box; color: rgb(51, 51, 51);"><span class="pl-pse" style="box-sizing: border-box;">#{</span>inspect other<span class="pl-pse" style="box-sizing: border-box;">}</span></span><span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # And of course then we just tail-call</span> | |
| loop(data_agent) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"># Now we spawn the audio receiver, and it will constantly update our agent.</span> | |
| spawn(<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">fn</span>() <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| <span class="pl-vo" style="box-sizing: border-box;">AudioReceiver</span>.start(data_agent) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span>) | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"># Finally, we start our window with the data agent passed in</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">AudioVisualizer</span>.<span class="pl-vo" style="box-sizing: border-box;">Window</span>.start(data_agent)</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Now we'll need to update our window to get the data and pass it in.</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| vim lib/audio_visualizer/window.ex</pre> | |
| </div> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"># Let's fix that module name...</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">AudioVisualizer.Window</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">@moduledoc """</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> A window to draw our audio renderer within.</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> """</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"># And we'll fix the title</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">@title</span> <span class="pl-s3" style="box-sizing: border-box; color: rgb(0, 134, 179);"><span class="pl-pds" style="box-sizing: border-box; color: rgb(223, 80, 0);">'</span>Audio Visualizer<span class="pl-pds" style="box-sizing: border-box; color: rgb(223, 80, 0);">'</span></span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"># Now we're passing in a data agent</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> start(data_agent) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| do_init(data_agent) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"># Fix this reference...</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> init(data_agent) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:wx</span>.batch(<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">fn</span>() <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> do_init(data_agent) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"># And this one...</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> do_init(data_agent) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| wx <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:wx</span>.new | |
| frame <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:wxFrame</span>.new(wx, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1</span>, <span class="pl-vo" style="box-sizing: border-box;">@title</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">size:</span> {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1000</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1000</span>}) | |
| panel <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:wxPanel</span>.new(frame, []) | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> #...</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # and this one...</span> | |
| draw(data_agent, dc) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> #...</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"># And this one...</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> draw(data_agent, dc) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| do_draw(data_agent, dc) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"># And one more...</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> do_draw(data_agent, dc) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| canvas <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:wxGraphicsContext</span>.create(dc) | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # We need to clear the canvas each time we draw</span> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:wxPaintDC</span>.clear(dc) | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # And we'll get the data out of the agent and pass that in. In fact, we'll</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # grab the first 16_000 data points, as that should be a second</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">AudioVisualizer</span>.<span class="pl-vo" style="box-sizing: border-box;">Renderer</span>.render(canvas, <span class="pl-vo" style="box-sizing: border-box;">Agent</span>.get(data_agent, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">fn</span>(data) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| <span class="pl-vo" style="box-sizing: border-box;">Enum</span>.take(data, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">16_000</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span>)) | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:timer</span>.sleep(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">10</span>) | |
| do_draw(data_agent, dc) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Then we need to look at the renderer:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">AudioVisualizer.Renderer</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">@center_y</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">100</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # we're not going to draw 16000 lines. Let's sample every 100th data point.</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">@resolution</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">100</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> render(canvas, data) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # The data we're passing in doesn't have position information. We'll use</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Enum.with_index to get that</span> | |
| draw_lines(canvas, <span class="pl-vo" style="box-sizing: border-box;">Enum</span>.with_index(data)) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # ...</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Enum.with_index gives the position as the second element, so we have to</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # switch this 2-tuple around</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> draw_line(canvas, {amplitude, position}) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Here's where we'll do our sampling....</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">case</span> rem(position, <span class="pl-vo" style="box-sizing: border-box;">@resolution</span>) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| pen <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:wxPen</span>.new({<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">255</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">255</span>}) | |
| x <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">+</span> position<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">/</span><span class="pl-vo" style="box-sizing: border-box;">@resolution</span> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:wxGraphicsContext</span>.setPen(canvas, pen) | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:wxGraphicsContext</span>.drawLines(canvas, [ | |
| {x, <span class="pl-vo" style="box-sizing: border-box;">@center_y</span>}, | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # This part is important...remember our PCM audio is 8 bits and</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # unsigned. That means we get a value from 0 to 255. 127 is the</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # mid-point. That means if we get a 127, there's no amplitude for</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # that sample. Guess which part of this episode wasted an hour of my life.</span> | |
| {x, <span class="pl-vo" style="box-sizing: border-box;">@center_y</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">+</span> (<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">127</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">+</span> amplitude)} | |
| ]) | |
| _ <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:ok</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">With that, we should have a functioning visualizer. I need some audio for it to listen to, so let me start some music and let's try it out.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">((( do it )))</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">OK, so now let's move the visualizer around a bit and make it fill the window. The window's 1000 pixels wide, and we get 16000 samples per second. We're going to show every 16th sample, so we'll have a 1000 pixel-wide visualization. It would also be nice if it were a bit taller, so we'll introduce a multiplier to scale up the lines a bit. Open up the renderer:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">AudioVisualizer.Renderer</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">@center_y</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">500</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">@resolution</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">16</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">@multiplier</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">3</span> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:wxGraphicsContext</span>.setPen(canvas, pen) | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:wxGraphicsContext</span>.drawLines(canvas, [ | |
| {x, <span class="pl-vo" style="box-sizing: border-box;">@center_y</span>}, | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Add the multiplier to our y value</span> | |
| {x, <span class="pl-vo" style="box-sizing: border-box;">@center_y</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">+</span> (<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">128</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">+</span> amplitude) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">*</span> <span class="pl-vo" style="box-sizing: border-box;">@multiplier</span>} | |
| ]) | |
| _ <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:ok</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">((( music again )))</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Alright, run it again and it should look a little nicer.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">OK, so there are a few issues. The biggest thing I'd like to fix next are extracting the sampling of our data from the drawing of the lines - it's ridiculous that those two things are intertwined presently. Also, we'd like to draw one big long line rather than 1000 individual ones. This is all in the renderer:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> draw_lines(canvas, dc, data) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # We'll sample the data first</span> | |
| sampled_data <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> sample(data) | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # We'll also introduce a function to generate points from the sampled data</span> | |
| do_draw_lines(canvas, dc, points(sampled_data)) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Sampling the data is a basic recursive function</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> sample(data) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| sample(data, []) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> sample([{amplitude, position}<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span>rest], acc) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">case</span> rem(position, <span class="pl-vo" style="box-sizing: border-box;">@resolution</span>) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| sample(rest, [{amplitude, position}<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span>acc]) | |
| _ <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| sample(rest, acc) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # We'll reverse it at the end since we reversed it when recursing</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> sample([], acc), <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span>: <span class="pl-vo" style="box-sizing: border-box;">Enum</span>.reverse(acc) | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Here we just generate our graphics points based on the input data</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> points(sampled_data) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">Enum</span>.map(sampled_data, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">fn</span>({amplitude, position}) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| x <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">+</span> position<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">/</span><span class="pl-vo" style="box-sizing: border-box;">@resolution</span> | |
| y <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">128</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">+</span> amplitude <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">*</span> <span class="pl-vo" style="box-sizing: border-box;">@multiplier</span> | |
| {x, <span class="pl-vo" style="box-sizing: border-box;">@center_y</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">+</span> y} | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> do_draw_lines(_canvas, _dc, []), <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span>: <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:ok</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> do_draw_lines(canvas, dc, points) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:wxPaintDC</span>.clear(dc) | |
| pen <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:wxPen</span>.new({<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">255</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">255</span>}) | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:wxGraphicsContext</span>.setPen(canvas, pen) | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Finally we just pass those points into the drawLines function</span> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:wxGraphicsContext</span>.drawLines(canvas, points) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">With that in place, it looks a bit nicer. Let's have a look.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">((( music again )))</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">((( do it )))</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Summary</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Alright, so that works. In today's episode we saw how to use wxGraphics to build a visualizer for 8 bit unsigned 16kilohertz PCM audio. It's not the most beautiful thing in the world, but that's almost entirely down to me doing some ridiculously inefficient things in my wx code, like creating 100 new canvases every second and not using buffered drawing. Still, it's pretty neat, and it was pretty trivial to build. See you soon!</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Resources</h2> | |
| <ul class="task-list" style="box-sizing: border-box; padding-right: 0px; padding-left: 2em; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <li style="box-sizing: border-box;"><a href="https://github.com/knewter/audio_visualizer" rel="noreferrer" style="box-sizing: border-box; color: rgb(65, 131, 196); text-decoration: none;">knewter/audio_visualizer</a></li> | |
| </ul> | |
| </div> | |
| <h3>Attached Files</h3> | |
| <ul> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=54655">177_Audio_Visualizer.mp4</a></li> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=54656">177_Audio_Visualizer.markdown</a></li> | |
| </ul></div>]]></description> | |
| <guid isPermaLink="false">dpd-e89f67fe3386e8401a6b4be13f16ab49a846bcc2</guid> | |
| <pubDate>Wed, 15 Jul 2015 08:14:00 -0400</pubDate> | |
| <enclosure url="https://elixirsips.dpdcart.com/feed/download/54655/177_Audio_Visualizer.mp4" length="84637814" type="video/mp4"/> | |
| </item> | |
| <item> | |
| <title><![CDATA[176 - Prettying Up ElixirFriends]]></title> | |
| <link>https://elixirsips.dpdcart.com/subscriber/post?id=832</link> | |
| <description><![CDATA[<div class="blog-entry"> | |
| <div class="blog-content"><h1 style="box-sizing: border-box; font-size: 2.25em; margin-right: 0px; margin-bottom: 16px; margin-left: 0px; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; margin-top: 0px !important;">Episode 176: Prettying Up ElixirFriends</h1> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">In the last episode, I pointed out that this wasn't CSS Sips. However, I'm kind of miffed that ElixirFriends looks ugly, so today we'll look at integrating Semantic UI into it and removing the CRUD actions that we don't really need. Let's get started.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">NOTE: There's definitely stuff in this video that's not in the script; specifically, I add styles for pagination and support for active links at the end of the video.</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Project</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Well, so it's not entirely CSS related. First off, we'll remove the CRUD bits from posts...</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| scope <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>/<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, <span class="pl-vo" style="box-sizing: border-box;">ElixirFriends</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| pipe_through <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:browser</span> <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"># Use the default browser stack</span> | |
| get <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>/<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, <span class="pl-vo" style="box-sizing: border-box;">PostController</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:index</span> | |
| resources <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>/posts<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, <span class="pl-vo" style="box-sizing: border-box;">PostController</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">only:</span> [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:show</span>] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <div class="highlight highlight-html" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">td</span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">class</span>=<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>text-right<span class="pl-pds" style="box-sizing: border-box;">"</span></span>> | |
| <%= link "Show", to: post_path(@conn, :show, post), class: "btn btn-default btn-xs" %> | |
| </<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">td</span>></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Next we'll install Semantic UI.</p> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 16px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; background-color: rgb(247, 247, 247);"> | |
| <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0px; margin: 0px; border-radius: 3px; word-break: normal; white-space: pre; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;">npm install semantic-ui --save | |
| cd semantic | |
| gulp build | |
| </code></pre> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">We'll copy the distribution into the vendor directory:</p> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 16px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; background-color: rgb(247, 247, 247);"> | |
| <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0px; margin: 0px; border-radius: 3px; word-break: normal; white-space: pre; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;">cp semantic/dist/semantic.js web/static/vendor/ | |
| cp semantic/dist/semantic.css web/static/vendor/ | |
| </code></pre> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Semantic UI assumes we have jQuery:</p> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 16px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; background-color: rgb(247, 247, 247);"> | |
| <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0px; margin: 0px; border-radius: 3px; word-break: normal; white-space: pre; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;">cd web/static/vendor | |
| wget http://code.jquery.com/jquery-1.11.3.js | |
| </code></pre> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Let's clear out the existing bootstrappy Phoenix CSS:</p> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 16px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; background-color: rgb(247, 247, 247);"> | |
| <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0px; margin: 0px; border-radius: 3px; word-break: normal; white-space: pre; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;">vim web/static/css/app.css | |
| </code></pre> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">((( clear it out )))</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Now we want to just show a card for each post:</p> | |
| <div class="highlight highlight-html" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">h2</span>>Look at all these people! They came together because of <%= link "Elixir!", to: "http://www.elixir-lang.org" %></<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">h2</span>> | |
| <%= pagination_links(@posts_page) %> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">div</span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">class</span>=<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>ui grid<span class="pl-pds" style="box-sizing: border-box;">"</span></span>> | |
| <%= for post <- @posts_page.entries do %> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">div</span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">class</span>=<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>four wide column<span class="pl-pds" style="box-sizing: border-box;">"</span></span>> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">div</span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">class</span>=<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>ui card<span class="pl-pds" style="box-sizing: border-box;">"</span></span>> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">div</span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">class</span>=<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>image<span class="pl-pds" style="box-sizing: border-box;">"</span></span>> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">img</span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">src</span>=<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">'</span><%= post.image_url %><span class="pl-pds" style="box-sizing: border-box;">'</span></span> /> | |
| </<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">div</span>> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">div</span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">class</span>=<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>content<span class="pl-pds" style="box-sizing: border-box;">"</span></span>> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">div</span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">class</span>=<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>header<span class="pl-pds" style="box-sizing: border-box;">"</span></span>> | |
| elixirsips # here we want to show a username but we aren't storing this yet | |
| </<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">div</span>> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">div</span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">class</span>=<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>meta<span class="pl-pds" style="box-sizing: border-box;">"</span></span>> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">span</span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">class</span>=<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>date<span class="pl-pds" style="box-sizing: border-box;">"</span></span>><%= post.inserted_at %></<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">span</span>> | |
| </<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">div</span>> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">div</span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">class</span>=<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>description<span class="pl-pds" style="box-sizing: border-box;">"</span></span>> | |
| <%= post.content %> | |
| </<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">div</span>> | |
| </<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">div</span>> | |
| </<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">div</span>> | |
| </<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">div</span>> | |
| <% end %> | |
| </<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">div</span>> | |
| <%= pagination_links(@posts_page) %></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">We'll also tweak the application layout a bit...</p> | |
| <div class="highlight highlight-html" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <!DOCTYPE html> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">html</span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">lang</span>=<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>en<span class="pl-pds" style="box-sizing: border-box;">"</span></span>> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">head</span>> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">meta</span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">charset</span>=<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>utf-8<span class="pl-pds" style="box-sizing: border-box;">"</span></span>> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">meta</span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">http-equiv</span>=<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>X-UA-Compatible<span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">content</span>=<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>IE=edge<span class="pl-pds" style="box-sizing: border-box;">"</span></span>> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">meta</span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">name</span>=<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>viewport<span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">content</span>=<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>width=device-width, initial-scale=1<span class="pl-pds" style="box-sizing: border-box;">"</span></span>> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">meta</span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">name</span>=<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>description<span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">content</span>=<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">meta</span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">name</span>=<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>author<span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">content</span>=<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">title</span>>ElixirFriends!</<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">title</span>> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">link</span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">rel</span>=<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>stylesheet<span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">href</span>=<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span><%= static_path(@conn, <span class="pl-pds" style="box-sizing: border-box;">"</span></span>/<span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">css</span>/<span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">app</span>.<span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">css</span><span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>) %><span class="pl-pds" style="box-sizing: border-box;">"</span></span>> | |
| </<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">head</span>> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">body</span>> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">div</span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">class</span>=<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>ui container<span class="pl-pds" style="box-sizing: border-box;">"</span></span>> | |
| <%= @inner %> | |
| </<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">div</span>> | |
| <span class="pl-s2" style="box-sizing: border-box;"> <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">script</span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">src</span>=<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span><%= static_path(@conn, <span class="pl-pds" style="box-sizing: border-box;">"</span></span>/<span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">js</span>/<span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">app</span>.<span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">js</span><span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>) %><span class="pl-pds" style="box-sizing: border-box;">"</span></span>></<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">script</span>></span> | |
| <span class="pl-s2" style="box-sizing: border-box;"> <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">script</span>><span class="pl-s3" style="box-sizing: border-box; color: rgb(0, 134, 179);">require</span>(<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>web/static/js/app<span class="pl-pds" style="box-sizing: border-box;">"</span></span>)</<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">script</span>></span> | |
| </<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">body</span>> | |
| </<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">html</span>></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">OK now we actually need to do some elixir. We need to store the username on posts to show it, so we'll add a migration to store that:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| mix ecto.gen.migration add_username_to_posts</pre> | |
| </div> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">ElixirFriends.Repo.Migrations.AddUsernameToPosts</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">use</span> <span class="pl-vo" style="box-sizing: border-box;">Ecto</span>.<span class="pl-vo" style="box-sizing: border-box;">Migration</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> change <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| alter table(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:posts</span>) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| add <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:username</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:string</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Alright, so we've added username as a string to the database table. We also need to add it to the struct, so open up <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">web/models/post.ex</code> and we'll do that:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| schema <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>posts<span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| field <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:image_url</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:string</span> | |
| field <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:content</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:string</span> | |
| field <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:source_url</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:string</span> | |
| field <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:username</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:string</span> | |
| timestamps | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Alright, now we'll modify the Streamer to store the username as well:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defp</span> store_tweet(%<span class="pl-vo" style="box-sizing: border-box;">ExTwitter</span>.<span class="pl-vo" style="box-sizing: border-box;">Model</span>.<span class="pl-vo" style="box-sizing: border-box;">Tweet</span>{}<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span>tweet) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| post <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> %<span class="pl-vo" style="box-sizing: border-box;">ElixirFriends</span>.<span class="pl-vo" style="box-sizing: border-box;">Post</span>{ | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">image_url:</span> first_photo(tweet).media_url, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">content:</span> tweet.text, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">source_url:</span> first_photo(tweet).expanded_url, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">username:</span> tweet.user.screen_name | |
| } | |
| <span class="pl-vo" style="box-sizing: border-box;">ElixirFriends</span>.<span class="pl-vo" style="box-sizing: border-box;">Repo</span>.insert!(post) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Now that that's done, we're storing the usernames as well as the tweets now for display. We'll add it to the view and then check it out...</p> | |
| <div class="highlight highlight-html" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">div</span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">class</span>=<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>header<span class="pl-pds" style="box-sizing: border-box;">"</span></span>> | |
| <%= post.username %> | |
| </<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">div</span>></pre> | |
| </div> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| mix phoenix.server</pre> | |
| </div> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Resources</h2> | |
| <ul class="task-list" style="box-sizing: border-box; padding-right: 0px; padding-left: 2em; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <li style="box-sizing: border-box;"><a href="http://semantic-ui.com/" rel="noreferrer" style="box-sizing: border-box; color: rgb(65, 131, 196); text-decoration: none;">Semantic UI</a></li> | |
| <li style="box-sizing: border-box;"><a href="http://www.elixirfriends.com/" rel="noreferrer" style="box-sizing: border-box; color: rgb(65, 131, 196); text-decoration: none;">ElixirFriends</a></li> | |
| <li style="box-sizing: border-box;"><a href="https://github.com/knewter/elixir_friends" rel="noreferrer" style="box-sizing: border-box; color: rgb(65, 131, 196); text-decoration: none;">knewter/elixir_friends</a></li> | |
| </ul> | |
| </div> | |
| <h3>Attached Files</h3> | |
| <ul> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=54023">176_Prettying_Up_ElixirFriends.mp4</a></li> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=54024">176_Prettying_Up_ElixirFriends.markdown</a></li> | |
| </ul></div>]]></description> | |
| <guid isPermaLink="false">dpd-77a5ef4499e5c5f142f04b0e87b5f06f6801fb84</guid> | |
| <pubDate>Thu, 09 Jul 2015 22:15:00 -0400</pubDate> | |
| <enclosure url="https://elixirsips.dpdcart.com/feed/download/54023/176_Prettying_Up_ElixirFriends.mp4" length="82590090" type="video/mp4"/> | |
| </item> | |
| <item> | |
| <title><![CDATA[175 - Pagination with Ecto and Phoenix using Scrivener]]></title> | |
| <link>https://elixirsips.dpdcart.com/subscriber/post?id=830</link> | |
| <description><![CDATA[<div class="blog-entry"> | |
| <div class="blog-content"><h1 style="box-sizing: border-box; font-size: 2.25em; margin-right: 0px; margin-bottom: 16px; margin-left: 0px; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; margin-top: 0px !important;">Episode 175: Pagination with Ecto and Phoenix using Scrivener</h1> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">In the last episode we built a background task that would save tweets from a search on twitter into our database. Since then we've gathered...quite a bit of data, and we would like to display it in pages. Let's get started.</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Project</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Drew Olsen wrote a nice package called Scrivener that we can use to paginate our Ecto queries. We'll add Scrivener to the project:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:scrivener</span>, <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>~> 0.9.0<span class="pl-pds" style="box-sizing: border-box;">"</span></span>}</pre> | |
| </div> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| mix deps.get</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Then we'll update our controller to use it to paginate:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">import</span> <span class="pl-vo" style="box-sizing: border-box;">Ecto</span>.<span class="pl-vo" style="box-sizing: border-box;">Query</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-vo" style="box-sizing: border-box;">ElixirFriends</span>.<span class="pl-vo" style="box-sizing: border-box;">Post</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> index(conn, params) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| posts_page <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-vo" style="box-sizing: border-box;">Post</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> order_by([p], <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">desc:</span> p.inserted_at) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-vo" style="box-sizing: border-box;">ElixirFriends</span>.<span class="pl-vo" style="box-sizing: border-box;">Repo</span>.paginate(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">page:</span> params[<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>page<span class="pl-pds" style="box-sizing: border-box;">"</span></span>]) | |
| render(conn, <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>index.html<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">posts_page:</span> posts_page) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <div class="highlight highlight-html" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <%= for post <- @posts_page.entries do %></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">So this works, but now we want to show pagination links. We'll replace the new post link with a link to other pages:</p> | |
| <div class="highlight highlight-html" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <%= pagination_links(@posts_page) %></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Of course that won't work yet because no such function exists. We'll put it in the PostsView:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> pagination_links(page) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>zomg pages go here<span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">We can refresh, and we'll at least see that this helper is outputting some text. Next we want it to output a link. Let's make it just output a link to page 2.</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> pagination_links(page) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| link(<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>2<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">to:</span> <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>?page=2<span class="pl-pds" style="box-sizing: border-box;">"</span></span>]) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">OK, so we can click that link and it works. That's pretty cool, but it sure would be nice to go to other pages. We'll add a list of links:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> pagination_links(paginator) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| links <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-vo" style="box-sizing: border-box;">Enum</span>.map((<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">..</span>paginator.total_pages), <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">fn</span>(page_number) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| content_tag(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:li</span>, link(<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-s2" style="box-sizing: border-box; color: rgb(51, 51, 51);"><span class="pl-pse" style="box-sizing: border-box;">#{</span>page_number<span class="pl-pse" style="box-sizing: border-box;">}</span></span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>, [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">to:</span> <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>?page=<span class="pl-s2" style="box-sizing: border-box; color: rgb(51, 51, 51);"><span class="pl-pse" style="box-sizing: border-box;">#{</span>page_number<span class="pl-pse" style="box-sizing: border-box;">}</span></span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>])) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span>) | |
| content_tag(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:ul</span>, links) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Now if we refresh it, we can see a link to every single page...so that's something. It would be better to have a limit to the number of links, so for starters we'll just say there can only be 10 links on the page and it starts at the current page:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> pagination_links(paginator) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| total_links <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">10</span> | |
| links <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> (paginator.page_number<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">..</span>paginator.total_pages) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-vo" style="box-sizing: border-box;">Enum</span>.take(total_links) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-vo" style="box-sizing: border-box;">Enum</span>.map(<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">fn</span>(page_number) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| content_tag(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:li</span>, link(<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-s2" style="box-sizing: border-box; color: rgb(51, 51, 51);"><span class="pl-pse" style="box-sizing: border-box;">#{</span>page_number<span class="pl-pse" style="box-sizing: border-box;">}</span></span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>, [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">to:</span> <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>?page=<span class="pl-s2" style="box-sizing: border-box; color: rgb(51, 51, 51);"><span class="pl-pse" style="box-sizing: border-box;">#{</span>page_number<span class="pl-pse" style="box-sizing: border-box;">}</span></span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>])) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span>) | |
| content_tag(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:ul</span>, links) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Next, we'd like a link to the first page and the last page to always be there, so if the current page isn't 1 we'll put a 1, and if it's not <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">total_pages</code> we'll put that in there...</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> pagination_links(paginator) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| total_links <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">10</span> | |
| page_numbers <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> (paginator.page_number<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">..</span>paginator.total_pages) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-vo" style="box-sizing: border-box;">Enum</span>.to_list | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">if</span> paginator.page_number <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">!==</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| page_numbers <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span>page_numbers] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| links <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> page_numbers | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-vo" style="box-sizing: border-box;">Enum</span>.take(total_links) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-vo" style="box-sizing: border-box;">Enum</span>.map(<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">fn</span>(page_number) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| content_tag(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:li</span>, link(<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-s2" style="box-sizing: border-box; color: rgb(51, 51, 51);"><span class="pl-pse" style="box-sizing: border-box;">#{</span>page_number<span class="pl-pse" style="box-sizing: border-box;">}</span></span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>, [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">to:</span> <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>?page=<span class="pl-s2" style="box-sizing: border-box; color: rgb(51, 51, 51);"><span class="pl-pse" style="box-sizing: border-box;">#{</span>page_number<span class="pl-pse" style="box-sizing: border-box;">}</span></span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>])) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span>) | |
| content_tag(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:ul</span>, links) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">We'd also like to have a link to the last page...</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> pagination_links(paginator) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| total_links <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">10</span> | |
| page_numbers <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> (paginator.page_number<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">..</span>paginator.total_pages) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-vo" style="box-sizing: border-box;">Enum</span>.to_list | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">if</span> paginator.page_number <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">!==</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| page_numbers <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span>page_numbers] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| page_numbers <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-vo" style="box-sizing: border-box;">Enum</span>.take(page_numbers, total_links) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">if</span> paginator.page_number <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">!==</span> paginator.total_pages <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| page_numbers <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> page_numbers <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">++</span> [paginator.total_pages] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| links <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> page_numbers | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-vo" style="box-sizing: border-box;">Enum</span>.map(<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">fn</span>(page_number) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| content_tag(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:li</span>, link(<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-s2" style="box-sizing: border-box; color: rgb(51, 51, 51);"><span class="pl-pse" style="box-sizing: border-box;">#{</span>page_number<span class="pl-pse" style="box-sizing: border-box;">}</span></span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>, [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">to:</span> <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>?page=<span class="pl-s2" style="box-sizing: border-box; color: rgb(51, 51, 51);"><span class="pl-pse" style="box-sizing: border-box;">#{</span>page_number<span class="pl-pse" style="box-sizing: border-box;">}</span></span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>])) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span>) | |
| content_tag(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:ul</span>, links) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">OK, so this is getting hairy. Let's move <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">total_links</code> to a module attribute for now and turn the page numbers list into a function:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">ElixirFriends.PostView</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">use</span> <span class="pl-vo" style="box-sizing: border-box;">ElixirFriends</span>.<span class="pl-vo" style="box-sizing: border-box;">Web</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:view</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">@total_links</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">10</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> pagination_links(paginator) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| links <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> page_numbers(paginator) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-vo" style="box-sizing: border-box;">Enum</span>.map(<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">fn</span>(page_number) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| content_tag(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:li</span>, link(<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-s2" style="box-sizing: border-box; color: rgb(51, 51, 51);"><span class="pl-pse" style="box-sizing: border-box;">#{</span>page_number<span class="pl-pse" style="box-sizing: border-box;">}</span></span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>, [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">to:</span> <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>?page=<span class="pl-s2" style="box-sizing: border-box; color: rgb(51, 51, 51);"><span class="pl-pse" style="box-sizing: border-box;">#{</span>page_number<span class="pl-pse" style="box-sizing: border-box;">}</span></span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>])) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span>) | |
| content_tag(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:ul</span>, links) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defp</span> page_numbers(paginator) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| page_numbers <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> (paginator.page_number<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">..</span>paginator.total_pages) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-vo" style="box-sizing: border-box;">Enum</span>.to_list | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">if</span> paginator.page_number <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">!==</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| page_numbers <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span>page_numbers] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| page_numbers <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-vo" style="box-sizing: border-box;">Enum</span>.take(page_numbers, <span class="pl-vo" style="box-sizing: border-box;">@total_links</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">if</span> paginator.page_number <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">!==</span> paginator.total_pages <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| page_numbers <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> page_numbers <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">++</span> [paginator.total_pages] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| page_numbers | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">OK, so this is a functional bit of pagination but pretty awful, and there's no next or previous links. Let's first extract the page link bit into its own function:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">ElixirFriends.PostView</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">use</span> <span class="pl-vo" style="box-sizing: border-box;">ElixirFriends</span>.<span class="pl-vo" style="box-sizing: border-box;">Web</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:view</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">@total_links</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">10</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> pagination_links(paginator) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| links <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> page_numbers(paginator) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-vo" style="box-sizing: border-box;">Enum</span>.map(<span class="pl-vo" style="box-sizing: border-box;">&</span>page_link<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">/</span><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1</span>) | |
| content_tag(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:ul</span>, links) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defp</span> page_numbers(paginator) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| page_numbers <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> (paginator.page_number<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">..</span>paginator.total_pages) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-vo" style="box-sizing: border-box;">Enum</span>.to_list | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">if</span> paginator.page_number <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">!==</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| page_numbers <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span>page_numbers] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| page_numbers <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-vo" style="box-sizing: border-box;">Enum</span>.take(page_numbers, <span class="pl-vo" style="box-sizing: border-box;">@total_links</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">if</span> paginator.page_number <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">!==</span> paginator.total_pages <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| page_numbers <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> page_numbers <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">++</span> [paginator.total_pages] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| page_numbers | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defp</span> page_link(page_number) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| content_tag(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:li</span>, link(<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-s2" style="box-sizing: border-box; color: rgb(51, 51, 51);"><span class="pl-pse" style="box-sizing: border-box;">#{</span>page_number<span class="pl-pse" style="box-sizing: border-box;">}</span></span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>, [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">to:</span> <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>?page=<span class="pl-s2" style="box-sizing: border-box; color: rgb(51, 51, 51);"><span class="pl-pse" style="box-sizing: border-box;">#{</span>page_number<span class="pl-pse" style="box-sizing: border-box;">}</span></span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>])) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Now, since next and previous will have different text than the page they link to, this function should take two arguments:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">ElixirFriends.PostView</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">use</span> <span class="pl-vo" style="box-sizing: border-box;">ElixirFriends</span>.<span class="pl-vo" style="box-sizing: border-box;">Web</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:view</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">@total_links</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">10</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> pagination_links(paginator) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| links <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> page_numbers(paginator) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-vo" style="box-sizing: border-box;">Enum</span>.map(<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">fn</span>(page_number) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| page_link(page_number, page_number) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span>) | |
| content_tag(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:ul</span>, links) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defp</span> page_numbers(paginator) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| page_numbers <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> (paginator.page_number<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">..</span>paginator.total_pages) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-vo" style="box-sizing: border-box;">Enum</span>.to_list | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">if</span> paginator.page_number <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">!==</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| page_numbers <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span>page_numbers] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| page_numbers <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-vo" style="box-sizing: border-box;">Enum</span>.take(page_numbers, <span class="pl-vo" style="box-sizing: border-box;">@total_links</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">if</span> paginator.page_number <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">!==</span> paginator.total_pages <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| page_numbers <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> page_numbers <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">++</span> [paginator.total_pages] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| page_numbers | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defp</span> page_link(text, page_number) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| content_tag(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:li</span>, link(<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-s2" style="box-sizing: border-box; color: rgb(51, 51, 51);"><span class="pl-pse" style="box-sizing: border-box;">#{</span>text<span class="pl-pse" style="box-sizing: border-box;">}</span></span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>, [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">to:</span> <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>?page=<span class="pl-s2" style="box-sizing: border-box; color: rgb(51, 51, 51);"><span class="pl-pse" style="box-sizing: border-box;">#{</span>page_number<span class="pl-pse" style="box-sizing: border-box;">}</span></span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>])) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Now we just need to add our next and previous links if they're applicable:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">ElixirFriends.PostView</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">use</span> <span class="pl-vo" style="box-sizing: border-box;">ElixirFriends</span>.<span class="pl-vo" style="box-sizing: border-box;">Web</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:view</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">@total_links</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">10</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> pagination_links(paginator) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| links <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> page_numbers(paginator) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-vo" style="box-sizing: border-box;">Enum</span>.map(<span class="pl-vo" style="box-sizing: border-box;">&</span>page_link<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">/</span><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1</span>) | |
| content_tag(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:ul</span>, links) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defp</span> page_numbers(paginator) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| page_numbers <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> (paginator.page_number<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">..</span>paginator.total_pages) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-vo" style="box-sizing: border-box;">Enum</span>.to_list | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">if</span> paginator.page_number <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">!==</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| page_numbers <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> [{<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span><<<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, paginator.page_number<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1</span>}, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1</span>] <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">++</span> page_numbers | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| page_numbers <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-vo" style="box-sizing: border-box;">Enum</span>.take(page_numbers, <span class="pl-vo" style="box-sizing: border-box;">@total_links</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">if</span> paginator.page_number <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">!==</span> paginator.total_pages <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| page_numbers <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> page_numbers <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">++</span> [paginator.total_pages, {<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>>><span class="pl-pds" style="box-sizing: border-box;">"</span></span>, paginator.page_number<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">+</span><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1</span>}] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| page_numbers | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defp</span> page_link({text, page_number}) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| content_tag(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:li</span>, link(<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-s2" style="box-sizing: border-box; color: rgb(51, 51, 51);"><span class="pl-pse" style="box-sizing: border-box;">#{</span>text<span class="pl-pse" style="box-sizing: border-box;">}</span></span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>, [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">to:</span> <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>?page=<span class="pl-s2" style="box-sizing: border-box; color: rgb(51, 51, 51);"><span class="pl-pse" style="box-sizing: border-box;">#{</span>page_number<span class="pl-pse" style="box-sizing: border-box;">}</span></span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>])) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defp</span> page_link(page_number) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| content_tag(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:li</span>, link(<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-s2" style="box-sizing: border-box; color: rgb(51, 51, 51);"><span class="pl-pse" style="box-sizing: border-box;">#{</span>page_number<span class="pl-pse" style="box-sizing: border-box;">}</span></span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>, [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">to:</span> <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>?page=<span class="pl-s2" style="box-sizing: border-box; color: rgb(51, 51, 51);"><span class="pl-pse" style="box-sizing: border-box;">#{</span>page_number<span class="pl-pse" style="box-sizing: border-box;">}</span></span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>])) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Summary</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Alright, so this isn't gorgeous yet but it works. This isn't CSS Sips so I think we're going to call it good enough for now. I'll clean up the design a bit later, but for now this should be enough to help you build pagination for your apps. See you soon!</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Resources</h2> | |
| <ul class="task-list" style="box-sizing: border-box; padding-right: 0px; padding-left: 2em; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <li style="box-sizing: border-box;"><a href="https://github.com/drewolson/scrivener" rel="noreferrer" style="box-sizing: border-box; color: rgb(65, 131, 196); text-decoration: none;">drewolson/scrivener</a></li> | |
| </ul> | |
| </div> | |
| <h3>Attached Files</h3> | |
| <ul> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=53862">175_Pagination_with_Ecto_and_Phoenix.mp4</a></li> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=53863">175_Pagination_with_Ecto_and_Phoenix.markdown</a></li> | |
| </ul></div>]]></description> | |
| <guid isPermaLink="false">dpd-f7e4514da1091c766202dcf068ad48931a508110</guid> | |
| <pubDate>Tue, 07 Jul 2015 22:24:00 -0400</pubDate> | |
| <enclosure url="https://elixirsips.dpdcart.com/feed/download/53862/175_Pagination_with_Ecto_and_Phoenix.mp4" length="74655257" type="video/mp4"/> | |
| </item> | |
| <item> | |
| <title><![CDATA[174 - ElixirFriends: Saving Tweets with Streams and Filters]]></title> | |
| <link>https://elixirsips.dpdcart.com/subscriber/post?id=822</link> | |
| <description><![CDATA[<div class="blog-entry"> | |
| <div class="blog-content"><h1 style="box-sizing: border-box; font-size: 2.25em; margin-right: 0px; margin-bottom: 16px; margin-left: 0px; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; margin-top: 0px !important;">Episode 174: ElixirFriends - Saving Tweets with Streams and Filters</h1> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">In today's episode we're going to update the ElixirFriends application that we used for our Continuous Integration and Continuous Deployment episodes to constantly save any tweets that are tagged with #elixirfriends into the database as posts so we can display them. We'll only be storing tweets that have attached images. Let's get started.</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Project</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">We're going to start off by adding ExTwitter to our project. We've done previous episodes on ExTwitter, so if you don't know how it works you can check those out.</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:extwitter</span>, <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>~> 0.4<span class="pl-pds" style="box-sizing: border-box;">"</span></span>}, | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:oauth</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">github:</span> <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>tim/erlang-oauth<span class="pl-pds" style="box-sizing: border-box;">"</span></span>},</pre> | |
| </div> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| mix deps.get</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">We also need to configure it, so open up config/config.exs:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| config <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:ex_twitter</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:oauth</span>, [ | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">consumer_key:</span> <span class="pl-vo" style="box-sizing: border-box;">System</span>.get_env(<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>TWITTER_CONSUMER_KEY<span class="pl-pds" style="box-sizing: border-box;">"</span></span>), | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">consumer_secret:</span> <span class="pl-vo" style="box-sizing: border-box;">System</span>.get_env(<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>TWITTER_CONSUMER_SECRET<span class="pl-pds" style="box-sizing: border-box;">"</span></span>), | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">access_token:</span> <span class="pl-vo" style="box-sizing: border-box;">System</span>.get_env(<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>TWITTER_ACCESS_TOKEN<span class="pl-pds" style="box-sizing: border-box;">"</span></span>), | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">access_token_secret:</span> <span class="pl-vo" style="box-sizing: border-box;">System</span>.get_env(<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>TWITTER_ACCESS_SECRET<span class="pl-pds" style="box-sizing: border-box;">"</span></span>) | |
| ]</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">We are going to be streaming ExTwitter.Model.Tweets into our database. The structure of one of those is as follows:</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">((( open the README and paste this in )))</p> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 16px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; background-color: rgb(247, 247, 247);"> | |
| <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0px; margin: 0px; border-radius: 3px; word-break: normal; white-space: pre; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;">%ExTwitter.Model.Tweet{contributors: nil, coordinates: nil, | |
| created_at: "Thu Jul 02 12:41:00 +0000 2015", | |
| entities: %{hashtags: [], symbols: [], | |
| urls: [%{display_url: "bit.ly/1GQjkm6", | |
| expanded_url: "http://bit.ly/1GQjkm6", indices: 'Qg', | |
| url: "http://t.co/glk1sfwhDz"}], user_mentions: []}, favorite_count: 0, | |
| favorited: false, geo: nil, id: 616587375062290432, | |
| id_str: "616587375062290432", in_reply_to_screen_name: nil, | |
| in_reply_to_status_id: nil, in_reply_to_status_id_str: nil, | |
| in_reply_to_user_id: nil, in_reply_to_user_id_str: nil, lang: "en", place: nil, | |
| retweet_count: 0, retweeted: false, | |
| source: "<a href=\"http://twitterfeed.com\" rel=\"nofollow\">twitterfeed</a>", | |
| text: "lang/elixir/bsd.elixir.mk @ 391136: Add helper makefile for Elixir applications. http://t.co/glk1sfwhDz", | |
| truncated: false, | |
| user: %ExTwitter.Model.User{contributors_enabled: false, utc_offset: -14400, | |
| following: false, follow_request_sent: false, id_str: "2218195068", | |
| profile_background_color: "C0DEED", | |
| profile_image_url: "http://pbs.twimg.com/profile_images/378800000812206542/e0e817590ddd46782ffbe848a4244d88_normal.png", | |
| followers_count: 39, | |
| description: "Tweets of FreeBSD Ports code changes, managed by @swills", | |
| default_profile: true, | |
| entities: %{description: %{urls: []}, | |
| url: %{urls: [%{display_url: "src.mouf.net/ports", | |
| expanded_url: "http://src.mouf.net/ports", indices: [0, 22], | |
| url: "http://t.co/ZYzYhwEh4z"}]}}, | |
| created_at: "Wed Nov 27 17:54:25 +0000 2013", location: "", | |
| geo_enabled: false, statuses_count: 567, name: "FreeBSD Ports", | |
| screen_name: "fbsdports", profile_sidebar_border_color: "C0DEED", | |
| profile_background_tile: false, time_zone: "Eastern Time (US & Canada)", | |
| default_profile_image: false, friends_count: 1, favourites_count: 0, | |
| is_translator: false, id: 2218195068, lang: "en", | |
| profile_background_image_url_https: "https://abs.twimg.com/images/themes/theme1/bg.png", | |
| notifications: false, | |
| profile_background_image_url: "http://abs.twimg.com/images/themes/theme1/bg.png", | |
| listed_count: 6, is_translation_enabled: false, protected: false, | |
| profile_image_url_https: "https://pbs.twimg.com/profile_images/378800000812206542/e0e817590ddd46782ffbe848a4244d88_normal.png", | |
| profile_text_color: "333333", profile_sidebar_fill_color: "DDEEF6", | |
| verified: false, profile_link_color: "0084B4", | |
| profile_use_background_image: true, url: "http://t.co/ZYzYhwEh4z"}} | |
| </code></pre> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Now we'll write the meat of the streamer, which we'll put in<code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">lib/elixir_friends/image_tweet_streamer.ex</code>:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">ElixirFriends.ImageTweetStreamer</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # We want to allow you to pass a search term in...</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> stream(search_term) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # We'll search for that with a stream filter</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">ExTwitter</span>.stream_filter(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">track:</span> search_term) | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # We'll filter out any tweets that don't have images</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-vo" style="box-sizing: border-box;">Stream</span>.filter(<span class="pl-vo" style="box-sizing: border-box;">&</span>has_images?<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">/</span><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1</span>) | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # And we'll store them in our database</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-vo" style="box-sizing: border-box;">Stream</span>.map(<span class="pl-vo" style="box-sizing: border-box;">&</span>store_tweet<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">/</span><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Checking a tweet for images is easy:</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defp</span> has_images?(%<span class="pl-vo" style="box-sizing: border-box;">ExTwitter</span>.<span class="pl-vo" style="box-sizing: border-box;">Model</span>.<span class="pl-vo" style="box-sizing: border-box;">Tweet</span>{}<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span>tweet) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">Map</span>.has_key?(tweet.entities, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:media</span>) <span class="pl-vo" style="box-sizing: border-box;">&&</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">Enum</span>.any?(photos(tweet)) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Storing a tweet just consists of grabbing the first photo from the tweet and</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # creating a Post in our database</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defp</span> store_tweet(%<span class="pl-vo" style="box-sizing: border-box;">ExTwitter</span>.<span class="pl-vo" style="box-sizing: border-box;">Model</span>.<span class="pl-vo" style="box-sizing: border-box;">Tweet</span>{}<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span>tweet) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">IO</span>.puts <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>storing this tweet: <span class="pl-s2" style="box-sizing: border-box; color: rgb(51, 51, 51);"><span class="pl-pse" style="box-sizing: border-box;">#{</span>inspect(tweet, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">pretty:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">true</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">limit:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">2_000</span>)<span class="pl-pse" style="box-sizing: border-box;">}</span></span><span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| post <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> %<span class="pl-vo" style="box-sizing: border-box;">ElixirFriends</span>.<span class="pl-vo" style="box-sizing: border-box;">Post</span>{ | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">image_url:</span> first_photo(tweet).media_url, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">content:</span> tweet.text, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">source_url:</span> first_photo(tweet).expanded_url | |
| } | |
| <span class="pl-vo" style="box-sizing: border-box;">IO</span>.puts <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>storing this post: <span class="pl-s2" style="box-sizing: border-box; color: rgb(51, 51, 51);"><span class="pl-pse" style="box-sizing: border-box;">#{</span>inspect post<span class="pl-pse" style="box-sizing: border-box;">}</span></span><span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| <span class="pl-vo" style="box-sizing: border-box;">ElixirFriends</span>.<span class="pl-vo" style="box-sizing: border-box;">Repo</span>.insert(post) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Now we need to write the `photos` function, which will return a list of the</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # photos attached to a tweet. These are media under the entities key.</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defp</span> photos(%<span class="pl-vo" style="box-sizing: border-box;">ExTwitter</span>.<span class="pl-vo" style="box-sizing: border-box;">Model</span>.<span class="pl-vo" style="box-sizing: border-box;">Tweet</span>{}<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span>tweet) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| tweet.entities.media | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-vo" style="box-sizing: border-box;">Enum</span>.filter(<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">fn</span>(medium) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| medium.type <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">==</span> <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>photo<span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Finally, we want a convenience function to grab the first photo</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defp</span> first_photo(%<span class="pl-vo" style="box-sizing: border-box;">ExTwitter</span>.<span class="pl-vo" style="box-sizing: border-box;">Model</span>.<span class="pl-vo" style="box-sizing: border-box;">Tweet</span>{}<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span>tweet) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| photos(tweet) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> hd | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">This is pretty much it, and will push a stream of tweets into our database. Now, we want to start this up when our application starts, and supervise it. I was going to create a GenServer for this but it seemed so very very wrong, because it wouldn't be able to handle any messages as it would be blocked on this stream. Luckily, Jose is a much smarter man than I am and he graced us with Supervisable Tasks, so let's see what adding a worker looks like. Open up <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">lib/elixir_friends.ex</code>:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">import</span> <span class="pl-vo" style="box-sizing: border-box;">Supervisor</span>.<span class="pl-vo" style="box-sizing: border-box;">Spec</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # For now we'll use the term 'nintendo' for our search, since no one is</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # tweeting with #elixirfriends yet!</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">@term</span> <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>nintendo<span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> #...</span> | |
| worker(<span class="pl-vo" style="box-sizing: border-box;">Task</span>, [<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">fn</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-vo" style="box-sizing: border-box;">ElixirFriends</span>.<span class="pl-vo" style="box-sizing: border-box;">ImageTweetStreamer</span>.stream(<span class="pl-vo" style="box-sizing: border-box;">@term</span>) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-vo" style="box-sizing: border-box;">Enum</span>.to_list <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span>])</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">That's the core idea. Let's go ahead and run it and see what happens:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| iex -S mix phoenix.server</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">We can watch the console for a bit here and we should see some images being stored. Once some come through we'll look at the frontend.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">((( do it )))</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Summary</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">And there we have it. Elixir makes building something like this so absurdly easy. I hope you enjoyed learning about the Supervisable Tasks - I know I plan on using them constantly. See you soon!</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Resources</h2> | |
| <ul class="task-list" style="box-sizing: border-box; padding-right: 0px; padding-left: 2em; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <li style="box-sizing: border-box;"><a href="https://github.com/parroty/extwitter" rel="noreferrer" style="box-sizing: border-box; color: rgb(65, 131, 196); text-decoration: none;">parroty/extwitter</a></li> | |
| </ul> | |
| </div> | |
| <h3>Attached Files</h3> | |
| <ul> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=53597">174_ElixirFriends_Saving_Tweets_with_Streams_and_Filters.mp4</a></li> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=53598">174_ElixirFriends_Saving_Tweets_with_Streams_and_Filters.markdown</a></li> | |
| </ul></div>]]></description> | |
| <guid isPermaLink="false">dpd-73c6ee1f9042c55bac7db761699d3871e6727c5e</guid> | |
| <pubDate>Fri, 03 Jul 2015 14:49:00 -0400</pubDate> | |
| <enclosure url="https://elixirsips.dpdcart.com/feed/download/53597/174_ElixirFriends_Saving_Tweets_with_Streams_and_Filters.mp4" length="48912121" type="video/mp4"/> | |
| </item> | |
| <item> | |
| <title><![CDATA[173 - Continuous Deployment]]></title> | |
| <link>https://elixirsips.dpdcart.com/subscriber/post?id=821</link> | |
| <description><![CDATA[<div class="blog-entry"> | |
| <div class="blog-content"><h1 style="box-sizing: border-box; font-size: 2.25em; margin: 1em 0px 16px; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Episode 173: Deploying Phoenix Applications to Heroku</h1> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">We'd like to introduce Continuous Deployment. Before that happens, we need to get our application manually deployable to Heroku. Let's get started.</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Project</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">One of the things we need to start with is allowing the production secret to go up to Heroku. For the record, storing secrets in your git repo is absolutely against my principles. I just don't know a better way around this for heroku apps with phoenix for now. So let's open up the .gitignore and allow the prod secret:</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">((( do it )))</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">For what it's worth, this isn't the secret that our app will use in production since we'll be setting an environment variable for the secret...so it's not so bad.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Alright, next let's add it to the repository:</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">((( do it )))</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Next we'll create a heroku app for it:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| heroku create elixir-friends --buildpack=https://github.com/HashNuke/heroku-buildpack-elixir</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Now we'll add the phoenix static buildpack:</p> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 16px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; background-color: rgb(247, 247, 247);"> | |
| <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0px; margin: 0px; border-radius: 3px; word-break: normal; white-space: pre; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;">heroku buildpacks:add https://github.com/gjaldon/phoenix-static-buildpack | |
| </code></pre> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Now the phoenix static buildpack will give us a good-enough default Procfile, so we don't need one of those. If we wanted to do something more interesting we could add one.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">You also need to make sure your production environment uses the <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">DATABASE_URL</code> that heroku provides. You can see mine at <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">config/prod.secret.exs</code></p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"># Configure your database</span> | |
| config <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:elixir_friends</span>, <span class="pl-vo" style="box-sizing: border-box;">ElixirFriends</span>.<span class="pl-vo" style="box-sizing: border-box;">Repo</span>, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">adapter:</span> <span class="pl-vo" style="box-sizing: border-box;">Ecto</span>.<span class="pl-vo" style="box-sizing: border-box;">Adapters</span>.<span class="pl-vo" style="box-sizing: border-box;">Postgres</span>, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">url:</span> <span class="pl-vo" style="box-sizing: border-box;">System</span>.get_env(<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>DATABASE_URL<span class="pl-pds" style="box-sizing: border-box;">"</span></span>)</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Next we'll just push it up to heroku, and we'll get a successful deploy.</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| git push heroku master</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">We also need to run the migrations:</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">``sh heroku run mix ecto.migrate</p> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 16px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; background-color: rgb(247, 247, 247);"> | |
| <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0px; margin: 0px; border-radius: 3px; word-break: normal; white-space: pre; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;"> | |
| Finally our app is up and running, and we can verify it by visiting it at | |
| http://elixir-friends.herokuapp.com/posts | |
| We'll come in here and add a post. | |
| ### Continuous Deployment | |
| Now that we've got the core heroku deployment working, we can get to the point | |
| of this episode, which is to show off Phoenix continuous deployment with | |
| Semaphore CI. The first step there is to add the semaphore addon in heroku: | |
| ```sh | |
| heroku addons:create semaphore | |
| </code></pre> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Next we can look at the docs for the addon:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| heroku addons:docs semaphore</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">We'll just go to our apps list in semaphore now and add a deployment. There's a nice wizard that walks us through everything. I'll cut out the bit where I plug in my API key, but you get this from heroku. Now we pick the branch to deploy and we're done. Now, every time we push to that branch it will be automatically deployed after the tests pass.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Let's test it out by modifying the posts index to show the images in the table for each post.</p> | |
| <div class="highlight highlight-html" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">h2</span>>Listing posts</<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">h2</span>> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">table</span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">class</span>=<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>table<span class="pl-pds" style="box-sizing: border-box;">"</span></span>> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">thead</span>> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">tr</span>> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">th</span>>Image</<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">th</span>> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">th</span>>ImageUrl</<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">th</span>> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">th</span>>Content</<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">th</span>> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">th</span>>SourceUrl</<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">th</span>> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">th</span>></<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">th</span>> | |
| </<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">tr</span>> | |
| </<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">thead</span>> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">tbody</span>> | |
| <%= for post <- @posts do %> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">tr</span>> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">td</span>><<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">img</span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">src</span>=<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">'</span><%= post.image_url %><span class="pl-pds" style="box-sizing: border-box;">'</span></span> /></<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">td</span>> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">td</span>><%= post.image_url %></<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">td</span>> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">td</span>><%= post.content %></<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">td</span>> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">td</span>><%= post.source_url %></<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">td</span>> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">td</span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">class</span>=<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>text-right<span class="pl-pds" style="box-sizing: border-box;">"</span></span>> | |
| <%= link "Show", to: post_path(@conn, :show, post), class: "btn btn-default btn-xs" %> | |
| <%= link "Edit", to: post_path(@conn, :edit, post), class: "btn btn-default btn-xs" %> | |
| <%= link "Delete", to: post_path(@conn, :delete, post), method: :delete, class: "btn btn-danger btn-xs" %> | |
| </<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">td</span>> | |
| </<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">tr</span>> | |
| <% end %> | |
| </<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">tbody</span>> | |
| </<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">table</span>> | |
| <%= link "New post", to: post_path(@conn, :new) %></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Now let's push this up to github and let semaphore deploy it for us.</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| git add <span class="pl-s3" style="box-sizing: border-box; color: rgb(0, 134, 179);">.</span> | |
| git commit -m<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>images on posts index<span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| git push origin master</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">We can click into semaphore and watch it kick off the build ((( do that and wait )))</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Now we'll load the index again and see an image in the table.</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Summary</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">So there we go. In today's episode we saw how easy it is to set up semaphore to handle Continuous Deployment for your projects. See you soon!</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Resources</h2> | |
| <ul class="task-list" style="box-sizing: border-box; padding-right: 0px; padding-left: 2em; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <li style="box-sizing: border-box;"><a href="https://github.com/HashNuke/heroku-buildpack-elixir" rel="noreferrer" style="box-sizing: border-box; color: rgb(65, 131, 196); text-decoration: none;">HashNuke/heroku-buildpack-elixir</a></li> | |
| <li style="box-sizing: border-box;"><a href="https://github.com/gjaldon/phoenix-static-buildpack" rel="noreferrer" style="box-sizing: border-box; color: rgb(65, 131, 196); text-decoration: none;">gjaldon/phoenix-static-buildpack</a></li> | |
| </ul> | |
| </div> | |
| <h3>Attached Files</h3> | |
| <ul> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=53340">173_Continuous_Deployment.mp4</a></li> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=53341">173_Continuous_Deployment.markdown</a></li> | |
| </ul></div>]]></description> | |
| <guid isPermaLink="false">dpd-b49e1e04b7a47bee866c63837bb98c824e47225d</guid> | |
| <pubDate>Wed, 01 Jul 2015 07:34:00 -0400</pubDate> | |
| <enclosure url="https://elixirsips.dpdcart.com/feed/download/53340/173_Continuous_Deployment.mp4" length="53635882" type="video/mp4"/> | |
| </item> | |
| <item> | |
| <title><![CDATA[172 - Arc File Uploads]]></title> | |
| <link>https://elixirsips.dpdcart.com/subscriber/post?id=819</link> | |
| <description><![CDATA[<div class="blog-entry"> | |
| <div class="blog-content"><h1 style="box-sizing: border-box; font-size: 2.25em; margin-right: 0px; margin-bottom: 16px; margin-left: 0px; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; margin-top: 0px !important;">Episode 172: Arc File Uploads</h1> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">In this episode we're going to look at arc, which is a tool for handling file uploads in Phoenix. Let's get started.</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Project</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">We'll start a new phoenix project:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| mix phoenix.new arc_playground | |
| <span class="pl-s3" style="box-sizing: border-box; color: rgb(0, 134, 179);">cd</span> arc_playground</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">and add the dependencies for <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">arc</code> and <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">arc_ecto</code>:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:arc</span>, <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>~> 0.1<span class="pl-pds" style="box-sizing: border-box;">"</span></span>}, | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:arc_ecto</span>, <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>~> 0.1<span class="pl-pds" style="box-sizing: border-box;">"</span></span>},</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Then we'll fetch the dependencies:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| mix deps.get</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">arc_ecto</code> is an addition to arc that allows it to integrate nicely with ecto models, by the way. It's not necessary if you just want to use arc to handle uploads more generally, but it makes storing uploads on a given ecto model a bit easier.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Now we'll generate an avatar uploader with arc's generator:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| mix arc.g avatar | |
| vim web/uploaders/avatar.ex</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Here's the default uploader with inlined documentation. We'll make a few changes.</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">ArcPlayground.Avatar</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # NOTE: This assumes you've already gotten an s3 bucket in place in the Standard</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Region. If you're using IAM, you'll also need to grant permissions to</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # authenticated users.</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">use</span> <span class="pl-vo" style="box-sizing: border-box;">Arc</span>.<span class="pl-vo" style="box-sizing: border-box;">Definition</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Include ecto support (requires package arc_ecto installed):</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">use</span> <span class="pl-vo" style="box-sizing: border-box;">Arc</span>.<span class="pl-vo" style="box-sizing: border-box;">Ecto</span>.<span class="pl-vo" style="box-sizing: border-box;">Definition</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # To add a thumbnail version:</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">@versions</span> [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:original</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:thumb</span>] | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Everyone can see uploaded files. If you want anything other than the</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # default, which is files being private to unauthenticated users, your IAM</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # user will need to have the ability to write ACL policies for files as well.</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">@acl</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:public_read</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Whitelist file extensions:</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> validate({file, _}) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">~w(</span>.jpg .jpeg .gif .png<span class="pl-pds" style="box-sizing: border-box;">)</span></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-vo" style="box-sizing: border-box;">Enum</span>.member?(<span class="pl-vo" style="box-sizing: border-box;">Path</span>.extname(file.file_name)) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Define a thumbnail transformation:</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # NOTE: If you specify the -format png as is described in the documentation, it</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # doesn't actually get converted into a png but writes .png as the extension,</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # which will certainly confuse your image viewer if it uses the extension to</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # determine the image type. I've removed that option here for what it's</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # worth.</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> transform(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:thumb</span>, _) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:convert</span>, <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>-strip -thumbnail 250x250^ -gravity center -extent 250x250<span class="pl-pds" style="box-sizing: border-box;">"</span></span>} | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Override the persisted filenames:</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # def filename(version, _) do</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # version</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # end</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Override the storage directory:</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # def storage_dir(version, {file, scope}) do</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # "uploads/user/avatars/#{scope.id}"</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # end</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Provide a default URL if there hasn't been a file uploaded</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # def default_url(version) do</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # "/images/avatars/default_#{version}.png"</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Next we need to configure ARC. I'm going to use environment variables here to avoid showing off my IAM user's credentials.</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| vim config/config.exs</pre> | |
| </div> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| config <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:arc</span>, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">access_key_id:</span> <span class="pl-vo" style="box-sizing: border-box;">System</span>.get_env(<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>AWS_ACCESS_KEY_ID<span class="pl-pds" style="box-sizing: border-box;">"</span></span>), | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">secret_access_key:</span> <span class="pl-vo" style="box-sizing: border-box;">System</span>.get_env(<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>AWS_SECRET_ACCESS_KEY<span class="pl-pds" style="box-sizing: border-box;">"</span></span>), | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">bucket:</span> <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>arc-playground-2<span class="pl-pds" style="box-sizing: border-box;">"</span></span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Now I'm going to copy an .envrc in which contains these variables.</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| cp xx_arc_playground/.envrc <span class="pl-s3" style="box-sizing: border-box; color: rgb(0, 134, 179);">.</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Now we can upload a file and fetch it again:</p> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 16px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; background-color: rgb(247, 247, 247);"> | |
| <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0px; margin: 0px; border-radius: 3px; word-break: normal; white-space: pre; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;">iex(2)> ArcPlayground.Avatar.store("/home/jadams/elixir/arc_playground/files/gracie2.jpg") | |
| #... | |
| iex(3)> ArcPlayground.Avatar.url("gracie2.jpg", :thumb) | |
| "https://s3.amazonaws.com/arc-playground-2/uploads/gracie2.jpg_thumb.jpg" | |
| </code></pre> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Summary</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">So this is pretty good, and shows off <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">arc</code>. What about <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">arc_ecto</code> though? In some of my testing, I had issues doing anything more than the exact example provided in the <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">arc_ecto</code> README, based around issues caused by the <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">cast_attachments</code> function when using non-attachment parameters. Given that, I didn't want to show this piece off yet as I expect a few changes to happen, I'll save that for a later episode. See you soon!</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Resources</h2> | |
| <ul class="task-list" style="box-sizing: border-box; padding-right: 0px; padding-left: 2em; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <li style="box-sizing: border-box;"><a href="https://github.com/stavro/arc" rel="noreferrer" style="box-sizing: border-box; color: rgb(65, 131, 196); text-decoration: none;">stavro/arc</a></li> | |
| </ul> | |
| </div> | |
| <h3>Attached Files</h3> | |
| <ul> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=52978">172_Arc_File_Uploads.mp4</a></li> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=52979">172_Arc_File_Uploads.markdown</a></li> | |
| </ul></div>]]></description> | |
| <guid isPermaLink="false">dpd-36d06370d0b0796c87c6a6b56de85a2d66d780af</guid> | |
| <pubDate>Sat, 27 Jun 2015 09:22:00 -0400</pubDate> | |
| <enclosure url="https://elixirsips.dpdcart.com/feed/download/52978/172_Arc_File_Uploads.mp4" length="50023297" type="video/mp4"/> | |
| </item> | |
| <item> | |
| <title><![CDATA[171 - Erlang 18 and Time]]></title> | |
| <link>https://elixirsips.dpdcart.com/subscriber/post?id=815</link> | |
| <description><![CDATA[<div class="blog-entry"> | |
| <div class="blog-content"><h1 style="box-sizing: border-box; font-size: 2.25em; margin-right: 0px; margin-bottom: 16px; margin-left: 0px; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; margin-top: 0px !important;">Episode 171: Erlang 18 and time</h1> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Erlang 18.0 was officially released today. There are a lot of interesting changes in this release. The most interesting three are:</p> | |
| <ul class="task-list" style="box-sizing: border-box; padding-right: 0px; padding-left: 2em; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <li style="box-sizing: border-box;">a change of license to the Apache Public License 2.0</li> | |
| <li style="box-sizing: border-box;">support for big maps</li> | |
| <li style="box-sizing: border-box;">a new API for time</li> | |
| </ul> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">In this episode I'm going to focus on looking at the differences in time, as these changes will help performance and scalability of our systems and because we have to learn the new API sometime, so why not now? Let's get started.</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Installing Erlang 18</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">I figured this might give me a good opportunity to show my strategy for handling multiple erlang releases in my system. I use kerl as my version manager for erlang.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">If you've got kerl installed, you can update the list of releases with:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| kerl update releases</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Then you can list the releases to see what you can install with it:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| kerl list releases</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">We want to install 18.0. Because you can build releases with different options for various purposes, kerl makes you name your releases. Let's build 18.0 with the default options:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| kerl build 18.0 18.0</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">This took way longer than the video makes it seem :)</p> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 16px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; background-color: rgb(247, 247, 247);"> | |
| <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0px; margin: 0px; border-radius: 3px; word-break: normal; white-space: pre; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;">... | |
| Building Erlang/OTP 18.0 (18.0), please wait... | |
| Erlang/OTP 18.0 (18.0) has been successfully built | |
| </code></pre> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Alright, now that the release is built we'll install it.</p> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 16px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; background-color: rgb(247, 247, 247);"> | |
| <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0px; margin: 0px; border-radius: 3px; word-break: normal; white-space: pre; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;">[jadams:~] $ kerl install 18.0 ~/erlang/erlangs/18.0 | |
| Installing Erlang/OTP 18.0 (18.0) in /home/jadams/erlang/erlangs/18.0... | |
| </code></pre> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Finally, we activate it, with:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-s3" style="box-sizing: border-box; color: rgb(0, 134, 179);">.</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">~</span>/erlang/erlangs/18.0/activate</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Now we can see that we're using the newer erlang:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| erl</pre> | |
| </div> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 16px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; background-color: rgb(247, 247, 247);"> | |
| <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0px; margin: 0px; border-radius: 3px; word-break: normal; white-space: pre; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;">[jadams:~] $ erl | |
| Erlang/OTP 18 [erts-7.0] [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false] | |
| Eshell V7.0 (abort with ^G) | |
| 1> | |
| </code></pre> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">OK, so now we're in erlang 18. Fantastic. We'll go ahead and run an iex shell to play with it from elixir:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| iex</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">So the old time api, which we're familiar with, centers around the call to <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">:erlang.now</code>:</p> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 16px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; background-color: rgb(247, 247, 247);"> | |
| <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0px; margin: 0px; border-radius: 3px; word-break: normal; white-space: pre; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;">iex(7)> :erlang.now | |
| {1435, 156474, 180776} | |
| </code></pre> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">The problem with this is that a lot of calls to it will give incorrect times. It also handles system time warps very poorly. These could be caused by POSIX time jumping, which happens during a leap second insertion, or by the underlying system time changing, which could be caused by anything from a manual time change to a clock that skews and is corrected by NTP.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">There is a lot of detail in the erlang manual page for time correction, which I encourage you to read. It would be very boring to hear me rattle it off in my own words, and I'd be likely to explain some things worse than the fine folks at ericsson, so I won't even try. What we will do, though, is look at some of the Do's and Don'ts of the new api.</p> | |
| <h3 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.43; font-size: 1.5em; position: relative; font-weight: bold; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">System time</h3> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">If you want to retrieve the system time, you used to use <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">:erlang.now</code>. Now you should use<code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">:erlang.system_time</code> instead:</p> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 16px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; background-color: rgb(247, 247, 247);"> | |
| <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0px; margin: 0px; border-radius: 3px; word-break: normal; white-space: pre; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;">iex(8)> :erlang.system_time | |
| 1435157397480748777 | |
| </code></pre> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Of course this isn't the format you're used to. If you want the same format that <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">now</code> returned, use<code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">:erlang.timestamp</code>:</p> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 16px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; background-color: rgb(247, 247, 247);"> | |
| <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0px; margin: 0px; border-radius: 3px; word-break: normal; white-space: pre; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;">iex(11)> :erlang.timestamp | |
| {1435, 157439, 504701} | |
| </code></pre> | |
| <h3 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.43; font-size: 1.5em; position: relative; font-weight: bold; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Measuring Elapsed Time</h3> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Previously, to measure elapsed time (for benchmarks, for instance), you would use <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">now</code>. For this use case, it's better to take timestamps with <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">:erlang.monotonic_time</code> and use subtraction to calculate the difference.</p> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 16px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; background-color: rgb(247, 247, 247);"> | |
| <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0px; margin: 0px; border-radius: 3px; word-break: normal; white-space: pre; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;">timing = fn() -> | |
| time1 = :erlang.monotonic_time | |
| :timer.sleep(5000) | |
| time2 = :erlang.monotonic_time | |
| time2 - time1 | |
| end | |
| time = timing.() | |
| </code></pre> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">This reports the time in the native runtime time units. If you want to see how many native time units there are in a given named time unit, you can use <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">:erlang.convert_time_unit</code>. Let's see how many there are in a second on this system:</p> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 16px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; background-color: rgb(247, 247, 247);"> | |
| <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0px; margin: 0px; border-radius: 3px; word-break: normal; white-space: pre; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;">iex(22)> :erlang.convert_time_unit(1, :seconds, :native) | |
| 1000000000 | |
| </code></pre> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">So for now, this means the native time units are nanoseconds. We should not make assumptions about this, because it's not guaranteed. To convert your time to nanoseconds, you can use<code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">convert_time_unit</code> with our time as the input. That's not that exciting because it will return the same value presently, so we'll just use this value to convert it to a floating point representation in seconds for now:</p> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 16px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; background-color: rgb(247, 247, 247);"> | |
| <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0px; margin: 0px; border-radius: 3px; word-break: normal; white-space: pre; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;">iex(26)> time / :erlang.convert_time_unit(1, :seconds, :native) | |
| 5.004091314 | |
| </code></pre> | |
| <h3 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.43; font-size: 1.5em; position: relative; font-weight: bold; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Determine Order of Events</h3> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">It's also common presently to use <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">:erlang.now</code> to determine which order various events happened in. Instead, there's a new api called <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">erlang:unique_integer\1</code> that we can use for this purpose:</p> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 16px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; background-color: rgb(247, 247, 247);"> | |
| <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0px; margin: 0px; border-radius: 3px; word-break: normal; white-space: pre; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;">iex(29)> :erlang.unique_integer([:monotonic]) | |
| -576460752303423488 | |
| </code></pre> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">This will help with ordering of events, but only on the same runtime system instance. This doesn't magically solve ordering events in a distributed system (but how neat would that be? Sadly, science...)</p> | |
| <h3 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.43; font-size: 1.5em; position: relative; font-weight: bold; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Determine Order of Events with Time of Event</h3> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">If you want to record both the order of events and the time of the event, you should record a 2-tuple that has the monotonic time first and a unique monotonic integer second:</p> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 16px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; background-color: rgb(247, 247, 247);"> | |
| <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0px; margin: 0px; border-radius: 3px; word-break: normal; white-space: pre; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;">iex(30)> {:erlang.monotonic_time, :erlang.unique_integer([:monotonic])} | |
| {-576458615893212445, -576460752303423487} | |
| </code></pre> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">If you also want to record the system time, it should come third in a 3-tuple:</p> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 16px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; background-color: rgb(247, 247, 247);"> | |
| <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0px; margin: 0px; border-radius: 3px; word-break: normal; white-space: pre; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;">iex(31)> {:erlang.monotonic_time, :erlang.unique_integer([:monotonic]), :erlang.system_time} | |
| {-576457905581180237, -576460752303423486, 1435159292497133219} | |
| </code></pre> | |
| <h3 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.43; font-size: 1.5em; position: relative; font-weight: bold; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Create a Unique Name</h3> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">If you just want a unique name, use <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">unique_integer</code>:</p> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 16px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; background-color: rgb(247, 247, 247);"> | |
| <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0px; margin: 0px; border-radius: 3px; word-break: normal; white-space: pre; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;">iex(32)> :erlang.unique_integer | |
| -576460752303423451 | |
| </code></pre> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">If negative numbers wig you out for some reason, you can force positive unique integers:</p> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 16px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; background-color: rgb(247, 247, 247);"> | |
| <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0px; margin: 0px; border-radius: 3px; word-break: normal; white-space: pre; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;">iex(33)> :erlang.unique_integer([:positive]) | |
| 54 | |
| </code></pre> | |
| <h3 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.43; font-size: 1.5em; position: relative; font-weight: bold; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Seed Random Number Generator</h3> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Historically I've used <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">now</code> to seed the random number generator. You can use various other tools for this. Here I'm using a unique integer and monotonic time:</p> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 16px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; background-color: rgb(247, 247, 247);"> | |
| <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0px; margin: 0px; border-radius: 3px; word-break: normal; white-space: pre; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;">iex(36)> :random.seed(:erlang.monotonic_time, :erlang.unique_integer, :erlang.monotonic_time) | |
| {20852, 13432, 19482} | |
| iex(37)> :random.uniform | |
| 0.6874430130169173 | |
| iex(38)> :random.seed(:erlang.monotonic_time, :erlang.unique_integer, :erlang.monotonic_time) | |
| {27720, 16824, 6566} | |
| iex(39)> :random.uniform | |
| 0.042746502986585444 | |
| </code></pre> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Summary</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">In summary, stop using <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">:erlang.now</code> and start porting older code to no longer use it. You can't do this without fallbacks if you have to run on systems pre-18.0, but there are examples in the erlang source in<code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">./erts/example/time_compat.erl</code>:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| vim <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">~</span>/.kerl/builds/18.0/otp_src_18.0/erts/example/time_compat.erl</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Enjoy your newer, better-performing clocks! See you soon!</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Resources</h2> | |
| <ul class="task-list" style="box-sizing: border-box; padding-right: 0px; padding-left: 2em; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <li style="box-sizing: border-box;"><a href="http://www.erlang.org/doc/apps/erts/time_correction.html" rel="noreferrer" style="box-sizing: border-box; color: rgb(65, 131, 196); text-decoration: none;">Time Correction Erlang docs</a></li> | |
| <li style="box-sizing: border-box;"><a href="https://github.com/yrashk/kerl" rel="noreferrer" style="box-sizing: border-box; color: rgb(65, 131, 196); text-decoration: none;">yrashk/kerl</a></li> | |
| </ul> | |
| </div> | |
| <h3>Attached Files</h3> | |
| <ul> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=52879">171_Erlang_18_and_time.mp4</a></li> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=52880">171_Erlang_18_and_time.markdown</a></li> | |
| </ul></div>]]></description> | |
| <guid isPermaLink="false">dpd-9a2fa70dd941592721d62c52865406f54fb3af01</guid> | |
| <pubDate>Wed, 24 Jun 2015 12:42:00 -0400</pubDate> | |
| <enclosure url="https://elixirsips.dpdcart.com/feed/download/52879/171_Erlang_18_and_time.mp4" length="44483067" type="video/mp4"/> | |
| </item> | |
| <item> | |
| <title><![CDATA[170 - Building a Slack Bot]]></title> | |
| <link>https://elixirsips.dpdcart.com/subscriber/post?id=810</link> | |
| <description><![CDATA[<div class="blog-entry"> | |
| <div class="blog-content"><h1 style="box-sizing: border-box; font-size: 2.25em; margin: 1em 0px 16px; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Episode 170: Building a Slack Bot</h1> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">I'm in quite a few slack groups, and in some of them there's a pretty compelling need for a bot for various tasks. Blake Williams has written an API client for Slack's Real Time Messaging API. We're going to build a bot with it. Let's get started.</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Project</h2> | |
| <h3 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.43; font-size: 1.5em; position: relative; font-weight: bold; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Setup</h3> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| mix new magiccitytech_slack --sup | |
| <span class="pl-s3" style="box-sizing: border-box; color: rgb(0, 134, 179);">cd</span> magiccitytech_slack | |
| vim mix.exs</pre> | |
| </div> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> application <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">applications:</span> [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:logger</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:slack</span>], | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">mod:</span> {<span class="pl-vo" style="box-sizing: border-box;">MagiccitytechSlack</span>, []}] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defp</span> deps <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| [ | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:slack</span>, <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>~> 0.0.5<span class="pl-pds" style="box-sizing: border-box;">"</span></span>}, | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:websocket_client</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">git:</span> <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>https://github.com/jeremyong/websocket_client<span class="pl-pds" style="box-sizing: border-box;">"</span></span>} | |
| ] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| mix deps.get | |
| mkdir lib/magiccitytech_slack</pre> | |
| </div> | |
| <h3 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.43; font-size: 1.5em; position: relative; font-weight: bold; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">The Meat</h3> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">We'll basically use the example bot as a starting point, but we'll move the token into an environment variable. Open up <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">lib/magiccitytech_slack/bot.ex</code></p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">MagiccitytechSlack.Bot</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">use</span> <span class="pl-vo" style="box-sizing: border-box;">Slack</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # So we'll define a start_link function, and we'll defer to the</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Slack.start_link function, passing it our API Token</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> start_link(initial_state) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">Slack</span>.start_link(<span class="pl-v" style="box-sizing: border-box; color: rgb(29, 62, 129);">__MODULE__</span>, <span class="pl-vo" style="box-sizing: border-box;">System</span>.get_env(<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>SLACK_BOT_API_TOKEN<span class="pl-pds" style="box-sizing: border-box;">"</span></span>), initial_state) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> init(initial_state, slack) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # We'll output when we're connected</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">IO</span>.puts <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>Connected as <span class="pl-s2" style="box-sizing: border-box; color: rgb(51, 51, 51);"><span class="pl-pse" style="box-sizing: border-box;">#{</span>slack.me.name<span class="pl-pse" style="box-sizing: border-box;">}</span></span><span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:ok</span>, initial_state} | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> handle_message({<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:type</span>, <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>hello<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, response}, slack, state) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # The first message we receive from the slack socket will be the hello</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # message. We'll use this to output the available channels.</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">IO</span>.puts <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>Available channels: <span class="pl-s2" style="box-sizing: border-box; color: rgb(51, 51, 51);"><span class="pl-pse" style="box-sizing: border-box;">#{</span>inspect <span class="pl-vo" style="box-sizing: border-box;">Slack</span>.<span class="pl-vo" style="box-sizing: border-box;">State</span>.channels(slack)<span class="pl-pse" style="box-sizing: border-box;">}</span></span><span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:ok</span>, state} | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> handle_message({<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:type</span>, <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>message<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, response}, slack, state) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">IO</span>.puts <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>message<span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| <span class="pl-vo" style="box-sizing: border-box;">IO</span>.inspect response | |
| <span class="pl-vo" style="box-sizing: border-box;">IO</span>.puts <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>slack<span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| <span class="pl-vo" style="box-sizing: border-box;">IO</span>.inspect slack | |
| <span class="pl-vo" style="box-sizing: border-box;">IO</span>.puts <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>state<span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| <span class="pl-vo" style="box-sizing: border-box;">IO</span>.inspect state | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # While our bot is connected, we'll send an upcased reply to all messages</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">Slack</span>.send_message(<span class="pl-vo" style="box-sizing: border-box;">String</span>.upcase(response.text), response.channel, slack) | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:ok</span>, state} | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> handle_message({<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:type</span>, type, _response}, _slack, state) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">IO</span>.puts <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>some other type<span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:ok</span>, state} | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">And that's basically it. I'm using this as a framework to start our slack bot, and I'll just run it forever and keep adding features to it. It's so freaking easy! See you soon!</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Resources</h2> | |
| <ul class="task-list" style="box-sizing: border-box; padding-right: 0px; padding-left: 2em; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <li style="box-sizing: border-box;"><a href="https://github.com/BlakeWilliams/Elixir-Slack" rel="noreferrer" style="box-sizing: border-box; color: rgb(65, 131, 196); text-decoration: none;">BlakeWilliams/Elixir-Slack</a></li> | |
| <li style="box-sizing: border-box;"><a href="http://hexdocs.pm/slack/" rel="noreferrer" style="box-sizing: border-box; color: rgb(65, 131, 196); text-decoration: none;">Slack on hexdocs.pm</a></li> | |
| <li style="box-sizing: border-box;"><a href="https://api.slack.com/rtm" rel="noreferrer" style="box-sizing: border-box; color: rgb(65, 131, 196); text-decoration: none;">Slack Real Time Messaging API</a></li> | |
| </ul> | |
| </div> | |
| <h3>Attached Files</h3> | |
| <ul> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=52658">170_Building_a_Slack_Bot.mp4</a></li> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=52659">170_Building_a_Slack_Bot.markdown</a></li> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=52660">170_magiccitytech_slack.tar.gz</a></li> | |
| </ul></div>]]></description> | |
| <guid isPermaLink="false">dpd-2981c3e60955bf57de1ee08d61839371e44fff58</guid> | |
| <pubDate>Fri, 19 Jun 2015 08:16:00 -0400</pubDate> | |
| <enclosure url="https://elixirsips.dpdcart.com/feed/download/52658/170_Building_a_Slack_Bot.mp4" length="52942633" type="video/mp4"/> | |
| </item> | |
| <item> | |
| <title><![CDATA[169 - Fractals, Part 2]]></title> | |
| <link>https://elixirsips.dpdcart.com/subscriber/post?id=808</link> | |
| <description><![CDATA[<div class="blog-entry"> | |
| <div class="blog-content"><h1 style="box-sizing: border-box; font-size: 2.25em; margin-right: 0px; margin-bottom: 16px; margin-left: 0px; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; margin-top: 0px !important;">Episode 169: Fractals, Part 2</h1> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">In 3 previous episodes we built a Logo interpreter and a module for evolving L Systems. Today we'll combine them to show how you can generate interesting graphics. Let's get started.</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Project</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">I've tagged the fractal_playground with <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">before_episode_169</code></p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">We'll add the logo project to our dependencies:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:logo</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">github:</span> <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>knewter/logo<span class="pl-pds" style="box-sizing: border-box;">"</span></span>}</pre> | |
| </div> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| mix deps.get</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">OK, now we're going to just build a quick test for a module that reduces a string into a list of functions and arguments to apply against our turtle:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">LogoMappingTest</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">use</span> <span class="pl-vo" style="box-sizing: border-box;">ExUnit</span>.<span class="pl-vo" style="box-sizing: border-box;">Case</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # We expect to have a list of mappings from a character to a function and</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # arguments. Here I'll define some we'll use later.</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">@mappings</span> %{ | |
| <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>A<span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=></span> {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:forward</span>, [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">10</span>]}, | |
| <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>-<span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=></span> {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:right</span>, [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">30</span>]}, | |
| <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>B<span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=></span> {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:forward</span>, [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">10</span>]}, | |
| <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>+<span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=></span> {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:left</span>, [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">30</span>]}, | |
| } | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Now we want to make sure that our mapping works.</span> | |
| test <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>maps an alphabet to logo function calls<span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| assert [ | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:forward</span>, [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">10</span>]}, | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:right</span>, [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">30</span>]}, | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:forward</span>, [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">10</span>]}, | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:left</span>, [<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">30</span>]} | |
| ] <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-vo" style="box-sizing: border-box;">LogoMapping</span>.map(<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>A-B+<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, <span class="pl-vo" style="box-sizing: border-box;">@mappings</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Honestly, this is easily the smallest thing that could justify being a function; we're basically putting some <em style="box-sizing: border-box;">tiny</em> sugar on top of Enum.map. Here's the implementation anyway:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">LogoMapping</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> map(string, mappings) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| string | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-vo" style="box-sizing: border-box;">String</span>.graphemes | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-vo" style="box-sizing: border-box;">Enum</span>.map(<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">fn</span>(char) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| mappings[char] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">So this is comically tiny. When I first did this I had a mental block and this was a larger function, in which I'd implemented map in terms of reduce manually. Once I realized what I'd done I just mocked myself for a while. Still, I like having this chunk of code wrapped up. Run the tests, and they'll pass.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Next, we're just going to implement this thing. We'll make an example script:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| mkdir examples | |
| vim examples/sierpinski.exs</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">And on to the show. We'll set up an L system I grabbed off of wikipedia:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">Sierpinski</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">import</span> <span class="pl-vo" style="box-sizing: border-box;">Logo</span>.<span class="pl-vo" style="box-sizing: border-box;">Instance</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">@rules</span> %{ | |
| <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>A<span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=></span> <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>B-A-B<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, | |
| <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>B<span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=></span> <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>A+B+A<span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| } | |
| <span class="pl-vo" style="box-sizing: border-box;">@axiom</span> <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>A<span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">We'll build a quick function to iterate through our L System a set number of times - we're wrapping this up in a run function:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">Sierpinski</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # ...</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> run(iterations) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| runs <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-vo" style="box-sizing: border-box;">LSystem</span>.run(<span class="pl-vo" style="box-sizing: border-box;">@axiom</span>, <span class="pl-vo" style="box-sizing: border-box;">@rules</span>, steps) | |
| [output<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span>_] <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-vo" style="box-sizing: border-box;">Enum</span>.reverse(runs) | |
| <span class="pl-vo" style="box-sizing: border-box;">IO</span>.inspect output | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">Sierpinski</span>.run(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">5</span>)</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">We'll map comma-big-t to run our example:</p> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 16px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; background-color: rgb(247, 247, 247);"> | |
| <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0px; margin: 0px; border-radius: 3px; word-break: normal; white-space: pre; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;">:map ,T mix run examples/sierpinski.exs<cr> | |
| </code></pre> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Go ahead and run it and we should get the text output of 5 runs through this L system ((( do it )))</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Alright, now we want to map that string to functions that get passed to our turtle. Let's do that:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-vo" style="box-sizing: border-box;">@angle</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">60</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">@distance</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">10</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">@mappings</span> %{ | |
| <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>A<span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=></span> {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:forward</span>, [<span class="pl-vo" style="box-sizing: border-box;">@distance</span>]}, | |
| <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>B<span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=></span> {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:forward</span>, [<span class="pl-vo" style="box-sizing: border-box;">@distance</span>]}, | |
| <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>-<span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=></span> {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:right</span>, [<span class="pl-vo" style="box-sizing: border-box;">@angle</span>]}, | |
| <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>+<span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=></span> {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:left</span>, [<span class="pl-vo" style="box-sizing: border-box;">@angle</span>]} | |
| } | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> run(steps) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| runs <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-vo" style="box-sizing: border-box;">LSystem</span>.run(<span class="pl-vo" style="box-sizing: border-box;">@axiom</span>, <span class="pl-vo" style="box-sizing: border-box;">@rules</span>, steps) | |
| [output<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span>_] <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-vo" style="box-sizing: border-box;">Enum</span>.reverse(runs) | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # We'll map our output to the logo functions</span> | |
| moves <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-vo" style="box-sizing: border-box;">LogoMapping</span>.map(output, <span class="pl-vo" style="box-sizing: border-box;">@mappings</span>) | |
| <span class="pl-vo" style="box-sizing: border-box;">IO</span>.puts inspect moves | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">We can run it now, and we see some weird looking maps - that's because our arguments are all 1 character lists that can be represented as ASCII, so don't be alarmed. Now all that's left is to set the stage for our turtle, then pass these functions into it using apply:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> run(steps) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| runs <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-vo" style="box-sizing: border-box;">LSystem</span>.run(<span class="pl-vo" style="box-sizing: border-box;">@axiom</span>, <span class="pl-vo" style="box-sizing: border-box;">@rules</span>, steps) | |
| [output<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span>_] <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-vo" style="box-sizing: border-box;">Enum</span>.reverse(runs) | |
| moves <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-vo" style="box-sizing: border-box;">LogoMapping</span>.map(output, <span class="pl-vo" style="box-sizing: border-box;">@mappings</span>) | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # We'll start a new turtle and set him up near the center of the canvas with</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # a red pen down.</span> | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:ok</span>, turtle} <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-vo" style="box-sizing: border-box;">Logo</span>.<span class="pl-vo" style="box-sizing: border-box;">Instance</span>.start | |
| turtle | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> move_to({<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">300</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">300</span>}) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> color({<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">255</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span>}) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> pen_down | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # We'll apply each move to our turtle</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">for</span> {fun, args} <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"><</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span> moves <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| apply(<span class="pl-vo" style="box-sizing: border-box;">Logo</span>.<span class="pl-vo" style="box-sizing: border-box;">Instance</span>, fun, [turtle] <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">++</span> args) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # And then all that's left is to draw him</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">Logo</span>.<span class="pl-vo" style="box-sizing: border-box;">Window</span>.start(turtle) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Alright, run it now, and we get something really fun ((( do it )))</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Let's run a few more iterations</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">((( increase to 6, run it, reduce distance per iteration so it fits on the canvas )))</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Alright, what does 7 look like?</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">((( do it )))</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">That's obviously a sierpinski triangle, so that's fantastic.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">It's also a little fun to skew it by changing the angle slightly ((( change it to 58 and run it )))</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Summary</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">In today's episode, we combined our L Systems and our Logo interpreter to generate a sierpinski triangle. There are a lot of really fun examples you can run through on wikipedia, but some of the extra intriguing ones require the ability to push and pop the turtle's position and angle onto a stack. In an upcoming episode we'll introduce that and draw some more intricate graphics. See you soon!</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Resources</h2> | |
| <ul class="task-list" style="box-sizing: border-box; padding-right: 0px; padding-left: 2em; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <li style="box-sizing: border-box;"><a href="https://github.com/knewter/logo" rel="noreferrer" style="box-sizing: border-box; color: rgb(65, 131, 196); text-decoration: none;">knewter/logo</a></li> | |
| <li style="box-sizing: border-box;"><a href="https://github.com/knewter/fractal_playground" rel="noreferrer" style="box-sizing: border-box; color: rgb(65, 131, 196); text-decoration: none;">knewter/fractal_playground</a></li> | |
| </ul> | |
| </div> | |
| <h3>Attached Files</h3> | |
| <ul> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=52580">169_Fractals_Part_2.mp4</a></li> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=52581">169_Fractals_Part_2.markdown</a></li> | |
| </ul></div>]]></description> | |
| <guid isPermaLink="false">dpd-a6df8eb71e88c7098b7cd81e4c41a950cc402917</guid> | |
| <pubDate>Wed, 17 Jun 2015 09:19:00 -0400</pubDate> | |
| <enclosure url="https://elixirsips.dpdcart.com/feed/download/52580/169_Fractals_Part_2.mp4" length="41288894" type="video/mp4"/> | |
| </item> | |
| <item> | |
| <title><![CDATA[168 - Continuous Integration]]></title> | |
| <link>https://elixirsips.dpdcart.com/subscriber/post?id=784</link> | |
| <description><![CDATA[<div class="blog-entry"> | |
| <div class="blog-content"><h1 style="box-sizing: border-box; font-size: 2.25em; margin-right: 0px; margin-bottom: 16px; margin-left: 0px; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; margin-top: 0px !important;">Episode 168: Continuous Integration</h1> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Continuous Integration is the process of merging code branches regularly. When people talk about Continuous Integration these days, they almost always are referring to it in conjunction with tests, of course. It does no good to be sure that your code merges cleanly if it no longer performs the desired task!</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Today's episode is going to cover performing Continuous Integration in Elixir by way of the Semaphore hosted Continuous Integration service, running the tests for a Phoenix application. Let's get started.</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Project</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">We're going to start a new Phoenix project whose purpose is to collect images from twitter that are tagged with #elixirfriends and collect them. We'll not build the Twitter integration yet, but we'll build the Phoenix application that can display the data.</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| mix phoenix.new elixir_friends | |
| <span class="pl-s3" style="box-sizing: border-box; color: rgb(0, 134, 179);">cd</span> elixir_friends | |
| mix phoenix.server</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">((( visit http://localhost:4000 )))</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Alright, so here's a new phoenix app using the latest version of the framework. Now let's use its generators to build a quickie data model for the images:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| mix phoenix.gen.html <span class="pl-vo" style="box-sizing: border-box;">Post</span> posts <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">image_url:</span>string <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">content:</span>string <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">source_url:</span>string</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">So we'll just call these Posts, that have an <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">image_url</code>, some <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">content</code>, and a <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">source_url</code>. It's not a crazy complicated data model but this is a quick thing we want to deploy so no big deal.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Let's add the resource to the router:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| scope <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>/<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, <span class="pl-vo" style="box-sizing: border-box;">ElixirFriends</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| pipe_through <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:browser</span> <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"># Use the default browser stack</span> | |
| get <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>/<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, <span class="pl-vo" style="box-sizing: border-box;">PageController</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:index</span> | |
| resources <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>/posts<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, <span class="pl-vo" style="box-sizing: border-box;">PostController</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Then we'll create the database and migrate it up:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| mix ecto.create | |
| mix ecto.migrate</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">OK, so now there are some posts that can be created. Let's look at that:</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">((( http://localhost:4000/posts )))</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">We'll make a post:</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">((( do it, using: image_url:<a href="http://fc00.deviantart.net/fs71/i/2012/176/8/f/marvin_the_paranoid_android_by_wouthezx-d54uny0.jpg" rel="noreferrer" style="box-sizing: border-box; color: rgb(65, 131, 196); text-decoration: none;">http://fc00.deviantart.net/fs71/i/2012/176/8/f/marvin_the_paranoid_android_by_wouthezx-d54uny0.jpg</a>content: Marvin the Martian source_url: <a href="http://elixirsips.com/" rel="noreferrer" style="box-sizing: border-box; color: rgb(65, 131, 196); text-decoration: none;">http://elixirsips.com</a> )))</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">OK, so this works and we'll visit it at the show url:</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">((( do it )))</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Right, so we want this to show the image in an image tag, and link to the source. We'll define this desire in the controller test for now. Let's say that the show page ought to have an image tag with our image's source. Open up <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">test/controllers/post_controller_test.exs</code>:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| test <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>shows an image for the post<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, %{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">conn:</span> conn} <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| post <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-vo" style="box-sizing: border-box;">Repo</span>.insert %<span class="pl-vo" style="box-sizing: border-box;">Post</span>{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">image_url:</span> <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>http://fc00.deviantart.net/fs71/i/2012/176/8/f/marvin_the_paranoid_android_by_wouthezx-d54uny0.jpg<span class="pl-pds" style="box-sizing: border-box;">"</span></span>} | |
| conn <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> get conn, post_path(conn, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:show</span>, post) | |
| assert html_response(conn, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">200</span>) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">~</span> <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>Show post<span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| assert html_response(conn, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">200</span>) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">~</span> <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span><img src='http://fc00.deviantart.net/fs71/i/2012/176/8/f/marvin_the_paranoid_android_by_wouthezx-d54uny0.jpg' /><span class="pl-pds" style="box-sizing: border-box;">"</span></span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Run the tests, and they'll fail. Let's fix the template.</p> | |
| <div class="highlight highlight-html" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">h2</span>>Show post</<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">h2</span>> | |
| <<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">img</span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">src</span>=<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">'</span><%= @post.image_url %><span class="pl-pds" style="box-sizing: border-box;">'</span></span> /></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Run the test again, and it passes. Now this isn't anything fancy, but it's a start. Now let's see about using Semaphore to run the tests everytime we commit changes to this project. First I'll create it on github:</p> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 16px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; background-color: rgb(247, 247, 247);"> | |
| <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0px; margin: 0px; border-radius: 3px; word-break: normal; white-space: pre; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;">git init . | |
| git add . | |
| git commit -m"Initial checkin" | |
| hub create | |
| git push origin master | |
| </code></pre> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">OK, so now it's up on GitHub. Next we'll pull up <a href="https://semaphoreci.com/" rel="noreferrer" style="box-sizing: border-box; color: rgb(65, 131, 196); text-decoration: none;">Semaphore CI</a> where I'm logged in already. Let's add a new project.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">((( do it )))</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">It takes quite a while to list my projects because I have like 400 of them. We'll find <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">elixir_friends</code> in the list ((( use ctrl+f to find it )))</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">OK, so we'll just click through and it will see it's an elixir project. We can continue, and the predefined settings would work for a basic elixir library or something like that. Since we have a Phoenix application though, we need a postgres database. Semaphore provides the database username and password as environment variables, so we'll provide for that in our test configuration:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">username:</span> <span class="pl-vo" style="box-sizing: border-box;">System</span>.get_env(<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>DATABASE_POSTGRESQL_USERNAME<span class="pl-pds" style="box-sizing: border-box;">"</span></span>) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">||</span> <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>postgres<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">password:</span> <span class="pl-vo" style="box-sizing: border-box;">System</span>.get_env(<span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>DATABASE_POSTGRESQL_PASSWORD<span class="pl-pds" style="box-sizing: border-box;">"</span></span>) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">||</span> <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>postgres<span class="pl-pds" style="box-sizing: border-box;">"</span></span>,</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">We'll push up again, and now our tests are passing. Now every time we push to our GitHub repo, Semaphore's running our tests. Fantastic.</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Summary</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">In today's episode we saw how to use Semaphore CI to run our Phoenix application's integration tests every time we push new commits. We'll look at following the build up with a Heroku deploy for Continuous Deployment in a later episode. See you soon!</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Resources</h2> | |
| <ul class="task-list" style="box-sizing: border-box; padding-right: 0px; padding-left: 2em; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <li style="box-sizing: border-box;"><a href="http://en.wikipedia.org/wiki/Continuous_integration" rel="noreferrer" style="box-sizing: border-box; color: rgb(65, 131, 196); text-decoration: none;">Continuous Integration on Wikipedia</a></li> | |
| <li style="box-sizing: border-box;"><a href="https://semaphoreci.com/" rel="noreferrer" style="box-sizing: border-box; color: rgb(65, 131, 196); text-decoration: none;">Semaphore CI</a></li> | |
| </ul> | |
| </div> | |
| <h3>Attached Files</h3> | |
| <ul> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=51837">168_Continuous_Integration.mp4</a></li> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=51838">168_Continuous_Integration.markdown</a></li> | |
| </ul></div>]]></description> | |
| <guid isPermaLink="false">dpd-e0e5332038b108ca27551d1198cd16e3e957b0b7</guid> | |
| <pubDate>Thu, 04 Jun 2015 22:49:00 -0400</pubDate> | |
| <enclosure url="https://elixirsips.dpdcart.com/feed/download/51837/168_Continuous_Integration.mp4" length="55146239" type="video/mp4"/> | |
| </item> | |
| <item> | |
| <title><![CDATA[167 - Implementing Logo, Part 2]]></title> | |
| <link>https://elixirsips.dpdcart.com/subscriber/post?id=777</link> | |
| <description><![CDATA[<div class="blog-entry"> | |
| <div class="blog-content"><h1 style="box-sizing: border-box; font-size: 2.25em; margin-right: 0px; margin-bottom: 16px; margin-left: 0px; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; margin-top: 0px !important;">Episode 167: Implementing Logo, Part 2</h1> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">In the last episode, we implemented the core of a Logo interpreter. Today we'll add on a renderer, because without a renderer it's basically a few unit tests that pass which isn't that impressive to show off. Let's get started.</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Project</h2> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">I've tagged the code before this episode as <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">before_episode_167</code> if you want to follow along.</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| git checkout before_episode_167</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">So before we started the last episode I added a Logo.Renderer that just drew a box, to make sure we'd have an easy way to start drawing when the time came. We can see it in iex:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| iex -S mix</pre> | |
| </div> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 16px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; background-color: rgb(247, 247, 247);"> | |
| <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0px; margin: 0px; border-radius: 3px; word-break: normal; white-space: pre; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;">Logo.Window.start([]) | |
| </code></pre> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">I also wrote up an example script that we haven't explored yet. Let's look at it and tweak it a bit to pass our turtle instance into the window we render:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"># We'll import Logo.Instance so we don't have to write that bit all the time</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">import</span> <span class="pl-vo" style="box-sizing: border-box;">Logo</span>.<span class="pl-vo" style="box-sizing: border-box;">Instance</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"># We're starting an instance here</span> | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:ok</span>, logo} <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-vo" style="box-sizing: border-box;">Logo</span>.<span class="pl-vo" style="box-sizing: border-box;">Instance</span>.start | |
| logo | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> color({<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">255</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span>}) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> pen_down | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> forward(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">400</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> right(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">90</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> forward(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">200</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> right(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">180</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> forward(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">400</span>) | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"># Finally, we'll pass our instance into the Logo.Window to be drawn</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">Logo</span>.<span class="pl-vo" style="box-sizing: border-box;">Window</span>.start(logo)</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">OK, so next we need to open up the window and just fix a few references to make it clear what we're passing through all these functions:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"># Just :%s/config/instance/g in lib/logo/window.ex</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Finally, we'll open up the renderer and fix this reference there as well:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"># same deal, :%s/config/instance/g</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">OK, so that's got us ready to actually implement the rendering. Let's run the tests, which will at least confirm I didn't fat-finger any syntax changes.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">((( do it )))</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Back in the renderer we'll look at the render function. Before I change anything, I've got comma-big-t mapped to running the example, which at present should run the Turtle but then follow it up with running the renderer, which just draws a square somewhere on the canvas.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">((( do it )))</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Now in the renderer and write some hopeful code to help us think about what we want to do.</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> render(canvas, instance) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # So we've passed in the instance. Let's get the turtle out of this</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # instance</span> | |
| turtle <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-vo" style="box-sizing: border-box;">Instance</span>.get_turtle(instance) | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Now we have a turtle...but we really need to draw some shapes. The turtle</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # doesn't store any shapes though. It's just an actor that's doing its</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # work. We want to take the shapes off of the turtle, and then draw a list</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # of them. What we want to do is this:</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # draw_shapes(canvas, turtle.shapes)</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # But we can't grab those yet, so we'll leave that in but commented out.</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Let's think through what we want to be in that turtle.shapes key.</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Really we just need a list of shapes to draw, and a shape is named tuple.</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # We'll start out defining a line, because that's all we need for the</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # fractals. We'll leave a pattern for introducing new shapes later though.</span> | |
| draw_shapes(canvas, [{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:line</span>, {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span>}, {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">100</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">100</span>}}]) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Alright, so now we want a recursive function that goes through the shapes,</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # drawing until the list is empty.</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> draw_shapes(canvas, [head<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span>rest]) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| draw_shape(canvas, head) | |
| draw_shapes(canvas, rest) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> draw_shapes(_canvas, []), <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span>: <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:ok</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Now all we have to do is define how to draw a line. We'll just make a pen</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # for now - it's immediately obvious that we need to store the colors with the</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # shapes though.</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> draw_shape(canvas, {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:line</span>, {x1, y1}, {x2, y2}}) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # So here's a red pen for our line</span> | |
| pen <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:wxPen</span>.new({<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">255</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">255</span>}) | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # We'll set the pen in our graphics context</span> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:wxGraphicsContext</span>.setPen(canvas, pen) | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # And now we just use the drawLines function, which takes a list of points</span> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:wxGraphicsContext</span>.drawLines(canvas, [{x1, y1}, {x2, y2}]) | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:ok</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| </pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Let's run the example, and we should end up with a line from {0, 0} to {100, 100}.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">((( do it )))</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Now all we need to do is build up the list of shapes from the turtle as it walks around. Let's open up the Logo.Instance and add that property to it to store the shapes:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">Turtle</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defstruct</span> [ | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">color:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">nil</span>, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">pen_down:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">false</span>, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">x:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span>, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">y:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span>, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">angle:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span>, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">shapes:</span> [] | |
| ] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">The right way to move on from here would be to write a test, but I'm kind of eager to see the turtle drawing so let's skip it this once...may future-me forgive us. Go down to where we handle the cast for forward and we'll add a shape if the pen is down:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> handle_cast({<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:forward</span>, amount}, turtle) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| delta_x <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> amount <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">*</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:math</span>.cos(radians(turtle.angle)) | |
| delta_y <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> amount <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">*</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:math</span>.sin(radians(turtle.angle)) | |
| shapes <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> turtle.shapes | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">if</span>(turtle.pen_down) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| shapes <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> [{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:line</span>, {turtle.x, turtle.y}, {turtle.x <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">+</span> delta_x, turtle.y <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">+</span> delta_y}}<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span>shapes] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:noreply</span>, %<span class="pl-vo" style="box-sizing: border-box;">Turtle</span>{turtle<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">x:</span> turtle.x <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">+</span> delta_x, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">y:</span> turtle.y <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">+</span> delta_y, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">shapes:</span> shapes}} | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">There's almost certainly a nicer way to handle that, but this works and it's not the worst code I've ever written. This should be sufficient to make our renderer work, so let's go back to the renderer and fetch the shapes instead of passing in our hard coded shapes:</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">((( do it )))</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">With that in place all we really need to do is run the example and see what we end up with.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">((( do it, comma-big-t )))</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Here we can see that we don't quite have a T. That's because we started off in the top left, pointing right, rather than in the middle pointing up. Rather than solving this in a perfect manner, I think we'd just like to move our turtle to a specific location at the beginning of our example.</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| logo | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> move_to({<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">300</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">300</span>}) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> color({<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">255</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span>}) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> pen_down | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> forward(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">400</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> right(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">90</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> forward(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">200</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> right(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">180</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> forward(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">400</span>) | |
| <span class="pl-vo" style="box-sizing: border-box;">Logo</span>.<span class="pl-vo" style="box-sizing: border-box;">Window</span>.start(logo)</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">So of course this doesn't exist yet. We'll open up the tests and implement it quickly:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| test <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>can move to a particular position<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, meta <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| turtle <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> meta[<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:pid</span>] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-vo" style="box-sizing: border-box;">Instance</span>.move_to({<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">300</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">300</span>}) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> <span class="pl-vo" style="box-sizing: border-box;">Instance</span>.get_turtle | |
| assert <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">300</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> turtle.x | |
| assert <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">300</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> turtle.y | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">We can run the tests, and obviously this function doesn't exist. Open up Logo.Instance:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> move_to(pid, {x, y}) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:ok</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-vo" style="box-sizing: border-box;">GenServer</span>.cast(pid, {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:move_to</span>, {x, y}}) | |
| pid | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> #...</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> handle_cast({<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:move_to</span>, {x, y}}, turtle) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:noreply</span>, %<span class="pl-vo" style="box-sizing: border-box;">Turtle</span>{turtle<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">x:</span> x, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">y:</span> y}} | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Run the tests, and they'll pass. Now let's run the example again and our T should not be stuck in the top right any longer:</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">((( comma-big-T )))</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">OK, so our basic example works. Now I'm going to add a more interesting example that I got from an online logo gallery and ported.</p> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">((( open examples/interesting.exs )))</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"># Ported from https://turight(leacademy.com/view/programs/555aa690f45859910a3c986a/en</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">import</span> <span class="pl-vo" style="box-sizing: border-box;">Logo</span>.<span class="pl-vo" style="box-sizing: border-box;">Instance</span> | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:ok</span>, logo} <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-vo" style="box-sizing: border-box;">Logo</span>.<span class="pl-vo" style="box-sizing: border-box;">Instance</span>.start | |
| logo | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> move_to({<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">300</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">300</span>}) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> color({<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">255</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span>}) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> pen_down | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> right(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">45</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> forward(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">200</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> right(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">90</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> forward(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">200</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> right(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">90</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> forward(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">200</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> right(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">90</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> forward(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">200</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> right(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">90</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> forward(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">200</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> right(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">90</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> forward(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">50</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> right(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">90</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> forward(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">50</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> left(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">90</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> forward(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">50</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> right(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">90</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> forward(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">50</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> left(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">90</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> forward(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">50</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> right(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">90</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> forward(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">50</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> left(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">90</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> forward(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">50</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> right(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">90</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> forward(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">50</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> right(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">90</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> forward(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">200</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> right(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">90</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> forward(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">150</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> right(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">90</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> forward(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">50</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> right(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">90</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> forward(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">50</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> left(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">90</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> forward(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">50</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> right(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">90</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> forward(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">50</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> left(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">90</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> forward(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">50</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> right(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">90</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> forward(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">50</span>) | |
| <span class="pl-vo" style="box-sizing: border-box;">Logo</span>.<span class="pl-vo" style="box-sizing: border-box;">Window</span>.start(logo)</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Now let's run it:</p> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| mix run examples/interesting.exs</pre> | |
| </div> | |
| <h3 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.43; font-size: 1.5em; position: relative; font-weight: bold; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Summary</h3> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Sweet. Our logo interpreter works essentially out of the box (granted, we manually parsed it into function calls) with a logo program from elsewhere, and we get some interesting output. We'll use this later to explore L System fractals. See you soon!</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Resources</h2> | |
| <ul class="task-list" style="box-sizing: border-box; padding-right: 0px; padding-left: 2em; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <li style="box-sizing: border-box;"><a href="https://github.com/knewter/logo" rel="noreferrer" style="box-sizing: border-box; color: rgb(65, 131, 196); text-decoration: none;">knewter/logo</a></li> | |
| <li style="box-sizing: border-box;"><a href="http://www.erlang.org/doc/man/wx.html" rel="noreferrer" style="box-sizing: border-box; color: rgb(65, 131, 196); text-decoration: none;">wx Erlang docs</a></li> | |
| <li style="box-sizing: border-box;"><a href="https://turtleacademy.com/view/programs/555aa690f45859910a3c986a/en" rel="noreferrer" style="box-sizing: border-box; color: rgb(65, 131, 196); text-decoration: none;">The logo example I ported</a></li> | |
| </ul> | |
| </div> | |
| <h3>Attached Files</h3> | |
| <ul> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=51757">167_Implementing_Logo_Part_2.mp4</a></li> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=51758">167_Implementing_Logo_Part_2.markdown</a></li> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=51759">167_logo.tar.gz</a></li> | |
| </ul></div>]]></description> | |
| <guid isPermaLink="false">dpd-e11c101e940fdf135fbf4a0c74c9dae37d0df2cf</guid> | |
| <pubDate>Tue, 02 Jun 2015 22:16:00 -0400</pubDate> | |
| <enclosure url="https://elixirsips.dpdcart.com/feed/download/51757/167_Implementing_Logo_Part_2.mp4" length="62507095" type="video/mp4"/> | |
| <itunes:subtitle>Building a renderer for our Logo interpreter.</itunes:subtitle> | |
| </item> | |
| <item> | |
| <title><![CDATA[166 - Implementing Logo, Part 1]]></title> | |
| <link>https://elixirsips.dpdcart.com/subscriber/post?id=776</link> | |
| <description><![CDATA[<div class="blog-entry"> | |
| <div class="blog-content"><h1>Episode 166: Implementing Logo, Part 1</h1> | |
| <p>In Episode 164 we built a module to evaluate L systems. The episode was titled fractals, but until we take the next step it's not immediately clear why. The next step is to generate Logo programs from the resulting output. There are no Logo interpreters that I can find for Erlang or Elixir, so I suppose we'll just go ahead and build our own. Let's get started.</p> | |
| <h2>Project</h2> | |
| <p>So I've built a basic app that can render to a wx canvas, using Extris' window module as a foundation. You can find it tagged <code>before_episode_166</code> in the logo repo I've linked to in the resources section. Let's look at the README.</p> | |
| <p>((( do it )))</p> | |
| <p>So here you can see a couple of example bits of code. We're going to implement the second bit. We don't need a parser yet to show our fractals, but we'll probably build a parser for the logo language later. For now, we're just going to provide functions into a genserver that provide the same basic semantics.</p> | |
| <p>Let's open up the test file and start defining the genserver:</p> | |
| <div class="highlight highlight-elixir"> | |
| <pre> | |
| <span class="pl-c"> # We want to have an instance for each of our tests, so let's refactor this to</span> | |
| <span class="pl-c"> # use a setup...</span> | |
| setup <span class="pl-k">do</span> | |
| {<span class="pl-c1">:ok</span>, pid} <span class="pl-k">=</span> <span class="pl-vo">Logo</span>.<span class="pl-vo">Instance</span>.start | |
| {<span class="pl-c1">:ok</span>, <span class="pl-c1">pid:</span> pid} | |
| <span class="pl-k">end</span> | |
| test <span class="pl-s1"><span class="pl-pds">"</span>can start a logo instance<span class="pl-pds">"</span></span>, meta <span class="pl-k">do</span> | |
| assert is_pid(meta[<span class="pl-c1">:pid</span>]) | |
| <span class="pl-k">end</span></pre> | |
| </div> | |
| <p>Alright, now let's start to implement the functions from the README. The first thing we need to support is setting the color.</p> | |
| <div class="highlight highlight-elixir"> | |
| <pre> | |
| <span class="pl-k">alias</span> <span class="pl-vo">Logo</span>.<span class="pl-vo">Instance</span> | |
| <span class="pl-c"> #...</span> | |
| test <span class="pl-s1"><span class="pl-pds">"</span>can set the color<span class="pl-pds">"</span></span>, meta <span class="pl-k">do</span> | |
| turtle <span class="pl-k">=</span> meta[<span class="pl-c1">:pid</span>] | |
| <span class="pl-k">|</span><span class="pl-k">></span> <span class="pl-vo">Instance</span>.color({<span class="pl-c1">255</span>, <span class="pl-c1">0</span>, <span class="pl-c1">0</span>}) | |
| <span class="pl-k">|</span><span class="pl-k">></span> <span class="pl-vo">Instance</span>.get_turtle | |
| assert {<span class="pl-c1">255</span>, <span class="pl-c1">0</span>, <span class="pl-c1">0</span>} <span class="pl-k">=</span> turtle.color | |
| <span class="pl-k">end</span></pre> | |
| </div> | |
| <p>Alright, so we get an error. Let's open up the Logo.Instance module and add the functions necessary for this to pass:</p> | |
| <div class="highlight highlight-elixir"> | |
| <pre> | |
| <span class="pl-k">defmodule</span> <span class="pl-en">Logo.Instance</span> <span class="pl-k">do</span> | |
| <span class="pl-k">use</span> <span class="pl-vo">GenServer</span> | |
| <span class="pl-k">alias</span> <span class="pl-v">__MODULE__</span> | |
| <span class="pl-c"> # So we know we need a turtle to store the color</span> | |
| <span class="pl-k">defmodule</span> <span class="pl-en">Turtle</span> <span class="pl-k">do</span> | |
| <span class="pl-k">defstruct</span> [ | |
| <span class="pl-c1">color:</span> <span class="pl-c1">nil</span> | |
| ] | |
| <span class="pl-k">end</span> | |
| <span class="pl-c"> # Public API</span> | |
| <span class="pl-k">def</span> start <span class="pl-k">do</span> | |
| <span class="pl-c"> # We want to pass in a new instance of our server's turtle when we start it</span> | |
| <span class="pl-c"> # up</span> | |
| <span class="pl-vo">GenServer</span>.start(<span class="pl-vo">Instance</span>, %<span class="pl-vo">Turtle</span>{}, []) | |
| <span class="pl-k">end</span> | |
| <span class="pl-c"> # We'll implement the public color function. Note that we're returning the</span> | |
| <span class="pl-c"> # pid so that this will be a chainable API</span> | |
| <span class="pl-k">def</span> color(pid, {r, g, b}) <span class="pl-k">do</span> | |
| <span class="pl-c1">:ok</span> <span class="pl-k">=</span> <span class="pl-vo">GenServer</span>.cast(pid, {<span class="pl-c1">:color</span>, {r, g, b}}) | |
| pid | |
| <span class="pl-k">end</span> | |
| <span class="pl-c"> # `get_turtle` won't be part of the chainable API since it's a call rather than a</span> | |
| <span class="pl-c"> # cast.</span> | |
| <span class="pl-k">def</span> get_turtle(pid) <span class="pl-k">do</span> | |
| <span class="pl-vo">GenServer</span>.call(pid, <span class="pl-c1">:get_turtle</span>) | |
| <span class="pl-k">end</span> | |
| <span class="pl-c"> # Server callbacks</span> | |
| <span class="pl-k">def</span> init(turtle) <span class="pl-k">do</span> | |
| {<span class="pl-c1">:ok</span>, turtle} | |
| <span class="pl-k">end</span> | |
| <span class="pl-c"> # Handling the color cast is trivial</span> | |
| <span class="pl-k">def</span> handle_cast({<span class="pl-c1">:color</span>, {r, g, b}}, turtle) <span class="pl-k">do</span> | |
| {<span class="pl-c1">:noreply</span>, %<span class="pl-vo">Turtle</span>{turtle<span class="pl-k">|</span><span class="pl-c1">color:</span> {r, g, b}}} | |
| <span class="pl-k">end</span> | |
| <span class="pl-c"> # So is the get_turtle call</span> | |
| <span class="pl-k">def</span> handle_call(<span class="pl-c1">:get_turtle</span>, _from, turtle) <span class="pl-k">do</span> | |
| {<span class="pl-c1">:reply</span>, turtle, turtle} | |
| <span class="pl-k">end</span> | |
| <span class="pl-k">end</span></pre> | |
| </div> | |
| <p>Alright, run the tests, and they should pass. This isn't a complicated bit of code at all at this point, so I don't really think it deserves any explanation. We'll power through and implement the rest of the API mentioned in the README. Next is <code>pen_down</code>.</p> | |
| <div class="highlight highlight-elixir"> | |
| <pre> | |
| test <span class="pl-s1"><span class="pl-pds">"</span>can put the pen down<span class="pl-pds">"</span></span>, meta <span class="pl-k">do</span> | |
| turtle <span class="pl-k">=</span> meta[<span class="pl-c1">:pid</span>] | |
| <span class="pl-k">|</span><span class="pl-k">></span> <span class="pl-vo">Instance</span>.pen_down | |
| <span class="pl-k">|</span><span class="pl-k">></span> <span class="pl-vo">Instance</span>.get_turtle | |
| assert turtle.pen_down | |
| <span class="pl-k">end</span></pre> | |
| </div> | |
| <p>There's our test. We'll implement it rapidly.</p> | |
| <div class="highlight highlight-elixir"> | |
| <pre> | |
| <span class="pl-k">defmodule</span> <span class="pl-en">Turtle</span> <span class="pl-k">do</span> | |
| <span class="pl-c"> # Here we're just going to track a boolean that specifies whether the pen is</span> | |
| <span class="pl-c"> # down or not</span> | |
| <span class="pl-k">defstruct</span> [ | |
| <span class="pl-c1">color:</span> <span class="pl-c1">nil</span>, | |
| <span class="pl-c1">pen_down:</span> <span class="pl-c1">false</span> | |
| ] | |
| <span class="pl-k">end</span> | |
| <span class="pl-c"> #...</span> | |
| <span class="pl-c"> # And a function to put it down</span> | |
| <span class="pl-k">def</span> pen_down(pid) <span class="pl-k">do</span> | |
| <span class="pl-c1">:ok</span> <span class="pl-k">=</span> <span class="pl-vo">GenServer</span>.cast(pid, <span class="pl-c1">:pen_down</span>) | |
| pid | |
| <span class="pl-k">end</span> | |
| <span class="pl-c"> #...</span> | |
| <span class="pl-c"> # And in our handle_cast we'll update the turtle to put the pen down</span> | |
| <span class="pl-k">def</span> handle_cast(<span class="pl-c1">:pen_down</span>, turtle) <span class="pl-k">do</span> | |
| {<span class="pl-c1">:noreply</span>, %<span class="pl-vo">Turtle</span>{turtle<span class="pl-k">|</span><span class="pl-c1">pen_down:</span> <span class="pl-c1">true</span>}} | |
| <span class="pl-k">end</span></pre> | |
| </div> | |
| <p>Run the tests and they'll pass.</p> | |
| <p>Next we need to implement forward. This requires us to start tracking x and y coordinates for our turtle. We'll start with the test:</p> | |
| <div class="highlight highlight-elixir"> | |
| <pre> | |
| test <span class="pl-s1"><span class="pl-pds">"</span>can move forward<span class="pl-pds">"</span></span>, meta <span class="pl-k">do</span> | |
| turtle <span class="pl-k">=</span> meta[<span class="pl-c1">:pid</span>] | |
| <span class="pl-k">|</span><span class="pl-k">></span> <span class="pl-vo">Instance</span>.forward(<span class="pl-c1">400</span>) | |
| <span class="pl-k">|</span><span class="pl-k">></span> <span class="pl-vo">Instance</span>.get_turtle | |
| assert <span class="pl-c1">400</span> <span class="pl-k">=</span> turtle.x | |
| <span class="pl-k">end</span></pre> | |
| </div> | |
| <p>If we run the test, obviously there's no forward function. We'll add it:</p> | |
| <div class="highlight highlight-elixir"> | |
| <pre> | |
| <span class="pl-c"> # We need to add coordinates for the turtle</span> | |
| <span class="pl-k">defmodule</span> <span class="pl-en">Turtle</span> <span class="pl-k">do</span> | |
| <span class="pl-k">defstruct</span> [ | |
| <span class="pl-c1">color:</span> <span class="pl-c1">nil</span>, | |
| <span class="pl-c1">pen_down:</span> <span class="pl-c1">false</span>, | |
| <span class="pl-c1">x:</span> <span class="pl-c1">0</span>, | |
| <span class="pl-c1">y:</span> <span class="pl-c1">0</span> | |
| ] | |
| <span class="pl-k">end</span> | |
| <span class="pl-c"> # Here's the public function</span> | |
| <span class="pl-k">def</span> forward(pid, amount) <span class="pl-k">do</span> | |
| <span class="pl-c1">:ok</span> <span class="pl-k">=</span> <span class="pl-vo">GenServer</span>.cast(pid, {<span class="pl-c1">:forward</span>, amount}) | |
| pid | |
| <span class="pl-k">end</span> | |
| <span class="pl-c"> # And the function that updates the state</span> | |
| <span class="pl-k">def</span> handle_cast({<span class="pl-c1">:forward</span>, amount}, turtle) <span class="pl-k">do</span> | |
| {<span class="pl-c1">:noreply</span>, %<span class="pl-vo">Turtle</span>{turtle<span class="pl-k">|</span><span class="pl-c1">x:</span> turtle.x <span class="pl-k">+</span> amount}} | |
| <span class="pl-k">end</span></pre> | |
| </div> | |
| <p>Run the tests and they'll pass. There are two other real issues to handle. The first is that we need to handle modifying the angle at which the turtle is pointing. This is easy enough and continues to be a typical basic state update. Let's add the test:</p> | |
| <div class="highlight highlight-elixir"> | |
| <pre> | |
| test <span class="pl-s1"><span class="pl-pds">"</span>can rotate<span class="pl-pds">"</span></span>, meta <span class="pl-k">do</span> | |
| turtle <span class="pl-k">=</span> meta[<span class="pl-c1">:pid</span>] | |
| <span class="pl-k">|</span><span class="pl-k">></span> <span class="pl-vo">Instance</span>.right(<span class="pl-c1">90</span>) | |
| <span class="pl-k">|</span><span class="pl-k">></span> <span class="pl-vo">Instance</span>.get_turtle | |
| assert <span class="pl-c1">90</span> <span class="pl-k">=</span> turtle.angle | |
| turtle <span class="pl-k">=</span> meta[<span class="pl-c1">:pid</span>] | |
| <span class="pl-k">|</span><span class="pl-k">></span> <span class="pl-vo">Instance</span>.right(<span class="pl-c1">360</span>) | |
| <span class="pl-k">|</span><span class="pl-k">></span> <span class="pl-vo">Instance</span>.get_turtle | |
| assert <span class="pl-c1">90</span> <span class="pl-k">=</span> turtle.angle | |
| <span class="pl-k">end</span></pre> | |
| </div> | |
| <p>Alright, so there's no <code>right</code> function yet so we'll add that, along with an angle key in the Turtle:</p> | |
| <div class="highlight highlight-elixir"> | |
| <pre> | |
| <span class="pl-k">defmodule</span> <span class="pl-en">Turtle</span> <span class="pl-k">do</span> | |
| <span class="pl-k">defstruct</span> [ | |
| <span class="pl-c1">color:</span> <span class="pl-c1">nil</span>, | |
| <span class="pl-c1">pen_down:</span> <span class="pl-c1">false</span>, | |
| <span class="pl-c1">x:</span> <span class="pl-c1">0</span>, | |
| <span class="pl-c1">y:</span> <span class="pl-c1">0</span>, | |
| <span class="pl-c1">angle:</span> <span class="pl-c1">0</span> | |
| ] | |
| <span class="pl-k">end</span> | |
| <span class="pl-k">def</span> right(pid, angle) <span class="pl-k">do</span> | |
| <span class="pl-c1">:ok</span> <span class="pl-k">=</span> <span class="pl-vo">GenServer</span>.cast(pid, {<span class="pl-c1">:right</span>, angle}) | |
| pid | |
| <span class="pl-k">end</span> | |
| <span class="pl-k">def</span> handle_cast({<span class="pl-c1">:right</span>, angle}, turtle) <span class="pl-k">do</span> | |
| <span class="pl-c"> # Now this is the only quirky bit. Since we always want this to be</span> | |
| <span class="pl-c"> # positive, I'm adding 360 to whatever it is. Then I'm using rem to make</span> | |
| <span class="pl-c"> # sure it cycles at 360.</span> | |
| angle <span class="pl-k">=</span> rem(<span class="pl-c1">360</span> <span class="pl-k">+</span> turtle.angle <span class="pl-k">+</span> angle, <span class="pl-c1">360</span>) | |
| {<span class="pl-c1">:noreply</span>, %<span class="pl-vo">Turtle</span>{turtle<span class="pl-k">|</span><span class="pl-c1">angle:</span> angle}} | |
| <span class="pl-k">end</span></pre> | |
| </div> | |
| <p>Now we can run the tests and they'll pass. It's not in the readme, but let's go ahead and implement a <code>left</code> function as well:</p> | |
| <div class="highlight highlight-elixir"> | |
| <pre> | |
| test <span class="pl-s1"><span class="pl-pds">"</span>can rotate<span class="pl-pds">"</span></span>, meta <span class="pl-k">do</span> | |
| turtle <span class="pl-k">=</span> meta[<span class="pl-c1">:pid</span>] | |
| <span class="pl-k">|</span><span class="pl-k">></span> <span class="pl-vo">Instance</span>.right(<span class="pl-c1">90</span>) | |
| <span class="pl-k">|</span><span class="pl-k">></span> <span class="pl-vo">Instance</span>.get_turtle | |
| assert <span class="pl-c1">90</span> <span class="pl-k">=</span> turtle.angle | |
| turtle <span class="pl-k">=</span> meta[<span class="pl-c1">:pid</span>] | |
| <span class="pl-k">|</span><span class="pl-k">></span> <span class="pl-vo">Instance</span>.right(<span class="pl-c1">360</span>) | |
| <span class="pl-k">|</span><span class="pl-k">></span> <span class="pl-vo">Instance</span>.get_turtle | |
| assert <span class="pl-c1">90</span> <span class="pl-k">=</span> turtle.angle | |
| turtle <span class="pl-k">=</span> meta[<span class="pl-c1">:pid</span>] | |
| <span class="pl-k">|</span><span class="pl-k">></span> <span class="pl-vo">Instance</span>.left(<span class="pl-c1">20</span>) | |
| <span class="pl-k">|</span><span class="pl-k">></span> <span class="pl-vo">Instance</span>.get_turtle | |
| assert <span class="pl-c1">70</span> <span class="pl-k">=</span> turtle.angle | |
| <span class="pl-k">end</span></pre> | |
| </div> | |
| <p>Run the tests and they'll fail. Now we implement it:</p> | |
| <div class="highlight highlight-elixir"> | |
| <pre> | |
| <span class="pl-c"> # Now we don't want to implement a `left` cast, since our `right` cast was</span> | |
| <span class="pl-c"> # really just setting a delta on the angle. We'll change its name and then</span> | |
| <span class="pl-c"> # just use the same server API to implement left</span> | |
| <span class="pl-k">def</span> right(pid, angle) <span class="pl-k">do</span> | |
| <span class="pl-c1">:ok</span> <span class="pl-k">=</span> <span class="pl-vo">GenServer</span>.cast(pid, {<span class="pl-c1">:angle_delta</span>, angle}) | |
| pid | |
| <span class="pl-k">end</span> | |
| <span class="pl-k">def</span> left(pid, angle) <span class="pl-k">do</span> | |
| <span class="pl-c1">:ok</span> <span class="pl-k">=</span> <span class="pl-vo">GenServer</span>.cast(pid, {<span class="pl-c1">:angle_delta</span>, <span class="pl-k">-</span><span class="pl-c1">1</span> <span class="pl-k">*</span> angle}) | |
| pid | |
| <span class="pl-k">end</span> | |
| <span class="pl-k">def</span> handle_cast({<span class="pl-c1">:angle_delta</span>, angle}, turtle) <span class="pl-k">do</span> | |
| angle <span class="pl-k">=</span> rem(<span class="pl-c1">360</span> <span class="pl-k">+</span> turtle.angle <span class="pl-k">+</span> angle, <span class="pl-c1">360</span>) | |
| {<span class="pl-c1">:noreply</span>, %<span class="pl-vo">Turtle</span>{turtle<span class="pl-k">|</span><span class="pl-c1">angle:</span> angle}} | |
| <span class="pl-k">end</span></pre> | |
| </div> | |
| <p>Run the tests, and they'll pass. Now this is almost good enough. However, when we go forward we just increment X. That's not right. We need to do trig here folks! First we'll need a function to convert degrees to radians:</p> | |
| <div class="highlight highlight-elixir"> | |
| <pre> | |
| <span class="pl-k">def</span> radians(degrees) <span class="pl-k">do</span> | |
| degrees <span class="pl-k">*</span> (<span class="pl-c1">:math</span>.pi<span class="pl-k">/</span><span class="pl-c1">180</span>) | |
| <span class="pl-k">end</span></pre> | |
| </div> | |
| <p>And I'm adding a test after the fact to show that this works, although honestly this has been proved by things a lot more rigorous than our test suite :)</p> | |
| <div class="highlight highlight-elixir"> | |
| <pre> | |
| test <span class="pl-s1"><span class="pl-pds">"</span>converting degrees to radians<span class="pl-pds">"</span></span> <span class="pl-k">do</span> | |
| assert (<span class="pl-c1">3</span> <span class="pl-k">*</span> <span class="pl-c1">:math</span>.pi)<span class="pl-k">/</span><span class="pl-c1">2</span> <span class="pl-k">==</span> <span class="pl-vo">Instance</span>.radians(<span class="pl-c1">270</span>) | |
| <span class="pl-k">end</span></pre> | |
| </div> | |
| <p>I know that's not the right place for this function, but it'll have to do for now. Next we need to add a test that makes the turtle walk forward at an angle and verifies that it ends up at the right place. The easiest thing to do is to turn him 45 degrees and walk him (square root of 2) forward. This should place him at the coordinates (1, 1).</p> | |
| <div class="highlight highlight-elixir"> | |
| <pre> | |
| test <span class="pl-s1"><span class="pl-pds">"</span>walking at an angle<span class="pl-pds">"</span></span>, meta <span class="pl-k">do</span> | |
| turtle <span class="pl-k">=</span> meta[<span class="pl-c1">:pid</span>] | |
| <span class="pl-k">|</span><span class="pl-k">></span> <span class="pl-vo">Instance</span>.right(<span class="pl-c1">45</span>) | |
| <span class="pl-k">|</span><span class="pl-k">></span> <span class="pl-vo">Instance</span>.forward(<span class="pl-c1">:math</span>.sqrt(<span class="pl-c1">2</span>)) | |
| <span class="pl-k">|</span><span class="pl-k">></span> <span class="pl-vo">Instance</span>.get_turtle | |
| assert <span class="pl-c1">1</span> <span class="pl-k">=</span> turtle.x | |
| assert <span class="pl-c1">1</span> <span class="pl-k">=</span> turtle.y | |
| <span class="pl-k">end</span></pre> | |
| </div> | |
| <p>Run the tests, and they fail because our forward function is broken and awful. Let's fix it with math.</p> | |
| <div class="highlight highlight-elixir"> | |
| <pre> | |
| <span class="pl-k">def</span> handle_cast({<span class="pl-c1">:forward</span>, amount}, turtle) <span class="pl-k">do</span> | |
| delta_x <span class="pl-k">=</span> amount <span class="pl-k">*</span> <span class="pl-c1">:math</span>.cos(radians(turtle.angle)) | |
| delta_y <span class="pl-k">=</span> amount <span class="pl-k">*</span> <span class="pl-c1">:math</span>.sin(radians(turtle.angle)) | |
| {<span class="pl-c1">:noreply</span>, %<span class="pl-vo">Turtle</span>{turtle<span class="pl-k">|</span><span class="pl-c1">x:</span> turtle.x <span class="pl-k">+</span> delta_x, <span class="pl-c1">y:</span> turtle.y <span class="pl-k">+</span> delta_y}} | |
| <span class="pl-k">end</span></pre> | |
| </div> | |
| <p>So here we're moving our turtle forward by the appropriate amount based on its current angle. If we run our tests, they'll fail because floats aren't precise. Let's change them to use <code>assert_in_delta</code> instead.</p> | |
| <div class="highlight highlight-elixir"> | |
| <pre> | |
| test <span class="pl-s1"><span class="pl-pds">"</span>can move forward<span class="pl-pds">"</span></span>, meta <span class="pl-k">do</span> | |
| turtle <span class="pl-k">=</span> meta[<span class="pl-c1">:pid</span>] | |
| <span class="pl-k">|</span><span class="pl-k">></span> <span class="pl-vo">Instance</span>.forward(<span class="pl-c1">400</span>) | |
| <span class="pl-k">|</span><span class="pl-k">></span> <span class="pl-vo">Instance</span>.get_turtle | |
| assert_in_delta(<span class="pl-c1">400</span>, turtle.x, <span class="pl-c1">0.00001</span>) | |
| <span class="pl-k">end</span> | |
| test <span class="pl-s1"><span class="pl-pds">"</span>walking at an angle<span class="pl-pds">"</span></span>, meta <span class="pl-k">do</span> | |
| turtle <span class="pl-k">=</span> meta[<span class="pl-c1">:pid</span>] | |
| <span class="pl-k">|</span><span class="pl-k">></span> <span class="pl-vo">Instance</span>.right(<span class="pl-c1">45</span>) | |
| <span class="pl-k">|</span><span class="pl-k">></span> <span class="pl-vo">Instance</span>.forward(<span class="pl-c1">:math</span>.sqrt(<span class="pl-c1">2</span>)) | |
| <span class="pl-k">|</span><span class="pl-k">></span> <span class="pl-vo">Instance</span>.get_turtle | |
| assert_in_delta(<span class="pl-c1">1</span>, turtle.x, <span class="pl-c1">0.00001</span>) | |
| assert_in_delta(<span class="pl-c1">1</span>, turtle.y, <span class="pl-c1">0.00001</span>) | |
| <span class="pl-k">end</span></pre> | |
| </div> | |
| <h2>Summary</h2> | |
| <p>This is conceptually what we need to handle the logo language as far as our current use of it goes. However, it doesn't, you know, <em>draw</em> anything yet. Logo without drawing is pointless, right?</p> | |
| <p>As I'd mentioned, I already built a basic wx canvas before we started this episode. But honestly, even though I was a math major, doing trig again makes me tired. So we'll start drawing the turtle's tracks on that canvas in the next episode - but you should probably go ahead and try to implement it as an exercise for yourself. See you soon!</p> | |
| <h2>Resources</h2> | |
| <ul class="task-list"> | |
| <li><a href="https://github.com/knewter/logo" rel="noreferrer">knewter/logo</a></li> | |
| <li><a href="http://en.wikipedia.org/wiki/Logo_%28programming_language%29" rel="noreferrer">Logo Programming Language on Wikipedia</a></li> | |
| </ul> | |
| </div> | |
| <h3>Attached Files</h3> | |
| <ul> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=51629">166_Implementing_Logo.mp4</a></li> | |
| <li><a href="https://elixirsips.dpdcart.com/subscriber/download?file_id=51630">166_Implementing_Logo.markdown</a></li> | |
| </ul></div>]]></description> | |
| <guid isPermaLink="false">dpd-5446cc8d8c9ccd06bf00a85aec8ec4172950767e</guid> | |
| <pubDate>Sat, 30 May 2015 21:08:00 -0400</pubDate> | |
| <enclosure url="https://elixirsips.dpdcart.com/feed/download/51629/166_Implementing_Logo.mp4" length="87912447" type="video/mp4"/> | |
| <itunes:subtitle>Implementing the Logo graphical programming language in Elixir with wxWidgets. In this episode we just implement the underlying GenServer.</itunes:subtitle> | |
| </item> | |
| <item> | |
| <title><![CDATA[165 - Accounting 101]]></title> | |
| <link>https://elixirsips.dpdcart.com/subscriber/post?id=774</link> | |
| <description><![CDATA[<div class="blog-entry"> | |
| <div class="blog-content"><h1 style="box-sizing: border-box; font-size: 2.25em; margin-right: 0px; margin-bottom: 16px; margin-left: 0px; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; margin-top: 0px !important;">Episode 165: Accounting 101</h1> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">A company called Subledger recently released a series of documents detailing double entry accounting systems for developers. Most commercial projects can make use of an internalized accounting system, so it seems worthwhile to develop an application for managing charts of accounts. Let's get started, using their document as a reference point.</p> | |
| <h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; position: relative; font-weight: bold; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Project</h2> | |
| <h3 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.43; font-size: 1.5em; position: relative; font-weight: bold; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Setup</h3> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">We'll start a new application:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| mix new ledger <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">--</span>sup | |
| cd ledger | |
| mkdir test<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">/</span>ledger</pre> | |
| </div> | |
| <h3 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.43; font-size: 1.5em; position: relative; font-weight: bold; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Accounts</h3> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">The first entity we need to account for in an accounting system is an <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">Account</code>. It can be expected to be either a <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">:debit</code> or a <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">:credit</code> account. We'll add a test for this, not because we need to test structs, but so that our tests can serve as documentation for the system as we go along.</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">Ledger.Account</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defstruct</span> [ | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">type:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">nil</span> | |
| ] | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">@typedoc """</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> An account can be either `:credit` or `:debit`.</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> """</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">@type</span> account_type <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">::</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:credit</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:debit</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">@typedoc """</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> A Ledger Account has a `type`.</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> """</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">@type</span> t <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">::</span> %<span class="pl-v" style="box-sizing: border-box; color: rgb(29, 62, 129);">__MODULE__</span>{ | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">type:</span> account_type | |
| } | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">Ledger.AccountTest</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">use</span> <span class="pl-vo" style="box-sizing: border-box;">ExUnit</span>.<span class="pl-vo" style="box-sizing: border-box;">Case</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-vo" style="box-sizing: border-box;">Ledger</span>.<span class="pl-vo" style="box-sizing: border-box;">Account</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">@credit_account</span> %<span class="pl-vo" style="box-sizing: border-box;">Account</span>{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">type:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:credit</span>} | |
| <span class="pl-vo" style="box-sizing: border-box;">@debit_account</span> %<span class="pl-vo" style="box-sizing: border-box;">Account</span>{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">type:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:debit</span>} | |
| test <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>Accounts can be either Credit or Debit accounts<span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| assert <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:debit</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-vo" style="box-sizing: border-box;">@debit_account</span>.type | |
| assert <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:credit</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-vo" style="box-sizing: border-box;">@credit_account</span>.type | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Accounts have a balance. In accounting, balances are comprised of two values: the sum of debit and the sum of credit. The net balance is the smaller subtracted from the larger. The balance of a 5-debit and 10-credit is a 5-credit.</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| test <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>Accounts have credits and debits<span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| account <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-vo" style="box-sizing: border-box;">Account</span>.debit(<span class="pl-vo" style="box-sizing: border-box;">@credit_account</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">5</span>) | |
| account <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-vo" style="box-sizing: border-box;">Account</span>.credit(account, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">10</span>) | |
| assert <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">5</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-vo" style="box-sizing: border-box;">Account</span>.debits_sum(account) | |
| assert <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">10</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-vo" style="box-sizing: border-box;">Account</span>.credits_sum(account) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Let's add the concept of an account having a list of debits and credits:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">Ledger.Account</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-v" style="box-sizing: border-box; color: rgb(29, 62, 129);">__MODULE__</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defstruct</span> [ | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">type:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">nil</span>, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">debits:</span> [], | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">credits:</span> [] | |
| ] | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">@typedoc """</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> An account can be either `:credit` or `:debit`.</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> """</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">@type</span> account_type <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">::</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:credit</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:debit</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">@typedoc """</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> An account has a list of debits.</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> """</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">@typedoc """</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> A Ledger Account has a `type`, a list of `credits, and a list of `debits`.</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> """</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">@type</span> t <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">::</span> %<span class="pl-vo" style="box-sizing: border-box;">Account</span>{ | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">type:</span> account_type, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">debits:</span> list(<span class="pl-vo" style="box-sizing: border-box;">Debit</span>.t), | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">credits:</span> list(<span class="pl-vo" style="box-sizing: border-box;">Credit</span>.t) | |
| } | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">OK before we move on we'll need to move modules into their own files.</p> | |
| <ul class="task-list" style="box-sizing: border-box; padding-right: 0px; padding-left: 2em; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <li style="box-sizing: border-box;"><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">mkdir lib/ledger</code></li> | |
| <li style="box-sizing: border-box;">move <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">Ledger.Account</code> to <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">lib/ledger/account.ex</code></li> | |
| </ul> | |
| <h3 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.43; font-size: 1.5em; position: relative; font-weight: bold; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Debits and Credits</h3> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">We're referencing a Debit and a Credit type, and we need to make these modules:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">Ledger.Credit</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-v" style="box-sizing: border-box; color: rgb(29, 62, 129);">__MODULE__</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defstruct</span> [ | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">amount:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">nil</span> | |
| ] | |
| <span class="pl-vo" style="box-sizing: border-box;">@type</span> t <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">::</span> %<span class="pl-vo" style="box-sizing: border-box;">Credit</span>{ | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">amount:</span> <span class="pl-vo" style="box-sizing: border-box;">Decimal</span>.t | |
| } | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">Ledger.Debit</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-v" style="box-sizing: border-box; color: rgb(29, 62, 129);">__MODULE__</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defstruct</span> [ | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">amount:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">nil</span> | |
| ] | |
| <span class="pl-vo" style="box-sizing: border-box;">@type</span> t <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">::</span> %<span class="pl-vo" style="box-sizing: border-box;">Debit</span>{ | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">amount:</span> <span class="pl-vo" style="box-sizing: border-box;">Decimal</span>.t | |
| } | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Here we're using a <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">Decimal</code> type that doesn't exist in the standard library but is a hex package. We'll add it to our dependencies.</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defp</span> deps <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| [ | |
| {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:decimal</span>, <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>~> 1.1.0<span class="pl-pds" style="box-sizing: border-box;">"</span></span>} | |
| ] | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <div class="highlight highlight-sh" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| mix deps.get</pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Now let's open up the <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">Account</code> module again and add aliases to our new <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">Debit</code> and <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">Credit</code>modules.</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">Ledger.Account</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-v" style="box-sizing: border-box; color: rgb(29, 62, 129);">__MODULE__</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-vo" style="box-sizing: border-box;">Ledger</span>.<span class="pl-vo" style="box-sizing: border-box;">Debit</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-vo" style="box-sizing: border-box;">Ledger</span>.<span class="pl-vo" style="box-sizing: border-box;">Credit</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> #...</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">We'll run the tests, and they fail because we don't have this debit function. Let's add it to the <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">Account</code>:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> debit(account<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span>%<span class="pl-vo" style="box-sizing: border-box;">Account</span>{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">debits:</span> debits}, amount) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| %<span class="pl-vo" style="box-sizing: border-box;">Account</span>{account <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">debits:</span> [%<span class="pl-vo" style="box-sizing: border-box;">Debit</span>{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">amount:</span> amount}]} | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">We also need a credit function:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> credit(account<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span>%<span class="pl-vo" style="box-sizing: border-box;">Account</span>{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">credits:</span> credits}, amount) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| %<span class="pl-vo" style="box-sizing: border-box;">Account</span>{account <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">credits:</span> [%<span class="pl-vo" style="box-sizing: border-box;">Credit</span>{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">amount:</span> amount}]} | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Alright, so now if we run the tests we're lacking our <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">debits_sum</code> and <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">credits_sum</code> functions. Let's implement these as a reduce over the amounts of each entry in the list:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> debits_sum(account<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span>%<span class="pl-vo" style="box-sizing: border-box;">Account</span>{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">debits:</span> debits}) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">Enum</span>.reduce(debits, <span class="pl-vo" style="box-sizing: border-box;">Decimal</span>.new(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span>), <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">fn</span>(x, acc) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| <span class="pl-vo" style="box-sizing: border-box;">Decimal</span>.add(x.amount, acc) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> credits_sum(account<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span>%<span class="pl-vo" style="box-sizing: border-box;">Account</span>{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">credits:</span> credits}) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">Enum</span>.reduce(credits, <span class="pl-vo" style="box-sizing: border-box;">Decimal</span>.new(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span>), <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">fn</span>(x, acc) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> | |
| <span class="pl-vo" style="box-sizing: border-box;">Decimal</span>.add(x.amount, acc) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span>) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">OK, so this still won't work because the Decimal module needs to operate on Decimal types. Let's change our test to use Decimal types.</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">Ledger.AccountTest</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">use</span> <span class="pl-vo" style="box-sizing: border-box;">ExUnit</span>.<span class="pl-vo" style="box-sizing: border-box;">Case</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-vo" style="box-sizing: border-box;">Ledger</span>.<span class="pl-vo" style="box-sizing: border-box;">Account</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">@credit_account</span> %<span class="pl-vo" style="box-sizing: border-box;">Account</span>{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">type:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:credit</span>} | |
| <span class="pl-vo" style="box-sizing: border-box;">@debit_account</span> %<span class="pl-vo" style="box-sizing: border-box;">Account</span>{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">type:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:debit</span>} | |
| test <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>Accounts can be either Credit or Debit accounts<span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| assert <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:debit</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-vo" style="box-sizing: border-box;">@debit_account</span>.type | |
| assert <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">:credit</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-vo" style="box-sizing: border-box;">@credit_account</span>.type | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| test <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>Accounts have credits and debits<span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| account <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-vo" style="box-sizing: border-box;">Account</span>.debit(<span class="pl-vo" style="box-sizing: border-box;">@credit_account</span>, <span class="pl-vo" style="box-sizing: border-box;">Decimal</span>.new(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">5</span>)) | |
| account <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-vo" style="box-sizing: border-box;">Account</span>.credit(account, <span class="pl-vo" style="box-sizing: border-box;">Decimal</span>.new(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">10</span>)) | |
| assert <span class="pl-vo" style="box-sizing: border-box;">Decimal</span>.new(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">5</span>) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">==</span> <span class="pl-vo" style="box-sizing: border-box;">Account</span>.debits_sum(account) | |
| assert <span class="pl-vo" style="box-sizing: border-box;">Decimal</span>.new(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">10</span>) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">==</span> <span class="pl-vo" style="box-sizing: border-box;">Account</span>.credits_sum(account) | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">And now our tests pass. We now have a concept of an account that holds debits and credits.</p> | |
| <h3 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.43; font-size: 1.5em; position: relative; font-weight: bold; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Journal Entries</h3> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Next we need to implement Journal Entries, which are how entries are made into accounts. Journal Entries are made in at least 2 accounts:</p> | |
| <ul class="task-list" style="box-sizing: border-box; padding-right: 0px; padding-left: 2em; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;"> | |
| <li style="box-sizing: border-box;">A <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">Debit</code> account, where account value is going <em style="box-sizing: border-box;">to</em></li> | |
| <li style="box-sizing: border-box;">A <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">Credit</code> account, where account value is coming <em style="box-sizing: border-box;">from</em></li> | |
| </ul> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Let's write a test for a Journal Entry:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">Ledger.JournalEntryTest</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">use</span> <span class="pl-vo" style="box-sizing: border-box;">ExUnit</span>.<span class="pl-vo" style="box-sizing: border-box;">Case</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-vo" style="box-sizing: border-box;">Ledger</span>.<span class="pl-vo" style="box-sizing: border-box;">JournalEntry</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-vo" style="box-sizing: border-box;">Ledger</span>.<span class="pl-vo" style="box-sizing: border-box;">Debit</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-vo" style="box-sizing: border-box;">Ledger</span>.<span class="pl-vo" style="box-sizing: border-box;">Credit</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">@debit_entry</span> %<span class="pl-vo" style="box-sizing: border-box;">Debit</span>{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">amount:</span> <span class="pl-vo" style="box-sizing: border-box;">Decimal</span>.new(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">5</span>)} | |
| <span class="pl-vo" style="box-sizing: border-box;">@credit_entry</span> %<span class="pl-vo" style="box-sizing: border-box;">Credit</span>{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">amount:</span> <span class="pl-vo" style="box-sizing: border-box;">Decimal</span>.new(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">5</span>)} | |
| test <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>Borrow Cash<span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # We'll start off just describing a JournalEntry struct</span> | |
| entry <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> %<span class="pl-vo" style="box-sizing: border-box;">JournalEntry</span>{ | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # It has a creation time</span> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">created_at:</span> {{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">2014</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">07</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">31</span>}, {<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span>}}, | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # We need to describe what this entry represents</span> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">description:</span> <span class="pl-s1" style="box-sizing: border-box; color: rgb(223, 80, 0);"><span class="pl-pds" style="box-sizing: border-box;">"</span>Borrowed money from Sam<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # And it will consist of a list of items</span> | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">items:</span> [ | |
| <span class="pl-vo" style="box-sizing: border-box;">@debit_entry</span>, | |
| <span class="pl-vo" style="box-sizing: border-box;">@credit_entry</span> | |
| ] | |
| } | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # We should be able to see the sum of the debit and credit amounts for the</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # entry</span> | |
| assert %<span class="pl-vo" style="box-sizing: border-box;">Debit</span>{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">amount:</span> <span class="pl-vo" style="box-sizing: border-box;">Decimal</span>.new(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">5</span>)} <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">==</span> <span class="pl-vo" style="box-sizing: border-box;">JournalEntry</span>.total(entry).debit | |
| assert %<span class="pl-vo" style="box-sizing: border-box;">Credit</span>{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">amount:</span> <span class="pl-vo" style="box-sizing: border-box;">Decimal</span>.new(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">5</span>)} <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">==</span> <span class="pl-vo" style="box-sizing: border-box;">JournalEntry</span>.total(entry).credit | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">OK, so it's easy enough to build out the struct we've defined here:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defmodule</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">Ledger.JournalEntry</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-v" style="box-sizing: border-box; color: rgb(29, 62, 129);">__MODULE__</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-vo" style="box-sizing: border-box;">Ledger</span>.<span class="pl-vo" style="box-sizing: border-box;">Credit</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">alias</span> <span class="pl-vo" style="box-sizing: border-box;">Ledger</span>.<span class="pl-vo" style="box-sizing: border-box;">Debit</span> | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">defstruct</span> [ | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">created_at:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">nil</span>, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">description:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">nil</span>, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">items:</span> [] | |
| ] | |
| <span class="pl-vo" style="box-sizing: border-box;">@type</span> t <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">::</span> %<span class="pl-vo" style="box-sizing: border-box;">JournalEntry</span>{ | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">created_at:</span> {{integer, integer, integer}, {integer, integer, integer}}, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">description:</span> <span class="pl-vo" style="box-sizing: border-box;">String</span>.t, | |
| <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">items:</span> list(%<span class="pl-vo" style="box-sizing: border-box;">Debit</span>{} <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span> %<span class="pl-vo" style="box-sizing: border-box;">Credit</span>{}) | |
| } | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">end</span></pre> | |
| </div> | |
| <p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px;">Now let's define the <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; padding: 0.2em 0px; margin: 0px; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">total</code> function:</p> | |
| <div class="highlight highlight-elixir" style="box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> | |
| <pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-radius: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247);"> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # We're going to take a JournalEntry and return a map representing the total</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # debit and credit for this entry</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">@spec</span> total(<span class="pl-vo" style="box-sizing: border-box;">JournalEntry</span>.t) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">::</span> %{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">debit:</span> %<span class="pl-vo" style="box-sizing: border-box;">Debit</span>{}, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">credit:</span> %<span class="pl-vo" style="box-sizing: border-box;">Credit</span>{}} | |
| <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">def</span> total(%<span class="pl-vo" style="box-sizing: border-box;">JournalEntry</span>{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">items:</span> items}) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">do</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Let's define the initial state for both the debit and credit sides of the</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # total</span> | |
| debit <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> %<span class="pl-vo" style="box-sizing: border-box;">Debit</span>{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">amount:</span> <span class="pl-vo" style="box-sizing: border-box;">Decimal</span>.new(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span>)} | |
| credit <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> %<span class="pl-vo" style="box-sizing: border-box;">Credit</span>{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">amount:</span> <span class="pl-vo" style="box-sizing: border-box;">Decimal</span>.new(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span>)} | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # Now we'll just reduce through the items in the entry, putting the debits</span> | |
| <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);"> # on the debit side and the credits on the credit side.</span> | |
| <span class="pl-vo" style="box-sizing: border-box;">Enum</span>.reduce(items, %{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">debit:</span> debit, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">credit:</span> credit}, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">fn</span> | |
| %<span class="pl-vo" style="box-sizing: border-box;">Debit</span>{<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">amount:</span> amount}, acc <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">-</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span> %{acc <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">debit:</span> %<span class="pl-vo" style="box-sizing: border-box;">Debit</span>{ acc.debit <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">|</span> <span class="pl-c1" style="box-sizing: border-box; col |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment