<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: James</title>
    <description>The latest articles on DEV Community by James (@jsrn).</description>
    <link>https://dev.to/jsrn</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F17334%2Ffa7525d5-cdf4-462a-80e9-a620f7541aa4.jpg</url>
      <title>DEV Community: James</title>
      <link>https://dev.to/jsrn</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jsrn"/>
    <language>en</language>
    <item>
      <title>Assertions of Truth in Ruby Tests</title>
      <dc:creator>James</dc:creator>
      <pubDate>Tue, 12 Jan 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/jsrn/assertions-of-truth-in-ruby-tests-3ebo</link>
      <guid>https://dev.to/jsrn/assertions-of-truth-in-ruby-tests-3ebo</guid>
      <description>&lt;p&gt;I used to write my assertions like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;active?&lt;/span&gt;
&lt;span class="n"&gt;refute&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;inactive?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I joined a team where I was encouraged to write this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;assert_equal&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;active?&lt;/span&gt;
&lt;span class="n"&gt;assert_equal&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;inactive?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;What?&lt;/em&gt; That doesn’t look very nice. That’s doesn’t feel very &lt;em&gt;Ruby&lt;/em&gt;. It’s less elegant!&lt;/p&gt;

&lt;p&gt;Here’s the thing, though: your unit tests aren’t about being elegant. They’re about guaranteeing correctness. You open the door to some insidious bugs when you test truthiness instead of truth.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You might perform an assignment rather than comparing equality.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;active?&lt;/span&gt;
  &lt;span class="c1"&gt;# Should be status == :active&lt;/span&gt;
  &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:active&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;You might check the presence of an array, rather than its length.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;has_users?&lt;/span&gt;
  &lt;span class="c1"&gt;# Should be user_list.any?&lt;/span&gt;
  &lt;span class="n"&gt;user_list&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;user_list&lt;/span&gt;
  &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Over time, I’ve gotten used to it. This style still chafes, but not as badly as bugs caused by returning the wrong value from a predicate method.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>testing</category>
      <category>programming</category>
    </item>
    <item>
      <title>The Surprising Case of `gets` in Ruby</title>
      <dc:creator>James</dc:creator>
      <pubDate>Thu, 07 Jan 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/jsrn/the-surprising-case-of-gets-in-ruby-74b</link>
      <guid>https://dev.to/jsrn/the-surprising-case-of-gets-in-ruby-74b</guid>
      <description>&lt;p&gt;&lt;code&gt;gets&lt;/code&gt; is seen is basically every introductory Ruby tutorial, but they rarely tell the whole story.&lt;/p&gt;

&lt;p&gt;You’ll be told to write something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env ruby&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"What is your name?"&lt;/span&gt;
&lt;span class="n"&gt;your_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;gets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chomp&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Hi, &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;your_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!"&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Confusingly, if this is in a script that takes additional command line arguments, you may not see “Hi, Janet!”&lt;/p&gt;

&lt;p&gt;If you execute &lt;code&gt;./gets.rb 123&lt;/code&gt; you will pretty quickly be greeted by the following error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./gets.rb:4:in `gets': No such file or directory @ rb_sysopen - 123 (Errno::ENOENT)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The tutorial didn’t warn you about &lt;em&gt;this&lt;/em&gt;. The tutorial is giving you a reduced view of things that may, if you’re like me, leave you scratching your head several years later.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;gets&lt;/code&gt; doesn’t just read user input from $stdin. &lt;code&gt;gets&lt;/code&gt; refers to &lt;a href="https://ruby-doc.org/core-2.7.0/Kernel.html#method-i-gets"&gt;Kernel#gets&lt;/a&gt;, and it behaves like so:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Returns (and assigns to $_) the next line from the list of files in ARGV (or $*), or from standard input if no files are present on the command line.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you really, truly want to prompt the user for their input, you can call &lt;code&gt;gets&lt;/code&gt; on $stdin directly. And who wouldn’t, with a user like you?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;your_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vg"&gt;$stdin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chomp&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>programming</category>
      <category>ruby</category>
      <category>gets</category>
    </item>
    <item>
      <title>Warning on long branch names with git hooks</title>
      <dc:creator>James</dc:creator>
      <pubDate>Wed, 01 Apr 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/jsrn/warning-on-long-branch-names-with-git-hooks-303a</link>
      <guid>https://dev.to/jsrn/warning-on-long-branch-names-with-git-hooks-303a</guid>
      <description>&lt;p&gt;My company does some cool stuff with our CI pipeline. When someone submits a merge request, we know that this branch may require some manual testing before it gets merged. We enable this with a button on the merge request that lets people spin up a docker container running the proposed change, whacking it on our kubernetes cluster, and pointing a URL to it.&lt;/p&gt;

&lt;p&gt;If your branch is called &lt;code&gt;new-feature&lt;/code&gt;, you’ll get a shiny copy of the app running just for you at &lt;code&gt;https://new-feature.review.example.com&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If your branch is called &lt;code&gt;super-amazing-cool-new-feature-that-i-love-and-you-will-too&lt;/code&gt;, you would expect to be able to test your feature at &lt;code&gt;https://super-amazing-cool-new-feature-that-i-love-and-you-will-too.review.example.com&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;So, we hit the button. Things begin to churn. We ping off a request to AWS Certificate Manager and… it tell us off.&lt;/p&gt;

&lt;p&gt;Oh.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Apparently&lt;/em&gt;, the first domain name on a certificate can’t exceed 64 octets in length (including periods). Ours is… somewhat longer than that.&lt;/p&gt;

&lt;p&gt;I wish someone had told me that AWS was going to reject my certificate request &lt;em&gt;before&lt;/em&gt; I created the branch and wrote the code and created the merge request and waited for the automated test suite to run and waited for the docker container to be built.&lt;/p&gt;

&lt;p&gt;Enter &lt;a href="https://githooks.com/"&gt;git hooks&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;git hooks let us execute a script before or after certain git actions. You can do lots of awesome stuff with them, like blocking commits that don’t match certain criteria, triggering deploys in different environments, and more.&lt;/p&gt;

&lt;p&gt;In this case, we want to warn ourselves whenever we create a branch name that is going to result in a domain name that won’t pass AWS Certificate Manager’s checks.&lt;/p&gt;

&lt;p&gt;We know that the base of our URL is &lt;code&gt;.review.example.com&lt;/code&gt;, which is 19 characters long. This gives us (assuming that all of our branch names are plain ol’ UTF-8) 45 characters to play with.&lt;/p&gt;

&lt;p&gt;Let’s drop the following into &lt;code&gt;.git/hooks/post-checkout&lt;/code&gt; and make it executable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/sh&lt;/span&gt;
&lt;span class="nv"&gt;RED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\033[0;31m'&lt;/span&gt;
&lt;span class="nv"&gt;NC&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\033[0m'&lt;/span&gt;
&lt;span class="nv"&gt;branchname&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git status | &lt;span class="nb"&gt;cut&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;' '&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; 3 | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="k"&gt;${#&lt;/span&gt;&lt;span class="nv"&gt;branchname&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;-gt&lt;/span&gt; 45]
&lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;RED&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;💩 This branch name is over 45 characters.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"If you proceed, you will be unable to generate a TLS certificate for your review app.&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NC&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Now when we try to create a branch with a luxuriously long name, we get:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➜ hooks git:(master) git checkout -b super-amazing-cool-new-feature-that-i-love-and-you-will-too
Switched to a new branch 'super-amazing-cool-new-feature-that-i-love-and-you-will-too'
💩 This branch name is over 45 characters.
If you proceed, you will be unable to generate a TLS certificate for your review app.
➜ hooks git:(super-amazing-cool-new-feature-that-i-love-and-you-will-too)

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

&lt;/div&gt;



&lt;p&gt;Sadly there doesn’t seem to be any pre-checkout hook, so you can’t block a branch from being created (or confirm that it’s really what you want), you can only spit out a warning after the fact. But hey, it’s red!&lt;/p&gt;

</description>
      <category>git</category>
    </item>
    <item>
      <title>Finding A Method Declaration With Source Location</title>
      <dc:creator>James</dc:creator>
      <pubDate>Sat, 30 Nov 2019 00:00:00 +0000</pubDate>
      <link>https://dev.to/jsrn/finding-a-method-declaration-with-source-location-2ae6</link>
      <guid>https://dev.to/jsrn/finding-a-method-declaration-with-source-location-2ae6</guid>
      <description>&lt;p&gt;I recently had one of those moments where some code failed, but not in the way I expected it to. To create a contrived example, the scenario was basically this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LocationsController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;update&lt;/span&gt;
    &lt;span class="n"&gt;my_location&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;do_something_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code won’t do what I want it to because I have defined the variable &lt;code&gt;my_location&lt;/code&gt; but then passed &lt;code&gt;location&lt;/code&gt; to another method. What I initially expected upon finding the bug is that I would have seen a &lt;code&gt;NameError&lt;/code&gt; complaining that the local variable &lt;code&gt;location&lt;/code&gt; didn’t exist. But I didn’t. As far as I could tell, &lt;code&gt;location&lt;/code&gt; existed and it was &lt;code&gt;nil&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It wasn’t referenced anywhere else in &lt;code&gt;LocationsController&lt;/code&gt;, nor in &lt;code&gt;ApplicationController&lt;/code&gt;. So what is it? Fortunately, Ruby provides a great way to find out.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LocationsController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;update&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="nb"&gt;method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:location&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;source_location&lt;/span&gt;
    &lt;span class="c1"&gt;# "/usr/local/bundle/gems/actionpack-5.0.7.2/lib/action_controller/metal.rb"&lt;/span&gt;
    &lt;span class="c1"&gt;# 149&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s that mystery solved. There is a method called &lt;code&gt;location&lt;/code&gt; implemented a layer or two up the inheritance hierarchy. We knew it had to come from &lt;em&gt;somewhere&lt;/em&gt;, but &lt;code&gt;source_location&lt;/code&gt; lets us determine the exact location.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>programming</category>
      <category>debugging</category>
    </item>
    <item>
      <title>Modules, Macros, Metaprogramming and Magic</title>
      <dc:creator>James</dc:creator>
      <pubDate>Wed, 05 Jun 2019 00:00:00 +0000</pubDate>
      <link>https://dev.to/jsrn/modules-macros-metaprogramming-and-magic-12k0</link>
      <guid>https://dev.to/jsrn/modules-macros-metaprogramming-and-magic-12k0</guid>
      <description>&lt;p&gt;If you’ve used the &lt;a href="https://rubyonrails.org/"&gt;Rails&lt;/a&gt; framework, you will probably recognise this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Comment&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:article&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This snippet of code implies three things:&lt;/p&gt;

&lt;p&gt;1) We have a table of comments.&lt;br&gt;
2) We have a table of articles.&lt;br&gt;
3) Each comment is related to an article by some ID.&lt;/p&gt;

&lt;p&gt;Rails users will take for granted that if they have an instance of the Comment class, they will be able to execute &lt;code&gt;some_comment.article&lt;/code&gt; to obtain the article that the comment is related to.&lt;/p&gt;

&lt;p&gt;This post will give you an extremely simplified look at how something like Rails’ ActiveRecord relations can be achieved. First, some groundwork.&lt;/p&gt;
&lt;h1&gt;
  
  
  Modules
&lt;/h1&gt;

&lt;p&gt;Modules in Ruby can be used to extend the behaviour of a class, and there are three ways in which they can do this: &lt;code&gt;include&lt;/code&gt;, &lt;code&gt;prepend&lt;/code&gt;, and &lt;code&gt;extend&lt;/code&gt;. The difference between the three? Where they fall in the method lookup chain.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyClass&lt;/span&gt;
  &lt;span class="n"&gt;prepend&lt;/span&gt; &lt;span class="no"&gt;PrependingModule&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;IncludingModule&lt;/span&gt;
  &lt;span class="kp"&gt;extend&lt;/span&gt; &lt;span class="no"&gt;ExtendingModule&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Methods from &lt;code&gt;PrependingModule&lt;/code&gt; will be created as &lt;strong&gt;instance methods&lt;/strong&gt; and &lt;strong&gt;override&lt;/strong&gt; instance methods from &lt;code&gt;MyClass&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Methods from &lt;code&gt;IncludingModule&lt;/code&gt; will be created as &lt;strong&gt;instance methods&lt;/strong&gt; but &lt;strong&gt;not override&lt;/strong&gt; methods from &lt;code&gt;MyClass&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Methods from &lt;code&gt;ExtendingModule&lt;/code&gt; will be added as &lt;strong&gt;class methods&lt;/strong&gt; on &lt;code&gt;MyClass&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can do fun things with &lt;code&gt;extend&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Executing Code During Interpretation Time
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Ownable&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;belongs_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"I belong to &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Item&lt;/span&gt;
  &lt;span class="kp"&gt;extend&lt;/span&gt; &lt;span class="no"&gt;Ownable&lt;/span&gt;
  &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:overlord&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above code, we’re just defining a module and a class. No instance of the class is ever created. However, when we execute &lt;em&gt;just this code&lt;/em&gt; in an IRB session, you will see “I belong to overlord!” as the output. Why? Because the code we write while defining a class is executed as that class definition is being interpreted.&lt;/p&gt;

&lt;p&gt;What if we re-write our module to define a method using Ruby’s &lt;a href="https://apidock.com/ruby/Module/define_method"&gt;define_method&lt;/a&gt;?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Ownable&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;belongs_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;define_method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_sym&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object_id&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Whatever we passed as the argument to &lt;code&gt;belongs_to&lt;/code&gt; will become a method on instances of our &lt;code&gt;Item&lt;/code&gt; class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;our_item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;
&lt;span class="n"&gt;our_item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;overlord&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; 70368441222580&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Excellent. You may have heard this term before, but this is “metaprogramming”. Writing code that writes code. You just metaprogrammed.&lt;/p&gt;

&lt;h1&gt;
  
  
  Tying It Together
&lt;/h1&gt;

&lt;p&gt;You might also notice that we’re getting closer to the behaviour that we would expect from Rails.&lt;/p&gt;

&lt;p&gt;So let’s say we have our &lt;code&gt;Item&lt;/code&gt; class, and we’re making a videogame, so we’re going to say that our item belongs to a player.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Item&lt;/span&gt;
  &lt;span class="kp"&gt;extend&lt;/span&gt; &lt;span class="no"&gt;Ownable&lt;/span&gt;
  &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:player&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our Rails-like system could make some assumptions about this.&lt;/p&gt;

&lt;p&gt;1) There is a table in the database called &lt;code&gt;players&lt;/code&gt;.&lt;br&gt;
2) There is a column in our &lt;code&gt;items&lt;/code&gt; table called &lt;code&gt;player_id&lt;/code&gt;.&lt;br&gt;
3) The player model is represented by the class &lt;code&gt;Player&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let’s return to our module and tweak it based on these assumptions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Ownable&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;belongs_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;define_method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_sym&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="c1"&gt;# We need to get `Player` out of `:player`&lt;/span&gt;
      &lt;span class="n"&gt;klass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;capitalize&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;constantize&lt;/span&gt;
      &lt;span class="c1"&gt;# We need to turn `:player` into `:player_id`&lt;/span&gt;
      &lt;span class="n"&gt;foreign_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;_id"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_sym&lt;/span&gt;
      &lt;span class="c1"&gt;# We need to execute the actual query&lt;/span&gt;
      &lt;span class="n"&gt;klass&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;id: &lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;foreign_key&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="c1"&gt;# SELECT * FROM players WHERE id = :player_id LIMIT 1&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Item&lt;/span&gt;
  &lt;span class="kp"&gt;extend&lt;/span&gt; &lt;span class="no"&gt;Ownable&lt;/span&gt;
  &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:player&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;my_item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;
&lt;span class="n"&gt;my_item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;player&lt;/span&gt;
&lt;span class="c1"&gt;# SELECT * FROM players WHERE id = 1 LIMIT 1&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; #&amp;lt;Player id: 12&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Neat.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>ruby</category>
      <category>rails</category>
    </item>
    <item>
      <title>Book Review: It Doesn't Have To Be Crazy At Work</title>
      <dc:creator>James</dc:creator>
      <pubDate>Sat, 09 Mar 2019 23:58:15 +0000</pubDate>
      <link>https://dev.to/jsrn/book-review-it-doesnt-have-to-be-crazy-at-work-59p0</link>
      <guid>https://dev.to/jsrn/book-review-it-doesnt-have-to-be-crazy-at-work-59p0</guid>
      <description>&lt;p&gt;David Heinemeier Hansson and Jason Fried of &lt;a href="https://basecamp.com/"&gt;Basecamp&lt;/a&gt; and &lt;a href="https://m.signalvnoise.com/"&gt;Signal v. Noise&lt;/a&gt; lay out how they achieve calm at Basecamp and how other companies can make the choice to do the same.&lt;/p&gt;

&lt;p&gt;They point to the long hours, stolen weekends and barbed perks that run rampant in tech and say "it doesn't have to be this way!"&lt;/p&gt;

&lt;p&gt;Growth at all costs. Companies that demand the world of your time, and then steal it away with meetings and interruptions. Companies that coerce or bribe you to spend most of your waking hours with your nose to the grindstone (because after all, this company is &lt;em&gt;like a family&lt;/em&gt;, right?)&lt;/p&gt;

&lt;p&gt;It Doesn't Have To Be Crazy At Work discusses these problems and proposes a better way of doing things. DHH and Jason Fried discuss the solutions they've found to work at Basecamp, tackling issues from big picture ambitions to lower level project management, and from hiring to perks and payroll. They discuss the solutions that they have found work for them at Basecamp, but make no decrees as to how &lt;em&gt;your&lt;/em&gt; company ought to be run. That's for you to iterate on with your own team.&lt;/p&gt;

&lt;p&gt;Most of the stuff I have read about taming work feels very prescriptive. Do this. Do that. Try these processes. Add enough kanban boards and everything will click into place and you will finally be able to breathe. It Doesn't Have To Be Crazy At Work takes the opposite approach and encourages you to look at the things that you &lt;em&gt;don't&lt;/em&gt; need to do. Make time for the important things by stripping away the inessential.&lt;/p&gt;

&lt;p&gt;It's a pretty short read, and worth a look for anyone who feels like work is a little too hectic.&lt;/p&gt;

</description>
      <category>books</category>
      <category>career</category>
    </item>
    <item>
      <title>Lazy Loading Images For Your Digital Library</title>
      <dc:creator>James</dc:creator>
      <pubDate>Sat, 09 Mar 2019 13:21:50 +0000</pubDate>
      <link>https://dev.to/jsrn/lazy-loading-images-for-your-digital-library-3m9o</link>
      <guid>https://dev.to/jsrn/lazy-loading-images-for-your-digital-library-3m9o</guid>
      <description>&lt;p&gt;A quick morning (or afternoon, at this point) project to play with the magic of lazy loading. I wrote previously on &lt;a href="https://jsrn.net" rel="noopener noreferrer"&gt;my personal site&lt;/a&gt; about how I spent the beginning of the year &lt;a href="https://jsrn.net/personal/2019/02/05/the-month-of-deleting.html" rel="noopener noreferrer"&gt;getting rid of stuff&lt;/a&gt;. Like many people, I rather arrogantly identify as &lt;em&gt;a reader&lt;/em&gt;. Books sort of amass as trophies. The books I've read occupy a relatively small space, but the books I &lt;em&gt;plan&lt;/em&gt; to read threaten to tear the shelves straight off the wall.&lt;/p&gt;

&lt;p&gt;The Japanese word for this is "&lt;a href="https://en.wikipedia.org/wiki/Tsundoku" rel="noopener noreferrer"&gt;tsundoku&lt;/a&gt;."&lt;/p&gt;

&lt;p&gt;So, many books had to go. However, people tend to keep books around for two reasons:&lt;/p&gt;

&lt;p&gt;1) I might read it again.&lt;br&gt;
2) &lt;em&gt;I like having it there.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The first point is debatable. The second, harder to argue with. I wanted to reclaim some space while ensuring that I wouldn't forget the books that I've read and enjoyed (or not) over the years.&lt;/p&gt;

&lt;p&gt;And, as said, I wanted to play with lazy image loading.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://jsrn.net/library/" rel="noopener noreferrer"&gt;https://jsrn.net/library/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fkd0tq08fczykyz5jgvab.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fkd0tq08fczykyz5jgvab.PNG" alt="library preview"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>javascript</category>
      <category>lazyloading</category>
    </item>
    <item>
      <title>I'm James, and I don't want to talk about myself.</title>
      <dc:creator>James</dc:creator>
      <pubDate>Thu, 07 Mar 2019 23:26:23 +0000</pubDate>
      <link>https://dev.to/jsrn/im-james-and-i-dont-want-to-talk-about-myself-3g96</link>
      <guid>https://dev.to/jsrn/im-james-and-i-dont-want-to-talk-about-myself-3g96</guid>
      <description>&lt;p&gt;I tried writing about myself and the things I want to see, but I couldn't really find anything I was comfortable with. I don't think I'm really the person to teach others how to be a good ally. I don't know what I'm doing.&lt;/p&gt;

&lt;p&gt;My only advice is to amplify people different than yourself. If there's something you want to say and someone else has already said it, don't speak over them or repeat it just so it can be a tiny picture of &lt;em&gt;your&lt;/em&gt; face next to the words. Use your platform to amplify them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Jessica Rose&lt;/strong&gt; [&lt;a href="https://jessica.tech"&gt;Website&lt;/a&gt; ⌨ &lt;a href="https://twitter.com/jesslynnrose"&gt;Twitter&lt;/a&gt;]&lt;br&gt;
One of the most inspiring people I follow. Jessica always seems to have time to help people and organise within the community.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sandi Metz&lt;/strong&gt; [&lt;a href="https://sandimetz.com"&gt;Website&lt;/a&gt; ⌨ &lt;a href="https://twitter.com/sandimetz"&gt;Twitter&lt;/a&gt;]&lt;br&gt;
Almost everything I managed to absorb about OOP came from Sandi Metz. Her books belong on every shelf.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Caroline Ada Ehmke&lt;/strong&gt; [&lt;a href="https://where.coraline.codes/"&gt;Website&lt;/a&gt; ⌨ &lt;a href="https://twitter.com/CoralineAda"&gt;Twitter&lt;/a&gt;]&lt;br&gt;
Created the contributor covenant. Fights seemingly fearless and tirelessly for decency in tech.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ali Spittel&lt;/strong&gt; [&lt;a href="https://www.alispit.tel/#/"&gt;Website&lt;/a&gt; ⌨ &lt;a href="https://twitter.com/ASpittel"&gt;Twitter&lt;/a&gt;]&lt;br&gt;
A prolific writer and helper. Seeing her get a role at DEV.to after being so involved in the community was awesome.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Emma Wedekind&lt;/strong&gt; [&lt;a href="https://emmawedekind.com/"&gt;Website&lt;/a&gt; ⌨ &lt;a href="https://twitter.com/EmmaWedekind"&gt;Twitter&lt;/a&gt;]&lt;br&gt;
Another super prolific DEV.to writer. It's difficult to visit this site without benefiting from something she wrote.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Amy (Sailor Mercury)&lt;/strong&gt; [&lt;a href="https://shop.bubblesort.io/"&gt;Website&lt;/a&gt; ⌨ &lt;a href="https://twitter.com/sailorhg"&gt;Twitter&lt;/a&gt;]&lt;br&gt;
A programmer who creates zines explaining tech concepts, clothes, and more.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Liz Fong Jones&lt;/strong&gt; [&lt;a href="https://www.lizthegrey.com/"&gt;Website&lt;/a&gt; ⌨ &lt;a href="https://twitter.com/lizthegrey"&gt;Twitter&lt;/a&gt;]&lt;br&gt;
Another tireless campaigner for decency in tech. Has been most recently helping me by live-tweeting conference talks in awesome detail.&lt;/p&gt;

&lt;p&gt;Happy International Women's Day.&lt;/p&gt;

</description>
      <category>wecoded</category>
    </item>
    <item>
      <title>What’s Tripping Up Uglifier?</title>
      <dc:creator>James</dc:creator>
      <pubDate>Wed, 06 Mar 2019 00:00:00 +0000</pubDate>
      <link>https://dev.to/jsrn/whats-tripping-up-uglifier-3j94</link>
      <guid>https://dev.to/jsrn/whats-tripping-up-uglifier-3j94</guid>
      <description>&lt;p&gt;In production mode, Rails 4 uses the &lt;code&gt;uglifier&lt;/code&gt; gem to compress your JavaScript code into something nice and small to send over the wire. However, when you’ve got a syntax error, it can fail rather… ungracefully.&lt;/p&gt;

&lt;p&gt;You get a big stack trace that tells you that you’ve got a syntax error. It even helpfully tells you what the error was! Unexpected punctuation. There’s a comma, somewhere. Where? Who knows. It doesn’t tell you.&lt;/p&gt;

&lt;p&gt;If you have a large project, or have multiple people making large changes, it can be a little time consuming checking the diffs of recent commits to figure out where the error was introduced. Here is how you can use the rails console to at least find the offending file:&lt;/p&gt;

&lt;p&gt;Since the uglifier doesn’t run in development, let’s drop into the rails console in production mode:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RAILS_ENV=production rails c
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can use the following snippet of code to find our errors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Take each javascript file...&lt;/span&gt;
&lt;span class="no"&gt;Dir&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"app/assets/javascripts/**/*.js"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;file_name&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="k"&gt;begin&lt;/span&gt;
    &lt;span class="c1"&gt;# ... run it through the uglifier on its own...&lt;/span&gt;
    &lt;span class="nb"&gt;print&lt;/span&gt; &lt;span class="s2"&gt;"."&lt;/span&gt;
    &lt;span class="no"&gt;Uglifier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_name&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;StandardError&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;
    &lt;span class="c1"&gt;# ... and tell us when there's a problem!&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;Error compiling &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;file_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This saved me a little time recently, so I hope it will be handy to someone else.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>ruby</category>
      <category>rails</category>
    </item>
    <item>
      <title>Hand-holding Simulator</title>
      <dc:creator>James</dc:creator>
      <pubDate>Mon, 04 Mar 2019 13:50:51 +0000</pubDate>
      <link>https://dev.to/jsrn/hand-holding-simulator-4jei</link>
      <guid>https://dev.to/jsrn/hand-holding-simulator-4jei</guid>
      <description>&lt;p&gt;For anyone who needs it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://handholding-simulator.glitch.me/"&gt;https://handholding-simulator.glitch.me/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wdnfnMtR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/i4aoyhr5xw8w48e433sw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wdnfnMtR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/i4aoyhr5xw8w48e433sw.png" alt="on the cusp of holding hands"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>showdev</category>
    </item>
    <item>
      <title>It’s Time For Link Pages</title>
      <dc:creator>James</dc:creator>
      <pubDate>Wed, 27 Feb 2019 00:00:00 +0000</pubDate>
      <link>https://dev.to/jsrn/its-time-for-link-pages-2a81</link>
      <guid>https://dev.to/jsrn/its-time-for-link-pages-2a81</guid>
      <description>&lt;p&gt;There are a few complaints that are often made about the internet by those of us who spend too much time on it.&lt;/p&gt;

&lt;h1&gt;
  
  
  1) It Sucks Now
&lt;/h1&gt;

&lt;p&gt;The first is that the internet isn’t fun any more. There’s no exploration. Everything is centralised in a few places. Everybody is trying to build a brand. Nobody does anything just for the fun of it. You go on Twitter, get mad, and log off. There’s nowhere else to go.&lt;/p&gt;

&lt;h1&gt;
  
  
  2) The Whole Thing Is Owned By Like Three People
&lt;/h1&gt;

&lt;p&gt;The second complaint, and it’s very much related, is that the majority of the content that &lt;em&gt;we&lt;/em&gt; produce is aggregated in a few places to the benefit of companies. Twitter. Facebook. Yahoo Answers.&lt;/p&gt;

&lt;p&gt;I was reading an AskReddit thread a while ago. “What sites do you use when you aren’t on reddit?” I didn’t know. Everything is on one place, and it’s filtered through algorithms, trends, bots and social manipulation. We generate content, but we don’t give it directly to each other. We give it to a third party who flavours it and squeezes it into our waiting mouths like a sort of digital nutrient paste.&lt;/p&gt;

&lt;p&gt;The solution &lt;del&gt;RSS, RSS is the solution&lt;/del&gt; has been staring us in the face. &lt;del&gt;It’s RSS.&lt;/del&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Link_page"&gt;Link pages&lt;/a&gt;. Remember link pages?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“A link page is a type of web page found on some websites. The page contains a list of links the web page owner, a person or organization, finds notable to mention. Often this concerns an enumeration of partner organizations, clients, friends or related projects.” - &lt;em&gt;Wikipedia, the only good counter-example to my rant.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;People still have personal websites. A lot of us techies still have personal websites. But it’s an exercise in brand building. Look how clever I am. Hire me. Be my friend.&lt;/p&gt;

&lt;p&gt;We need to bring link pages back. In a big way.&lt;/p&gt;

&lt;p&gt;Advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Make friends. Become popular.&lt;/li&gt;
&lt;li&gt;Cool graphics.&lt;/li&gt;
&lt;li&gt;Won’t disappear when Jack Dorsey dismantles the Twitter servers to salvage parts for Mark Zuckerberg’s future body.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Disadvantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Literally none.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I will put my money (just kidding, I use GitHub pages so I don’t pay squat) where my mouth is here and say that if you run a tech site, don’t represent a company, and send me a small (ideally 88 x 31, as per the &lt;a href="https://en.wikipedia.org/wiki/Web_badge"&gt;web badge guidelines&lt;/a&gt;) image, I will include it on a special page on my website that gets no traffic.&lt;/p&gt;

&lt;p&gt;My dream is that one day our sites will once again be connected by an intricate network of links. A web. A World Wide Web.&lt;/p&gt;

&lt;h1&gt;
  
  
  Answers To Anticipated Comments
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;James, the web badges you mention are generally used for web standards, not linking to other sites!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Yeah, I know. Aren’t they cool though?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Are you trying to be funny?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Depends whether it worked or not.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This is a great idea. Can I link to your site?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sure. Here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ucr92Eq1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://jsrn.net/assets/images/badge.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ucr92Eq1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://jsrn.net/assets/images/badge.png" alt="my badge" width="88" height="31"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>miscellaneous</category>
      <category>nonsense</category>
    </item>
    <item>
      <title>Book Review: Refactoring UI</title>
      <dc:creator>James</dc:creator>
      <pubDate>Mon, 25 Feb 2019 00:00:00 +0000</pubDate>
      <link>https://dev.to/jsrn/book-review-refactoring-ui-52gh</link>
      <guid>https://dev.to/jsrn/book-review-refactoring-ui-52gh</guid>
      <description>&lt;p&gt;I recently bought myself a copy of &lt;a href="https://refactoringui.com/book/"&gt;Refactoring UI&lt;/a&gt; by &lt;a href="https://twitter.com/adamwathan"&gt;Adam Wathan&lt;/a&gt; and &lt;a href="https://twitter.com/steveschoger"&gt;Steve Schoger&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I opted for the much cheaper ($79 USD for a book and three videos) package, foregoing the &lt;em&gt;large&lt;/em&gt; amount of extras I could have gotten for another $70 USD: icons, colour palettes, inspiration gallery and a rather comprehensive sounding font showcase.&lt;/p&gt;

&lt;p&gt;While I can’t say for sure, not having bought them, my guess is that they would easily provide more than the extra $70 of value to any designer or aspiring designer.&lt;/p&gt;

&lt;p&gt;So, on to the book and videos, from which I learned many things:&lt;/p&gt;

&lt;h1&gt;
  
  
  The Book
&lt;/h1&gt;

&lt;h2&gt;
  
  
  1) Design From Above
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;How to focus on what the product needs to do before worrying about the layout.&lt;/li&gt;
&lt;li&gt;How to prototype in low fidelity.&lt;/li&gt;
&lt;li&gt;How to prioritise designing the core features without getting bogged down in hypothetical extensions.&lt;/li&gt;
&lt;li&gt;How to figure out who you’re designing for.&lt;/li&gt;
&lt;li&gt;How to design systems to constrain your choices.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2) Design With Hierarchy
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;How to use font sizes and colours to convey hierarchy.&lt;/li&gt;
&lt;li&gt;How to separate visual hierarchy from document hierarchy.&lt;/li&gt;
&lt;li&gt;How to balance semantic importance with position in the hierarchy.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3) Layout
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;How to use white space effectively (and how not to).&lt;/li&gt;
&lt;li&gt;How to build good space relationships.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4) Text
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;How to establish good font size relationships.&lt;/li&gt;
&lt;li&gt;How to choose and pair good fonts for different parts of the interface.&lt;/li&gt;
&lt;li&gt;How to design text for prose.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5) Colour
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;How to choose a good colour palette.&lt;/li&gt;
&lt;li&gt;How to define your colours in code.&lt;/li&gt;
&lt;li&gt;How to pair colours and make effective use of contrast.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  6) Depth
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;How to use shadows to convey a sense of “realness” in your interface.&lt;/li&gt;
&lt;li&gt;How to position and overlap elements effectively.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  7) Images
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;How to choose good images.&lt;/li&gt;
&lt;li&gt;How to pair text and images when contrast becomes a problem.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  8) Finishing Touches
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;How to use &lt;em&gt;a lot&lt;/em&gt; of simple tips and tricks to make your product look more polished. These aren’t huge wins for accessibility or performance, but things you can do to elevate your design with minimal investment.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  The Videos
&lt;/h1&gt;

&lt;p&gt;Both packages come with three screen-cast style videos in which they improve the design of a realistic interface, explaining their process as they work. Being able to watch the interface transform as they talk you through it, and then be presented with the before and after makes a powerful impression as to the value of the concepts they discuss in the book.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;This might seem like I’m simply regurgitating the &lt;a href="https://refactoringui.com/book/table-of-contents/"&gt;table of contents&lt;/a&gt; and I suppose I am, but my aim is to convey the value I gained from this book in my own words as a developer who wants to be good at design (and who isn’t making any money from singing the book’s praises).&lt;/p&gt;

&lt;p&gt;The examples are compellingly presented with before and after states, as well as having the important information such as colour and font choices annotated. Weighing in at a relatively lean 218 pages, Refactoring UI doesn’t delve too deeply into colour theory and the psychology of design, but provides countless rules of thumb and visual examples, showing even someone with the most rudimentary design skills (me) how to elevate their work to the next level.&lt;/p&gt;

&lt;p&gt;To get a further sense of the value the book provides, I suggest you check out &lt;a href="https://twitter.com/i/moments/994601867987619840"&gt;this series of hot tips from author Steve Schoger&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ui</category>
      <category>design</category>
      <category>books</category>
    </item>
  </channel>
</rss>
