<?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>Forem: Fran C.</title>
    <description>The latest articles on Forem by Fran C. (@nflamel).</description>
    <link>https://forem.com/nflamel</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%2F42690%2F7923d63b-b00e-431a-89bf-89a5e62e8437.jpg</url>
      <title>Forem: Fran C.</title>
      <link>https://forem.com/nflamel</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/nflamel"/>
    <language>en</language>
    <item>
      <title>Smart textwidth on Vim when writing comments</title>
      <dc:creator>Fran C.</dc:creator>
      <pubDate>Sun, 13 Dec 2020 21:30:13 +0000</pubDate>
      <link>https://forem.com/nflamel/smart-textwidth-on-vim-to-80-characters-on-comments-56id</link>
      <guid>https://forem.com/nflamel/smart-textwidth-on-vim-to-80-characters-on-comments-56id</guid>
      <description>&lt;p&gt;I was checking my &lt;code&gt;init.vim&lt;/code&gt; today trying to find how to improve it a bit.&lt;/p&gt;

&lt;p&gt;I found this case that could be interesting to share... so there it goes.&lt;/p&gt;

&lt;p&gt;I write a lot of documentation. One thing I always try to do is to keep the comments I write well aligned and easy to read. That's why I keep them at a length of 80 characters, I find that to be easier to read than long lines.&lt;/p&gt;

&lt;p&gt;You can use the &lt;code&gt;textwidth&lt;/code&gt; configuration in vim to do that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="nb"&gt;textwidth&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the text you write gets to a width of 80 characters vim will split it to the next line.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--R_AyaLQG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/wam03sbvk61ub7i260ga.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--R_AyaLQG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/wam03sbvk61ub7i260ga.gif" alt="vim auto splitting text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a very well known fact about vim, but you can read more about it if you're interested with &lt;code&gt;:help textwidth&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                        *'textwidth'* *'tw'*
'textwidth' 'tw'    number  (default 0)
            local to buffer
    Maximum width of text that is being inserted.  A longer line will be
    broken after white space to get this width.  A zero value disables
    this.
    'textwidth' is set to 0 when the 'paste' option is set and restored
    when 'paste' is reset.
    When 'textwidth' is zero, 'wrapmargin' may be used.  See also
    'formatoptions' and |ins-textwidth|.
    When 'formatexpr' is set it will be used to break the line.

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

&lt;/div&gt;



&lt;p&gt;The thing is that I don't want vim to do the same on the code I write. Mainly because it will end up splitting the code on a different place than the one I would want it to.&lt;/p&gt;

&lt;p&gt;I needed a way to &lt;code&gt;set textwidth=80&lt;/code&gt; when editing comments and then &lt;code&gt;set textwidth=0&lt;/code&gt; when not editing comments anymore.&lt;/p&gt;

&lt;p&gt;Enter &lt;a href="https://github.com/inkarkat/vim-OnSyntaxChange"&gt;OnSyntaxChange&lt;/a&gt;. This plugin allows you to define vim autocommands that execute when the syntax of the current file changes, in our case, when we're editing comments.&lt;/p&gt;

&lt;p&gt;I use &lt;a href="https://github.com/junegunn/vim-plug"&gt;vim-plug&lt;/a&gt; so I install it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;Plug &lt;span class="s1"&gt;'inkarkat/vim-OnSyntaxChange'&lt;/span&gt;
&lt;span class="c"&gt;" This is a dependency library from the same author that includes&lt;/span&gt;
&lt;span class="c"&gt;" some autoload functions that he uses on the plugins he writes.&lt;/span&gt;
Plug &lt;span class="s1"&gt;'inkarkat/vim-ingo-library'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="c"&gt;" Add a new autocommand that will activate when the cursor is on a Comment and&lt;/span&gt;
&lt;span class="c"&gt;" it either enters or leaves insert mode.&lt;/span&gt;
&lt;span class="c"&gt;" 1. The name: `Comment` means the autocmd will be called&lt;/span&gt;
&lt;span class="c"&gt;" `SyntaxCommentEnter{MODE}`&lt;/span&gt;
&lt;span class="c"&gt;" 2. A regex to max the syntax, on our case any syntax similar to `Comment`&lt;/span&gt;
&lt;span class="c"&gt;" will match to us.&lt;/span&gt;
&lt;span class="c"&gt;" 3. Whether we want to generate it to all buffers or only a particular one,&lt;/span&gt;
&lt;span class="c"&gt;" we're ok with only the current buffer.&lt;/span&gt;
&lt;span class="c"&gt;" 4. To which mode we want to link the autocommand. We're only interested in&lt;/span&gt;
&lt;span class="c"&gt;" the insert mode&lt;/span&gt;
&lt;span class="k"&gt;call&lt;/span&gt; OnSyntaxChange#Install&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Comment'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'^Comment$'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'i'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

augroup auto_wrap_comments
  &lt;span class="c"&gt;" Set textwidth to 80 when editing&lt;/span&gt;
  autocmd &lt;span class="nb"&gt;User&lt;/span&gt; SyntaxCommentEnterI &lt;span class="k"&gt;setlocal&lt;/span&gt; &lt;span class="nb"&gt;textwidth&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;
  &lt;span class="c"&gt;" Remove it again when leaving insert mode&lt;/span&gt;
  autocmd &lt;span class="nb"&gt;User&lt;/span&gt; SyntaxCommentLeaveI &lt;span class="k"&gt;setlocal&lt;/span&gt; &lt;span class="nb"&gt;tw&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
augroup END
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And with that code on our &lt;code&gt;init.vim&lt;/code&gt; we now have that the split behaves like this :)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uo_ZXLjP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ir7ufq4g0xz9h22aq237.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uo_ZXLjP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ir7ufq4g0xz9h22aq237.gif" alt="Smart text width"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vim</category>
    </item>
    <item>
      <title>My small hook and my flow with git</title>
      <dc:creator>Fran C.</dc:creator>
      <pubDate>Sat, 14 Nov 2020 18:17:13 +0000</pubDate>
      <link>https://forem.com/nflamel/my-flow-with-git-52c2</link>
      <guid>https://forem.com/nflamel/my-flow-with-git-52c2</guid>
      <description>&lt;p&gt;I've just made this small git hook &lt;a href="https://github.com/franciscoj/dot-files/blob/0825d35076ce4550db20a12ea54d73bf3d6cea63/git/hooks/commit-msg" rel="noopener noreferrer"&gt;https://github.com/franciscoj/dot-files/blob/0825d35076ce4550db20a12ea54d73bf3d6cea63/git/hooks/commit-msg&lt;/a&gt; and I'm super happy because I've needed it for a long time!&lt;/p&gt;

&lt;p&gt;It analyses the commit msg and adds a &lt;code&gt;+&lt;/code&gt; sign at the beginning of the first line if the commit has more than 1 line. That way I can recognise commits with extended information.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4um9hm57704pd4qtaojy.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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4um9hm57704pd4qtaojy.png" alt="git log with this change"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When I'm coding serious stuff (like at work) I make very little and very atomic commits incrementally and I always try to keep things "green" and stable. When I say very little I really mean it. Sometimes those are things like "extract a variable" or "move this to the constructor" or "add an unused parameter".&lt;/p&gt;

&lt;p&gt;I don't always to that as I make the change. Instead I play around a bit until I get where I want to and then I just commit small hunks little by little.&lt;/p&gt;

&lt;p&gt;As I work on the task I extract things that are independent and can be rolled out on their own. Maybe a refactor that makes the new feature possible or a set of classes that aren't used yet but will be used by the new code I'm writing.&lt;/p&gt;

&lt;p&gt;This way I also make sure that, on long projects, I keep sharing my code with my team as much as possible and gathering their continuous feedback.&lt;/p&gt;

&lt;p&gt;I do that with many interactive rebases: editing, sqashing, splitting and reordering commits. I can't always do that, of course, but I try to code and commit taking that into account so that it is possible.&lt;/p&gt;

&lt;p&gt;I normally extract stuff from my PR that can be independently rolled out and that can ease having a big feature in production without needing big last day deploys.&lt;/p&gt;

&lt;p&gt;This way I start using the new code and capturing metrics about it before the new feature is even active for the final users, minimising the risk of performance or functional regressions.&lt;/p&gt;

&lt;p&gt;PS: This started as a tweet explaining my silly hook and it went out of hand xD&lt;/p&gt;

&lt;p&gt;Edit 2020 - 11 - 24: Updated the link to the hook to the latest version with some fixes I've done in the last weeks :)&lt;/p&gt;

</description>
      <category>git</category>
      <category>productivity</category>
    </item>
    <item>
      <title>My Ergodox EZ coding layout</title>
      <dc:creator>Fran C.</dc:creator>
      <pubDate>Wed, 29 Jul 2020 20:36:27 +0000</pubDate>
      <link>https://forem.com/nflamel/my-ergodox-ez-coding-layout-7bl</link>
      <guid>https://forem.com/nflamel/my-ergodox-ez-coding-layout-7bl</guid>
      <description>&lt;p&gt;2 or 3 years ago I bought an Ergodox Ez &lt;a href="https://ergodox-ez.com/" rel="noopener noreferrer"&gt;https://ergodox-ez.com/&lt;/a&gt; I like mechanical keyboards a lot but I fell in love with this on the moment I saw it.&lt;/p&gt;

&lt;p&gt;I own one of the old versions. No key backlights or any other of those fancy coloring stuff. It performs well, the cherry brown switches are great for my use and being able to position the keyboard halves the way I want has improved my posture when working a lot.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyyuyopbd360hteyt5hg5.jpg" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyyuyopbd360hteyt5hg5.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One of the things that made it a game-changer for me was the possibility to experiment with custom layouts and, lately, the support for macros.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 4 layers
&lt;/h2&gt;

&lt;p&gt;The layout is built around 4 different layers&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;0&lt;/code&gt; or Home layer&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;1&lt;/code&gt; or extended layer&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;2&lt;/code&gt; or media layer&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;3&lt;/code&gt; or numeric layer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some of the ideas on it (like reducing the use of pinkies) comes from here &lt;a href="https://implementsblog.com/2016/10/16/my-ergodox-ezs-custom-layout/" rel="noopener noreferrer"&gt;https://implementsblog.com/2016/10/16/my-ergodox-ezs-custom-layout/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Layer 0 (Home)
&lt;/h2&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fd4e91o1q85n36ll19bd1.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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fd4e91o1q85n36ll19bd1.png" alt="Home layer"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the default layer. It is built as a &lt;code&gt;QWERTY&lt;/code&gt; keyboard but in order to minimize the use of the pinky finger it has dual function keys on the home row (those are the keys on light blue for &lt;code&gt;a&lt;/code&gt;, &lt;code&gt;s&lt;/code&gt;, &lt;code&gt;d&lt;/code&gt;, &lt;code&gt;f&lt;/code&gt;, &lt;code&gt;j&lt;/code&gt;, &lt;code&gt;k&lt;/code&gt;, &lt;code&gt;l&lt;/code&gt; and &lt;code&gt;;&lt;/code&gt; that way &lt;code&gt;SHIFT&lt;/code&gt;, &lt;code&gt;ALT&lt;/code&gt;, &lt;code&gt;CTRL&lt;/code&gt; and &lt;code&gt;SUPER&lt;/code&gt;/&lt;code&gt;CMD&lt;/code&gt; are mapped on parallel on each hand and pinkies use is reduced.&lt;/p&gt;

&lt;p&gt;This is weird at the beginning but once you get used to it it is so much better than the regular keyboard distribution that I would never want to get back to it.&lt;/p&gt;

&lt;p&gt;The next thing that is worth mentioning here is the set of macros I have. Those are the purple keys at the top and at the bottom of the layout.&lt;/p&gt;

&lt;p&gt;The ones on the left hand are for Vim and going from top left to bottom right they:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open git status&lt;/li&gt;
&lt;li&gt;Open horizontal split&lt;/li&gt;
&lt;li&gt;Open vertical split&lt;/li&gt;
&lt;li&gt;Fuzzy file finder&lt;/li&gt;
&lt;li&gt;Grep on project&lt;/li&gt;
&lt;li&gt;Close current buffer&lt;/li&gt;
&lt;li&gt;Repeat last test (with &lt;a href="https://github.com/vim-test/vim-test" rel="noopener noreferrer"&gt;https://github.com/vim-test/vim-test&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Run the tests on this file&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the right hand I had tmux macros and from top left to bottom right:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rename tab&lt;/li&gt;
&lt;li&gt;Open new tab&lt;/li&gt;
&lt;li&gt;Open vertical split&lt;/li&gt;
&lt;li&gt;Open horizontal split&lt;/li&gt;
&lt;li&gt;Change to previous tab&lt;/li&gt;
&lt;li&gt;Change to next tab&lt;/li&gt;
&lt;li&gt;Switch to next split&lt;/li&gt;
&lt;li&gt;Zoom split&lt;/li&gt;
&lt;li&gt;Enter search mode&lt;/li&gt;
&lt;li&gt;Close current split/window&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I know, you're wondering "do you really use all that?" well, after some time yes. I use it all. Besides, so far I've not lost my muscular memory so I can still use a regular keyboard.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layer 1 (Extended)
&lt;/h2&gt;

&lt;p&gt;The most important thing about this layer is that it has some programming symbols like &lt;code&gt;[&lt;/code&gt; or &lt;code&gt;]&lt;/code&gt; and that it has the numbers (and all the symbols they have on &lt;code&gt;SHIFT&lt;/code&gt;) but in the home row instead of the top row.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fgus0gek8hsyzoo85wezl.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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fgus0gek8hsyzoo85wezl.png" alt="Extended layer"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm currently studying how can I change some of the other coding symbols to a more comfortable position, like the row on top of the home one on the right hand. But I have still not decided.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layer 2 (Media)
&lt;/h2&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F9nchdsrudbcjle6r97tr.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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F9nchdsrudbcjle6r97tr.png" alt="Media layer"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This one is easy. It has the arrows on the home row and on the same position as Vim &lt;code&gt;hjkl&lt;/code&gt; + the media keys on the row on top of the home one + mouse movement on the left hand.&lt;/p&gt;

&lt;p&gt;I actually don't use that mouse a lot, but it helps having it around.&lt;/p&gt;

&lt;p&gt;It has all the &lt;code&gt;F&lt;/code&gt; keys on the position where the numbers would be on a regular keyboard... I don't use them that much but I still want to have them around in some cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layer 3 (Numeric)
&lt;/h2&gt;

&lt;p&gt;This layer is pretty simple. It works as a numeric pad. I don't use it that much but it gets useful when you need to do things with excels for example.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fok6snnjcaj84p6rhoi4o.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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fok6snnjcaj84p6rhoi4o.png" alt="Numeric layer"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  WIP
&lt;/h2&gt;

&lt;p&gt;This is still unfinished. I change it from time to time and try to time and regularly go through it to try to find ways to improve. Mainly to make things more comfortable or to reduce typos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Can I use it?
&lt;/h2&gt;

&lt;p&gt;I wouldn't recommend it if you're starting with an ergodox keyboard. That's already a bit hard on its own. But if you want to give it a spin you can find it here &lt;a href="https://configure.ergodox-ez.com/ergodox-ez/layouts/KrKNl/latest/0" rel="noopener noreferrer"&gt;https://configure.ergodox-ez.com/ergodox-ez/layouts/KrKNl/latest/0&lt;/a&gt;&lt;/p&gt;

</description>
      <category>keyboards</category>
      <category>productivity</category>
    </item>
    <item>
      <title>A trick with the Ruby documentation</title>
      <dc:creator>Fran C.</dc:creator>
      <pubDate>Tue, 28 Jul 2020 06:28:47 +0000</pubDate>
      <link>https://forem.com/factorial/a-trick-with-the-ruby-documentation-58m7</link>
      <guid>https://forem.com/factorial/a-trick-with-the-ruby-documentation-58m7</guid>
      <description>&lt;p&gt;I've never been able to remember the arguments for &lt;code&gt;Array#reduce&lt;/code&gt;. Every time I think I've managed to do it I just get it wrong.&lt;/p&gt;

&lt;p&gt;Luckily for me, Ruby has very good documentation on its standard library and, what's even better, it ships with a CLI to explore it so I don't even need to Google it 😬&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ri "Array#reduce"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;= Array#reduce

(from ruby core)
=== Implementation from Enumerable
------------------------------------------------------------------------
  enum.reduce(initial, sym) -&amp;gt; obj
  enum.reduce(sym)          -&amp;gt; obj
  enum.reduce(initial) { |memo, obj| block }  -&amp;gt; obj
  enum.reduce          { |memo, obj| block }  -&amp;gt; obj

------------------------------------------------------------------------

Combines all elements of enum by applying a binary operation,
specified by a block or a symbol that names a method or operator.

The inject and reduce methods are aliases. There
is no performance benefit to either.

If you specify a block, then for each element in enum the block
is passed an accumulator value (memo) and the element. If you
specify a symbol instead, then each element in the collection will be
passed to the named method of memo. In either case, the result
becomes the new value for memo. At the end of the iteration, the
final value of memo is the return value for the method.

If you do not explicitly specify an initial value for
memo, then the first element of collection is used as the
initial value of memo.

  # Sum some numbers
  (5..10).reduce(:+)                             #=&amp;gt; 45
  # Same using a block and inject
  (5..10).inject { |sum, n| sum + n }            #=&amp;gt; 45
  # Multiply some numbers
  (5..10).reduce(1, :*)                          #=&amp;gt; 151200
  # Same using a block
  (5..10).inject(1) { |product, n| product * n } #=&amp;gt; 151200
  # find the longest word
  longest = %w{ cat sheep bear }.inject do |memo, word|
     memo.length &amp;gt; word.length ? memo : word
  end
  longest                                        #=&amp;gt; "sheep"

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

&lt;/div&gt;



&lt;p&gt;It has a very good interactive mode as well (&lt;code&gt;ri -i&lt;/code&gt;) In which you can search whatever you want :)&lt;/p&gt;

&lt;p&gt;Oh, and if you use Vim you can access it by using &lt;code&gt;K&lt;/code&gt; over any word. Check this out:&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3y3gxynkolbmrxwwonjd.gif" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3y3gxynkolbmrxwwonjd.gif" alt="K opens vim docs in vim"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ruby</category>
    </item>
    <item>
      <title>TIL: How my complicated alias works</title>
      <dc:creator>Fran C.</dc:creator>
      <pubDate>Sun, 12 Jul 2020 08:05:12 +0000</pubDate>
      <link>https://forem.com/nflamel/til-how-my-complicated-alias-works-1ka1</link>
      <guid>https://forem.com/nflamel/til-how-my-complicated-alias-works-1ka1</guid>
      <description>&lt;p&gt;This post comes from this comment: &lt;a href="https://dev.to/nflamel/comment/11o72"&gt;https://dev.to/nflamel/comment/11o72&lt;/a&gt;. You can read the whole thread here:&lt;/p&gt;


&lt;div class="liquid-comment"&gt;
    &lt;div class="details"&gt;
      &lt;a href="/nflamel"&gt;
        &lt;img class="profile-pic" src="https://res.cloudinary.com/practicaldev/image/fetch/s--jNLvXXmU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/practicaldev/image/fetch/s--IzZ5PoC6--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_50%2Cq_auto%2Cw_50/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/42690/7923d63b-b00e-431a-89bf-89a5e62e8437.jpg" alt="nflamel profile image"&gt;
      &lt;/a&gt;
      &lt;a href="/nflamel"&gt;
        &lt;span class="comment-username"&gt;Fran C.&lt;/span&gt;
      &lt;/a&gt;
      &lt;span class="color-base-30 px-2"&gt;•&lt;/span&gt;

&lt;a href="https://dev.to/nflamel/comment/11m4e" class="comment-date crayons-link crayons-link--secondary fs-s"&gt;
  &lt;time&gt;
    Jul 10 '20
  &lt;/time&gt;

&lt;/a&gt;

    &lt;/div&gt;
    &lt;div class="body"&gt;
      &lt;p&gt;I think that my 2 favortites and the 2 I use more are, no doubt:&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="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;e&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'${(z)VISUAL:-${(z)EDITOR}}'&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;g&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'git'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




    &lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;I've had this alias on my dot-files for some time. I use it to open my editor of choice (neovim).&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="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;e&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'${(z)VISUAL:-${(z)EDITOR}}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I didn't know what it was exactly doing until recently. I've had it copy/pasted around my dot-files many times.&lt;/p&gt;

&lt;p&gt;EDIT: I mean... I know I always use &lt;code&gt;e&lt;/code&gt; to open nvim. What I didn't know was why was I using such a complex alias to do it.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR:
&lt;/h2&gt;

&lt;p&gt;It uses &lt;code&gt;$VISUAL&lt;/code&gt; or &lt;code&gt;$EDITOR&lt;/code&gt; and makes sure that it properly handles any extra parameter given to it. So something line &lt;code&gt;vim -a -b -c&lt;/code&gt; works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Detailed explanation
&lt;/h2&gt;

&lt;p&gt;Got it from here &lt;a href="https://github.com/sorin-ionescu/prezto/blob/f4ca9ebfc913453f98ba6912a8c42684fd742cc1/modules/utility/init.zsh#L55"&gt;https://github.com/sorin-ionescu/prezto/blob/f4ca9ebfc913453f98ba6912a8c42684fd742cc1/modules/utility/init.zsh#L55&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What it does If I'm not mistaken is to alias &lt;code&gt;e&lt;/code&gt; to either the value of &lt;code&gt;$VISUAL&lt;/code&gt; or &lt;code&gt;$EDITOR&lt;/code&gt;. But to only do that it would be enough with:&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="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;e&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'${VISUAL:-${EDITOR}}`
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's also this &lt;code&gt;(z)&lt;/code&gt; that I just learned on ZSH is an expansion flag. Looking into ZSH manual it says:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;z

    Split the result of the expansion into words using shell parsing to find
    the words, i.e. taking into account any quoting in the value. Comments are
    not treated specially but as ordinary strings, similar to interactive
    shells with the INTERACTIVE_COMMENTS option unset (however, see the Z flag
    below for related options)

    Note that this is done very late, even later than the ‘(s)’ flag. So to
    access single words in the result use nested expansions as in
    ‘${${(z)foo}[2]}’. Likewise, to remove the quotes in the resulting words
    use ‘${(Q)${(z)foo}}’.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;but I still didn't know what it means... so I tried to do:&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="nv"&gt;VISUAL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'nvim -v'&lt;/span&gt; &lt;span class="c"&gt;# This just writes the nvim version&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;e&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'${VISUAL:-${EDITOR}}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If I then I've tried&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ e
zsh: command not found: nvim -v
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That doesn't happen if I try with &lt;code&gt;(z)&lt;/code&gt; flag on the expansion &lt;code&gt;alias e='${(z)VISUAL:-${(z)EDITOR}}'&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Thanks to &lt;a href="https://dev.to/nocnica"&gt;https://dev.to/nocnica&lt;/a&gt; for asking the right question and for suggesting that I extracted the comment into this post.&lt;/p&gt;

</description>
      <category>zsh</category>
    </item>
    <item>
      <title>How i install Arch Linux on my dev machine</title>
      <dc:creator>Fran C.</dc:creator>
      <pubDate>Wed, 20 May 2020 20:48:36 +0000</pubDate>
      <link>https://forem.com/nflamel/how-i-install-arch-linux-on-my-dev-machine-4jjp</link>
      <guid>https://forem.com/nflamel/how-i-install-arch-linux-on-my-dev-machine-4jjp</guid>
      <description>&lt;p&gt;I use ArchLinux on my 2 dev machines. One is an old Alienware M17xR4 that somehow is still alive and that I can only use plugged in (or on battery for like 20 minutes) and a powerful desktop machine that I share with Windows for playing videogames.&lt;/p&gt;

&lt;p&gt;The reasons why I use Linux for development are basically because I enjoy it. I've never used Windows for development so I don't know if I would enjoy it and I've used Mac... and I just don't like it. I feel MacOS gets in my way all the time and doesn't always allow me to do what I want to do.&lt;/p&gt;

&lt;p&gt;The reason why I use Arch? ... I don't know and I honestly ask myself this question every time I need to reinstall the system. But whenever I try something else I end up coming back to my Arch setup. It is just customized the way I like it.&lt;/p&gt;

&lt;p&gt;Installing Arch isn't easy or straightforward, you normally need to know what you're doing and last time I tried it took me around 3 hours because I'm dummy and lazy and I still don't understand EFI or how to make Grub work with it (spoiler: I used refind).&lt;/p&gt;

&lt;p&gt;In order to avoid this pain again I've decided to write this down so that I don't need to go through the same again 🤷&lt;/p&gt;

&lt;p&gt;Most of it is just copied from the awesome Arch installation guide, with just a pinch of what I want and explaining the same steps just for myself (if you want to install Arch please go and use the installation guide instead of this!)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://wiki.archlinux.org/index.php/Installation_guide"&gt;https://wiki.archlinux.org/index.php/Installation_guide&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Bootstrap from the live USB
&lt;/h2&gt;

&lt;h2&gt;
  
  
  2. Get internet
&lt;/h2&gt;

&lt;p&gt;If wifi just works&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wifi-menu
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If not, make sure your Ethernet cable or mobile tethering is connected. Arch will enable DHCP for the Ethernet devices it finds them (that includes USB tethering) while it boots. You only need to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;systemctl restart dhcpcd@enps0swhatever
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;check you have ping to &lt;code&gt;ping archlinux.org&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Sync time
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;timedatectl set-ntp true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Partition
&lt;/h2&gt;

&lt;p&gt;Use cfdisk. Important, make sure &lt;code&gt;/var&lt;/code&gt; is not on the SSD. There's probably no reason for that on modern SSDs? I don't know, it just scares me.&lt;/p&gt;

&lt;h3&gt;
  
  
  Laptop
&lt;/h3&gt;

&lt;p&gt;I use these partitions. &lt;code&gt;/dev/sda&lt;/code&gt; is the normal HDD and &lt;code&gt;/dev/sdb&lt;/code&gt; is the 32GB SSD.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/dev/sda1, 1G, /boot/efi
/dev/sda2, 1G, /boot
/dev/sda3, 100G, /var
/dev/sda4, all, /home

/dev/sdb1, all, /
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Desktop partition schema
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/dev/sda&lt;/code&gt; is the Windows installation disk on SSD&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/dev/sdb&lt;/code&gt; is the Windows storage HDD&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/dev/sdc&lt;/code&gt; is the Linux SSD&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/dev/sdd&lt;/code&gt; is the Linux storage HDD&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;EFI exists already from the Windows partition, don't format it, just mount it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/dev/sda2, /boot/efi
/dev/sdc1, all,  /
/dev/sdd1, 300G, /var
/dev/sdd2, all, /media/store
/dev/sda4, exists, /media/windows
/dev/sdb2, exists, media/store_win
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. Bootstrap the system
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pacstrap /mnt base linux linux-firmware neovim vi zsh networkmanager sudo
genfstab -U /mnt &amp;gt;&amp;gt; /mnt/etc/fstab
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On desktop remember to add &lt;code&gt;linux-headers base-devel broadcom-wl-dkms&lt;/code&gt; to the list of pacstrap packages. Because I have a broadcom wireless card and otherwise I don't have wifi on my first boot (and it is a pain to configure it later!)&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Chroot
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;arch-chroot /mnt
ln -sf /usr/share/zoneinfo/Europe/Madrid /etc/localtime
hwclock --systohc
nvim /etc/locale.gen # uncomment en_US.UTF-8 and es_ES.UTF-8
locale-gen
echo "LANG=en_US.UTF-8" &amp;gt; /etc/locale.conf
echo "my-hostname" &amp;gt; /etc/hostname
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Setup hosts &lt;code&gt;nvim /etc/hosts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;127.0.0.1   localhost
::1     localhost
127.0.1.1   my-hostname
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;passwd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  7. Boot manager
&lt;/h2&gt;

&lt;p&gt;I tipically install grub, but last time I wasn't able to do it and ended up installing refind.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install grub
&lt;/h3&gt;

&lt;p&gt;This just worked on the laptop 🤷&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pacman -S grub efibootmgr
grub-install --target=x86_64-efi --bootloader-id=GRUB --efi-directory=/boot/efi
grub-mkconfig -o /boot/grub/grub.cfg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Or refind
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pacman -S refind
refind-install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Edit &lt;code&gt;/boot/refind_linux.conf&lt;/code&gt; and make sure it has a line that refers to the &lt;code&gt;/&lt;/code&gt; partition&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    "Boot using default options"   "root=PARTUUID=978e3e81-8048-4ae1-8a06-aa727458e8ff rw quiet splash"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;PARTUUID can be found with &lt;code&gt;blkid&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Sometimes I add this theme &lt;a href="https://github.com/bobafetthotmail/refind-theme-regular"&gt;https://github.com/bobafetthotmail/refind-theme-regular&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Restart!
&lt;/h2&gt;

&lt;p&gt;Exit from chroot&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;umount -R /mnt
reboot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  9. Connect wifi
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;systemctl enable NetworkManager
systemctl restart NetworkManager
nmcli device wifi rescan
nmcli device wifi list
nmcli device wifi connect SSID-Name password wireless-password
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  10. Create my new user
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;visudo # to enable sudo to members of wheel group
userad -m -G wheel -s /bin/zsh username
passwd username
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then exit and login with this new user&lt;/p&gt;

&lt;h2&gt;
  
  
  11. Bootstrap the new system
&lt;/h2&gt;

&lt;p&gt;If you're here and you're not me, ⚠️stop⚠️. This is how to install my own personal dot-files and you don't want them, believe me.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo pacman -S python python-pip python-neovim git base-devel
git clone https://github.com/franciscoj/dot-files ~/Documents/src/dot-files
cd ~/Documents/src/dot-files
./boostrap/linux.sh
sudo DIFFPROG="nvim -d" pacdiff
sudo pip install dotbot
dotbot -c install.conf.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Enable lightdm
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl enable lightdm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Done!
&lt;/h2&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;

</description>
      <category>linux</category>
      <category>archlinux</category>
    </item>
    <item>
      <title>Some reasons to avoid Hashes in Ruby and some alternatives to them.</title>
      <dc:creator>Fran C.</dc:creator>
      <pubDate>Mon, 16 Mar 2020 08:23:28 +0000</pubDate>
      <link>https://forem.com/factorial/some-reasons-to-avoid-hashes-in-ruby-and-some-alternatives-to-them-3j7n</link>
      <guid>https://forem.com/factorial/some-reasons-to-avoid-hashes-in-ruby-and-some-alternatives-to-them-3j7n</guid>
      <description>&lt;p&gt;So, hashes, uh?&lt;/p&gt;

&lt;h3&gt;
  
  
  What's good about them?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;They are easy to build&lt;/li&gt;
&lt;li&gt;They are cheap (short-term cheap at least)&lt;/li&gt;
&lt;li&gt;They help interfacing with shapeless data (like JSON) in an easy way.&lt;/li&gt;
&lt;li&gt;They are good to build simple/cheap key-value stores in memory.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What's not so good about them?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;They are shapeless (in a bad way, you never know what you expect from them)&lt;/li&gt;
&lt;li&gt;They are mutable (in a bad way as well, how do you know nobody else will mutate this or nobody has already mutated it?)&lt;/li&gt;
&lt;li&gt;They are dummy (unlike objects, they know nothing, they have no way to interface with except for &lt;code&gt;Enumerable&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;They are impossible to type (🤷‍♂️)&lt;/li&gt;
&lt;li&gt;They need a lot of defensive code with &lt;code&gt;nil&lt;/code&gt; checks. (even when they are getting better at this with things like &lt;code&gt;hash.dig(:key1, :key2)&lt;/code&gt; it is not enough and you always need extra checks here and there, which makes the code difficult to read and to change).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  So, what should we do with them?
&lt;/h3&gt;

&lt;p&gt;I propose that we all agree on a small set of guidelines to help us answer the question "Should I use a &lt;code&gt;Hash&lt;/code&gt; for this?". TL;DR&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Avoid using Hashes as input to methods. Try to have shaped inputs.&lt;/li&gt;
&lt;li&gt;Avoid using Hashes as return values. Try to have shaped return values.&lt;/li&gt;
&lt;li&gt;If you receive a Hash, isolate it. Build a layer to interface with instead of the &lt;code&gt;Hash&lt;/code&gt;.

&lt;ul&gt;
&lt;li&gt;Get the data directly if it is a small hash.&lt;/li&gt;
&lt;li&gt;Build objects if it has an heterogeneous structure.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  1. Avoid using hashes as input to methods.
&lt;/h4&gt;

&lt;p&gt;There's no easy way to know what's inside &lt;code&gt;params&lt;/code&gt; here..&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="no"&gt;MyInteractor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="ss"&gt;author: &lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;params: &lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead use 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="no"&gt;MyInteractor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="ss"&gt;author: &lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;value: &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;:value&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="ss"&gt;question_id: &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;:question_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You now have an explicit knowledge of the input for that interactor which is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;simpler to use (you don't need a Hash now, only values which can come from any object)&lt;/li&gt;
&lt;li&gt;Intention revealing&lt;/li&gt;
&lt;li&gt;Typable&lt;/li&gt;
&lt;li&gt;Easier to document&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Try to avoid substituting the &lt;code&gt;Hash&lt;/code&gt; with a &lt;code&gt;T::Struct&lt;/code&gt; or a plain &lt;code&gt;Struct&lt;/code&gt; if you don't use sorbet. You will be adding an extra layer and having very little in return. You avoid the hash, which is good, but you add an extra layer and win very little in return. That does not justify a new layer.&lt;/p&gt;

&lt;p&gt;Instead, type the parameters you're receiving individually with Sorbet. If you don't use sorbet, just avoid the struct and pass them individually.&lt;/p&gt;

&lt;p&gt;You might think:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;But I have A TON of parameters and a &lt;code&gt;Hash&lt;/code&gt; is a nice and convenient way to&lt;br&gt;
make my object easier to use!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It isn't. You're sacrificing a lot in exchange for almost nothing and your code will suffer for it.&lt;/p&gt;

&lt;p&gt;Another reason to avoid this is that it can imply security holes. There's a very simple example which is mass assignment model attributes from the controller params.&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;# NOTE: This is not how our code works, this is an example of how NOT to do it&lt;/span&gt;
&lt;span class="n"&gt;current_user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;current_company&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;users&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;session&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:current_user&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="n"&gt;current_access&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update!&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;:user&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Can you spot the issue? It is subtle but it is there. An attacker could just send a &lt;code&gt;company_id&lt;/code&gt; and inject themselves on any company 😱. Not good.&lt;/p&gt;

&lt;p&gt;This kind of issue is what made Rails end up adding the strong parameters API: &lt;a href="https://guides.rubyonrails.org/action_controller_overview.html#strong-parameters"&gt;https://guides.rubyonrails.org/action_controller_overview.html#strong-parameters&lt;/a&gt; but that isn't enough. Strong parameters are focused on avoiding mass assignment. But you massively pass &lt;code&gt;params&lt;/code&gt; from a controller into any object as parameters you're exposed to this kind of problem as well.&lt;/p&gt;

&lt;p&gt;In short: Be as explicit as possible with contracts. Pass unfurled parameters as a preference and type as much as you can.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Avoid using hashes as return values.
&lt;/h4&gt;

&lt;p&gt;If whoever uses the code you write doesn't know what to expect from your return value, they'll have a hard time using you. Make it easy for them.&lt;/p&gt;

&lt;p&gt;If you need a dummy object, use a &lt;code&gt;T::Struct&lt;/code&gt; instead (or a &lt;code&gt;Struct&lt;/code&gt;). They are very good for transferring data, they have a defined shape and they are highly typable.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. If you receive a Hash, isolate it.
&lt;/h4&gt;

&lt;p&gt;Let's give an example, you get a &lt;code&gt;Hash&lt;/code&gt; from reading a YAML file, a JSON response from an API or even on a controller action.&lt;/p&gt;

&lt;p&gt;This is, by far, the hardest to solve among all the cases because each one will need a different solution.&lt;/p&gt;

&lt;p&gt;There are however some guidelines you can follow which help a bit:&lt;/p&gt;

&lt;h5&gt;
  
  
  1. Isolating hashes: Get their values
&lt;/h5&gt;

&lt;p&gt;If you only need to get some keys from the Hash, e.g. reading the &lt;code&gt;params&lt;/code&gt; on a controller. You're good to go. Slice the keys you need and then read them.&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;MyController&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;
    &lt;span class="no"&gt;MyCreateInteractor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="ss"&gt;author: &lt;/span&gt;&lt;span class="n"&gt;current_access&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;value: &lt;/span&gt;&lt;span class="n"&gt;create_params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:value&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="ss"&gt;description: &lt;/span&gt;&lt;span class="n"&gt;create_params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:description&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unwrap!&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;create_params&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:description&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;Soon we will be able to use sorbet for this, which will give use shaped and typed params. Until that moment arrives, we need to deal with it.&lt;/p&gt;

&lt;h5&gt;
  
  
  2. Isolating hashes: Build a defensive layer
&lt;/h5&gt;

&lt;p&gt;If the &lt;code&gt;Hash&lt;/code&gt; has layers with more hashes inside of it and you need to extract data from it through &lt;code&gt;Enumerable&lt;/code&gt; methods (&lt;code&gt;find&lt;/code&gt;, &lt;code&gt;map&lt;/code&gt;, &lt;code&gt;select&lt;/code&gt;...) then wrap that hash on an object and interface with that object instead.&lt;/p&gt;

&lt;p&gt;There's an example of this on our &lt;code&gt;PdfParser&lt;/code&gt; library. Its configuration is a YAML file with a shape like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;some_data_table&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;min_x&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;55&lt;/span&gt;
  &lt;span class="na"&gt;min_y&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;111&lt;/span&gt;
  &lt;span class="na"&gt;max_x&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;532&lt;/span&gt;
  &lt;span class="na"&gt;max_y&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;167&lt;/span&gt;
  &lt;span class="na"&gt;transform&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;table&lt;/span&gt;
    &lt;span class="na"&gt;arguments&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;column1&lt;/span&gt;
        &lt;span class="na"&gt;transform&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;text&lt;/span&gt;
        &lt;span class="na"&gt;max_x&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;214&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;column2&lt;/span&gt;
        &lt;span class="na"&gt;transform&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;text&lt;/span&gt;
        &lt;span class="na"&gt;max_x&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;372&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;column3&lt;/span&gt;
        &lt;span class="na"&gt;transform&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;money_es&lt;/span&gt;
        &lt;span class="na"&gt;max_x&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;532&lt;/span&gt;

&lt;span class="na"&gt;some_numeric_field&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;min_x&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;217&lt;/span&gt;
  &lt;span class="na"&gt;min_y&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;81&lt;/span&gt;
  &lt;span class="na"&gt;max_x&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;265&lt;/span&gt;
  &lt;span class="na"&gt;max_y&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;99&lt;/span&gt;
  &lt;span class="na"&gt;transform&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;money_es&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Interfacing with a hash like this is problematic because you don't know what to expect. Have a look at the &lt;code&gt;transform&lt;/code&gt; for example. On the numeric field, it only has a name. But on the table; it has a type, a list of arguments and more nested transforms.&lt;/p&gt;

&lt;p&gt;Let's first understand the problem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This file represents the format for a PDF file. A format has many different fields inside (&lt;code&gt;some_numeric_field&lt;/code&gt; and &lt;code&gt;some_data_table&lt;/code&gt; for example) in this case.&lt;/li&gt;
&lt;li&gt;Each field has boundaries to where it is found on the PDF&lt;/li&gt;
&lt;li&gt;Each field defines a transformation to be applied to it after reading the text on it. E.g.: &lt;code&gt;money_es&lt;/code&gt; means that it is money formatted like &lt;code&gt;1.000,00&lt;/code&gt; and it has to be transformed into a &lt;code&gt;BigDecimal&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How did we get over this? Interfacing with a &lt;code&gt;Hash&lt;/code&gt; like this could have been really complex so we started by separating the parts that change from the parts that stay the same.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All fields have boundaries&lt;/li&gt;
&lt;li&gt;All fields have a name&lt;/li&gt;
&lt;li&gt;All fields have a transform&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What is the changing part? The transform can be different per field so we defined 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="no"&gt;Field&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Struct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:boundaries&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:transform&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="no"&gt;Box&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Struct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:min_x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:min_y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:max_x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:max_y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="no"&gt;Transform&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Struct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:arguments&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;# @param args [Hash]&lt;/span&gt;
  &lt;span class="c1"&gt;# @option args [String, Hash] :transform the name of the transform or a&lt;/span&gt;
  &lt;span class="c1"&gt;#   Hash describing it&lt;/span&gt;
  &lt;span class="c1"&gt;# @option :transform [String] :type the name of the transform&lt;/span&gt;
  &lt;span class="c1"&gt;# @option :transform [Hash] :arguments a hash with the arguments for the&lt;/span&gt;
  &lt;span class="c1"&gt;#   transform&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arguments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:transform&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:transform&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:transform&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="ss"&gt;:type&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
          &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:transform&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="ss"&gt;:arguments&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arguments&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;With that we build objects from reading the file into a Hash 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;# name is the key of the YAML definition for a field and arguments is a hash&lt;/span&gt;
&lt;span class="c1"&gt;# with its content.&lt;/span&gt;
&lt;span class="n"&gt;read_file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="no"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="no"&gt;Transform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="no"&gt;Boundaries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:min_x&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;to_i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:min_y&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;to_i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:max_x&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;to_i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:max_y&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;to_i&lt;/span&gt;
    &lt;span class="p"&gt;)&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;ul&gt;
&lt;li&gt;We only read from the hash in 1 place (when parsing the configuration).&lt;/li&gt;
&lt;li&gt;We have a specific initializer for the case in which we need to pass a hash around (&lt;code&gt;Transform.from_hash&lt;/code&gt;) and we use a &lt;code&gt;case...when&lt;/code&gt; to map it into objects.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is indeed more work but saves you from a lot of pain later on. Nobody will know this all came from a Hash, nobody will try to read a shapeless object and nobody will try to mutate it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are Hashes good for?
&lt;/h2&gt;

&lt;p&gt;They are good as in-memory key-value stores. But even in that case, build a layer to isolate yourself from it. As an example:&lt;/p&gt;

&lt;p&gt;We use this object to store an in-memory cache of the hierarchical relations between employees and their managers. Fetching them is costly and because of our permissions architecture, we do it a lot.&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;HierarchyCache&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;
    &lt;span class="vi"&gt;@cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# If a key has value, return it&lt;/span&gt;
  &lt;span class="c1"&gt;# if it doesn't store the return value of `block` and return the value&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;employee&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;employee&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;nil?&lt;/span&gt;

    &lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;employee&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# Get the value stored on a key&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;employee&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;employee&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# Sore a value for a key&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;employee&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;new_cache_entry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@cache&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;employee&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="vi"&gt;@cache&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;employee&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;merge!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_cache_entry&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="vi"&gt;@cache&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;employee&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new_cache_entry&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;employee&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;We use a hash here but we take care of not letting anybody know we do and most importantly, we don't leak how the hash is structured and we provide a programmatic API to interface it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary (AKA TL;DR)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Avoid using Hashes as input to methods. Try to have shaped inputs.&lt;/li&gt;
&lt;li&gt;Avoid using Hashes as return values. Try to have shaped return values.&lt;/li&gt;
&lt;li&gt;If you receive a Hash, isolate it. Build a layer to interface with instead of the &lt;code&gt;Hash&lt;/code&gt;.

&lt;ul&gt;
&lt;li&gt;Get the data directly if it is a small hash.&lt;/li&gt;
&lt;li&gt;Build objects if it has a heterogeneous structure.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Use them as long as nobody can call &lt;code&gt;[]&lt;/code&gt; or any other &lt;code&gt;Enumerable&lt;/code&gt; method on them.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Last, but not least, don't serialize things into hashes if you intend to use them later on. If you find yourself using &lt;code&gt;[]&lt;/code&gt; on different layers of your code check if you can enforce any of the previous points.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summarized even more
&lt;/h2&gt;

&lt;p&gt;Don't use them to build contracts (as inputs/outputs). No problem as intermediate values (as long as you isolate them well enough).&lt;/p&gt;

</description>
      <category>ruby</category>
    </item>
    <item>
      <title>A trick with Ruby anonymous classes</title>
      <dc:creator>Fran C.</dc:creator>
      <pubDate>Fri, 14 Feb 2020 14:47:12 +0000</pubDate>
      <link>https://forem.com/factorial/a-trick-with-ruby-anonymous-classes-11pp</link>
      <guid>https://forem.com/factorial/a-trick-with-ruby-anonymous-classes-11pp</guid>
      <description>&lt;p&gt;Since everything in Ruby is an object it is only normal that classes are objects too. Which means they just have regular constructors with initializers, as any other object would do.&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="no"&gt;Class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hello&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Hello world!"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hello&lt;/span&gt;

&lt;span class="c1"&gt;# prints -&amp;gt; Hello world!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What can I use it for?
&lt;/h3&gt;

&lt;p&gt;Anonymous classes are an amazing candidate for testing mixings.&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;# callable_test.rb&lt;/span&gt;
&lt;span class="c1"&gt;# run it with:&lt;/span&gt;
&lt;span class="c1"&gt;# ruby callable_test.rb&lt;/span&gt;

&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Callable&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"minitest/autorun"&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestCallable&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Minitest&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Test&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;
    &lt;span class="vi"&gt;@klass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="kp"&gt;extend&lt;/span&gt; &lt;span class="no"&gt;Callable&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arg1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arg2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="vi"&gt;@arg1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arg1&lt;/span&gt;
        &lt;span class="vi"&gt;@arg2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arg2&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;call&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="vi"&gt;@arg1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vi"&gt;@arg2&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;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_same_return&lt;/span&gt;
    &lt;span class="n"&gt;assert_equal&lt;/span&gt; &lt;span class="vi"&gt;@klass&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vi"&gt;@klass&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&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;span class="c1"&gt;# Run options: --seed 3295&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# # Running:&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# .&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# Finished in 0.000605s, 1651.9615 runs/s, 1651.9615 assertions/s.&lt;/span&gt;
&lt;span class="c1"&gt;# 1 runs, 1 assertions, 0 failures, 0 errors, 0 skips&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's a caveat though... You need to be aware that anonymous classes have no name (they are anonymous after all ;) ) so any call to &lt;code&gt;Class.new.name&lt;/code&gt; will return &lt;code&gt;nil&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Classes only acquire a name when you assign them to a constant. That is:&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;klazz&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="n"&gt;klazz&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; nil&lt;/span&gt;

&lt;span class="no"&gt;MyClass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;klazz&lt;/span&gt;
&lt;span class="n"&gt;klazz&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; "MyClass"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, if you need to test things which depend on the class name you can't use anonymous classes, although they still have a benefit over regular declarations on tests, which is that they can be assigned to variables, while regular &lt;code&gt;class...end&lt;/code&gt; declarations can't.&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;my_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyClass&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="n"&gt;my_class&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; nil&lt;/span&gt;

&lt;span class="n"&gt;other_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;OtherClass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="n"&gt;other_class&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; OtherClass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, if you need a class with a name on a test you can still use this, only remember to remove the constant on your test's teardown.&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="no"&gt;Object&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="ss"&gt;:remove_const&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:MyClass&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you're on a Rails app and use RSpec, it even has a helper to test things with anonymous controllers: &lt;a href="https://relishapp.com/rspec/rspec-rails/v/3-9/docs/controller-specs/anonymous-controller"&gt;https://relishapp.com/rspec/rspec-rails/v/3-9/docs/controller-specs/anonymous-controller&lt;/a&gt;, which is especially useful to test things like login/logout flows independently.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>testing</category>
    </item>
    <item>
      <title>A trick with Ruby Hash.new</title>
      <dc:creator>Fran C.</dc:creator>
      <pubDate>Wed, 12 Feb 2020 06:54:29 +0000</pubDate>
      <link>https://forem.com/factorial/a-trick-with-ruby-hash-new-2ma0</link>
      <guid>https://forem.com/factorial/a-trick-with-ruby-hash-new-2ma0</guid>
      <description>&lt;p&gt;Hashes are used a lot in Ruby (sometimes even abused) and they have a very interesting functionality that is rarely used: &lt;code&gt;Hash.new&lt;/code&gt; has 3 different forms&lt;/p&gt;

&lt;h2&gt;
  
  
  Regular form
&lt;/h2&gt;

&lt;p&gt;It just returns an empty hash whose unexisting keys return always &lt;code&gt;nil&lt;/code&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="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Hash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="c1"&gt;# Or h = {}&lt;/span&gt;
&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:hello&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; nil&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is just equivalent to using an empty Hash literal also known as &lt;code&gt;{}&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fixed default
&lt;/h2&gt;

&lt;p&gt;It allows for a parameter which is returned in case the key doesn't exist.&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;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Hash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'world'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:hello&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; 'world'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This form needs to be used carefully though since you always return the same object, which means if you modify it, you modify it for all subsequent calls:&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;h&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:hello&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;upcase!&lt;/span&gt; &lt;span class="c1"&gt;# "WORLD"&lt;/span&gt;
&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:foo&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# "WORLD"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is why only recommend using this option in a case: maps of classes.&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="no"&gt;POLICIES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Hash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;ForbidAllPolicy&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="ss"&gt;admin: &lt;/span&gt;&lt;span class="no"&gt;AccessAllPolicy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;user: &lt;/span&gt;&lt;span class="no"&gt;RestrictedPolicy&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="n"&gt;policy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;POLICIES&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;current_user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;role&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="no"&gt;POLICIES&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; RestrictedPolicy&lt;/span&gt;

&lt;span class="no"&gt;POLICIES&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:hacker&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; ForbidAllPolicy&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why classes but not other objects? Because classes are &lt;a href="https://refactoring.guru/design-patterns/singleton"&gt;singletons&lt;/a&gt; (a singleton is an object that only has one instance at the same time) so you do not care that you're always going to get the very same object all the time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Calculated default
&lt;/h2&gt;

&lt;p&gt;This form gives the biggest freedom since it allows us to pass a block to calculate the value and even to store it on the hash. So the next call to that same key will already have a value.&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;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Hash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nb"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;upcase&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"'&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;' =&amp;gt; '&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;'"&lt;/span&gt;

  &lt;span class="nb"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="c1"&gt;# prints -&amp;gt; 'hello' =&amp;gt; 'HELLO'&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; "HELLO&lt;/span&gt;

&lt;span class="c1"&gt;# Next call to the same key is already assigned, the block isn't executed&lt;/span&gt;

&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; "HELLO"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My preferred use case for this is to protect myself from &lt;code&gt;nil&lt;/code&gt;s and to avoid continuous &lt;code&gt;nil&lt;/code&gt; checks.&lt;/p&gt;

&lt;p&gt;In a case 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;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:hello&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="ss"&gt;:world&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; NoMethodError (undefined method `&amp;lt;&amp;lt;' for nil:NilClass)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can either ensure the key is initialized&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;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:hello&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:hello&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="ss"&gt;:world&lt;/span&gt;
&lt;span class="n"&gt;h&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; {:hello=&amp;gt;[:world]}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or use the trick we just learned to ensure you will never have a &lt;code&gt;nil&lt;/code&gt; and you get a sane default instead.&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;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Hash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:hello&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="ss"&gt;:world&lt;/span&gt;
&lt;span class="n"&gt;h&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; {:hello=&amp;gt;[:world]}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Take into account that passing around a Hash like this might be dangerous as well. Nobody will expect that a Hash returns something for a key that doesn't exist, it can be confusing and hard to debug.&lt;/p&gt;

&lt;p&gt;If we get &lt;code&gt;keys&lt;/code&gt; for the previous hash:&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;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; [:hello]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How to use it then? Just do not let the rest of the world know it is a Hash 😬&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;CachedUser&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;
    &lt;span class="vi"&gt;@cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Hash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&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;k&lt;/span&gt;&lt;span class="p"&gt;)&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;def&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@cache&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;id&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;span class="n"&gt;cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;CachedUser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;

&lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; select * from users where id=1&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; &amp;lt;User: @id=1&amp;gt;&lt;/span&gt;

&lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; &amp;lt;User: @id=1&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Although the example is extremely simple it showcases how you can safely use a Hash as a container object safely without exposing some of its drawbacks but profiting from its flexibility.&lt;/p&gt;

</description>
      <category>ruby</category>
    </item>
    <item>
      <title>A trick with Ruby array literals</title>
      <dc:creator>Fran C.</dc:creator>
      <pubDate>Mon, 10 Feb 2020 09:49:24 +0000</pubDate>
      <link>https://forem.com/factorial/a-trick-with-ruby-array-literals-ha8</link>
      <guid>https://forem.com/factorial/a-trick-with-ruby-array-literals-ha8</guid>
      <description>&lt;p&gt;Declaring an array in Ruby is simple:&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;ary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"foo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"bar"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; ["foo", "bar"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;but did you know you can save the array elements as variables the same time you declare them?&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;ary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"foo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;bar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"bar"&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; "foo"&lt;/span&gt;
&lt;span class="n"&gt;bar&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; "bar"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looks like magic? Well, it is not magic. This happens because assigning a value to a variable is an expression in Ruby. This is applicable to many other cases, like assigning a value on a conditional&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;if&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&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="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"User is &lt;/span&gt;&lt;span class="si"&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;name&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or even crazier: to save the parameter you pass to a method!&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;def&lt;/span&gt; &lt;span class="nf"&gt;some_method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;arg&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;some_method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Hola"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# prints -&amp;gt; "Hola"&lt;/span&gt;

&lt;span class="n"&gt;value&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; "Hola"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Disclaimer: ☝️ those 2 might be bad ideas. I wouldn't use it regularly on any code I write but knowing it is possible is always a good thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  What can I use this for?
&lt;/h2&gt;

&lt;p&gt;It plays quite well with constants that can then be used as some kind of enums:&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="no"&gt;COLORS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="no"&gt;COLOR_RED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"RED"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="no"&gt;COLOR_BLUE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"BLUE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="no"&gt;COLOR_GREEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"GREEN"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="no"&gt;COLOR_YELLOW&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"YELLOW"&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; ["RED", "BLUE", "GREEN", "YELLOW"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On rails apps they are especially useful to declare scopes:&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;scope&lt;/span&gt; &lt;span class="ss"&gt;:non_red&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;color: &lt;/span&gt;&lt;span class="no"&gt;COLORS&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;COLOR_RED&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;scope&lt;/span&gt; &lt;span class="ss"&gt;:blue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;color: &lt;/span&gt;&lt;span class="no"&gt;COLOR_BLUE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>ruby</category>
      <category>rails</category>
    </item>
    <item>
      <title>5 Vim productivity tips to improve your workflow</title>
      <dc:creator>Fran C.</dc:creator>
      <pubDate>Tue, 15 Oct 2019 17:47:56 +0000</pubDate>
      <link>https://forem.com/nflamel/5-vim-productivity-tips-to-improve-your-workflow-3l5e</link>
      <guid>https://forem.com/nflamel/5-vim-productivity-tips-to-improve-your-workflow-3l5e</guid>
      <description>&lt;h2&gt;
  
  
  1. Remap the leader key to the space bar
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; mapleader      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;' '&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;It might look strange, but think about how little you use it on normal mode. The space bar is a pretty accessible key on your keyboard and it will reduce your pinky pain.&lt;/p&gt;
&lt;h2&gt;
  
  
  2. Use &lt;code&gt;Localvimrc&lt;/code&gt; to customize your vim per project
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i3JOwpme--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/embear"&gt;
        embear
      &lt;/a&gt; / &lt;a href="https://github.com/embear/vim-localvimrc"&gt;
        vim-localvimrc
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Search local vimrc files (".lvimrc") in the tree (root dir up to current dir) and load them.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
Localvimrc&lt;/h1&gt;
&lt;p&gt;This plugin searches for local vimrc files in the file system tree of the
currently opened file. It searches for all ".lvimrc" files from the directory
of the file up to the root directory. By default those files are loaded in
order from the root directory to the directory of the file. The filename and
amount of loaded files are customizable through global variables.&lt;/p&gt;
&lt;p&gt;For security reasons it the plugin asks for confirmation before loading a local
vimrc file and loads it using |:sandbox| command. The plugin asks once per
session and local vimrc before loading it, if the file didn't change since
previous loading.&lt;/p&gt;
&lt;p&gt;It is possible to define a whitelist and a blacklist of local vimrc files that
are loaded or ignored unconditionally.&lt;/p&gt;
&lt;p&gt;The plugin can be found on &lt;a href="https://bitbucket.org/embear/localvimrc" rel="nofollow"&gt;Bitbucket&lt;/a&gt;, &lt;a href="https://github.com/embear/vim-localvimrc"&gt;GitHub&lt;/a&gt; and &lt;a href="http://www.vim.org/scripts/script.php?script_id=441" rel="nofollow"&gt;VIM online&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
Commands&lt;/h2&gt;
&lt;h3&gt;
The &lt;code&gt;LocalVimRC&lt;/code&gt; command&lt;/h3&gt;
&lt;p&gt;Resource all local vimrc files for the…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/embear/vim-localvimrc"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;I have lot of customizations for Vim, but making them work on each and every project I work is nearly impossible. For example for JavaScript/TypeScript. In some projects I just use plain JS, in others JS with Flow, in others TypeScript but a bit of plain JS too... and setting up vim with specific linters, shortcuts, etc for each one of them is painful.&lt;/p&gt;

&lt;p&gt;Besides that, sometimes I don't want to make certain configurations public, so adding them to my public dot-files is not an option. &lt;/p&gt;

&lt;p&gt;With this plugin you can easily (and more or less safely) keep those configurations scoped to the projects where you need them.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Spell check your markdown and git commits
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;augroup setSpelling
  autocmd&lt;span class="p"&gt;!&lt;/span&gt;

  autocmd &lt;span class="nb"&gt;FileType&lt;/span&gt; gitcommit &lt;span class="k"&gt;setlocal&lt;/span&gt; &lt;span class="nb"&gt;spell&lt;/span&gt; &lt;span class="nb"&gt;spelllang&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;en_us
  autocmd &lt;span class="nb"&gt;FileType&lt;/span&gt; markdown &lt;span class="k"&gt;setlocal&lt;/span&gt; &lt;span class="nb"&gt;spell&lt;/span&gt; &lt;span class="nb"&gt;spelllang&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;en_us
augroup END
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If (like me) you're not a native English speaker it is even more helpful to have spell checking. This simple piece of config will spell check your git commit messages and the markdown you write.&lt;/p&gt;

&lt;p&gt;Remember when Vim marks a spelling issue you can see the available options with &lt;code&gt;z=&lt;/code&gt;. You want to know more about spelling? Check &lt;code&gt;:help spell&lt;/code&gt; on Vim.&lt;/p&gt;
&lt;h2&gt;
  
  
  4. Use mnemonics for your shortcuts
&lt;/h2&gt;

&lt;p&gt;I have a lot of shorcuts on Vim. Remembering them all is impossible. I group them with mnemonics which are simpler to remember. For example, all my git related mnemonics are grouped under &lt;code&gt;&amp;lt;leader&amp;gt;g&lt;/code&gt; so &lt;code&gt;&amp;lt;leader&amp;gt;gs&lt;/code&gt; means &lt;code&gt;:Gstatus&lt;/code&gt;. Most are obvious, but I've added some comments where not.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;nnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;leader&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;gs &lt;span class="p"&gt;:&lt;/span&gt;Gstatus&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
nnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;leader&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;gc &lt;span class="p"&gt;:&lt;/span&gt;Gcommit&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
nnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;leader&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;gC &lt;span class="p"&gt;:&lt;/span&gt;Gcommit &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="k"&gt;n&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; " commit but ignore hooks
nnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;leader&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;gP &lt;span class="p"&gt;:&lt;/span&gt;Gpush&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
nnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;leader&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;gfP &lt;span class="p"&gt;:&lt;/span&gt;Gpush &lt;span class="p"&gt;--&lt;/span&gt;force&lt;span class="p"&gt;-&lt;/span&gt;with&lt;span class="p"&gt;-&lt;/span&gt;lease&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
nnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;leader&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;gp&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;Gpull&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
nnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;leader&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;gf &lt;span class="p"&gt;:&lt;/span&gt;Gfetch&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
nnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;leader&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;gl &lt;span class="p"&gt;:&lt;/span&gt;GV&lt;span class="p"&gt;!&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; " Git &lt;span class="nb"&gt;log&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; the current &lt;span class="k"&gt;file&lt;/span&gt;
nnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;leader&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;gL &lt;span class="p"&gt;:&lt;/span&gt;GV&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; " Full git &lt;span class="nb"&gt;log&lt;/span&gt;
nnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;leader&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;gd&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;Gvdiff&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
nnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;leader&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;gb &lt;span class="p"&gt;:&lt;/span&gt;Gblame&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
nnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;leader&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;gm &lt;span class="p"&gt;:&lt;/span&gt;Git checkout master&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
nnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;leader&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;g&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;Git checkout &lt;span class="p"&gt;-&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
nnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;leader&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;grm &lt;span class="p"&gt;:&lt;/span&gt;Grebase &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="k"&gt;i&lt;/span&gt; master&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;BTW, If you are interested those 2 use fugitive and gv&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i3JOwpme--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/tpope"&gt;
        tpope
      &lt;/a&gt; / &lt;a href="https://github.com/tpope/vim-fugitive"&gt;
        vim-fugitive
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      fugitive.vim: A Git wrapper so awesome, it should be illegal
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="markdown"&gt;
&lt;h1&gt;
fugitive.vim&lt;/h1&gt;
&lt;p&gt;Fugitive is the premier Vim plugin for Git.  Or maybe it's the premier Git
plugin for Vim?  Either way, it's "so awesome, it should be illegal".  That's
why it's called Fugitive.&lt;/p&gt;
&lt;p&gt;The crown jewel of Fugitive is &lt;code&gt;:Git&lt;/code&gt; (or just &lt;code&gt;:G&lt;/code&gt;), which calls any
arbitrary Git command.  If you know how to use Git at the command line, you
know how to use &lt;code&gt;:Git&lt;/code&gt;.  It's vaguely akin to &lt;code&gt;:!git&lt;/code&gt; but with numerous
improvements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The default behavior is to directly echo the command's output.  Quiet
commands like &lt;code&gt;:Git add&lt;/code&gt; avoid the dreaded "Press ENTER or type command to
continue" prompt.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;:Git commit&lt;/code&gt;, &lt;code&gt;:Git rebase -i&lt;/code&gt;, and other commands that invoke an editor do
their editing in the current Vim instance.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;:Git diff&lt;/code&gt;, &lt;code&gt;:Git log&lt;/code&gt;, and other verbose, paginated commands have their
output loaded into a temporary buffer.  Force this behavior for any command
with…&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/tpope/vim-fugitive"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i3JOwpme--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/junegunn"&gt;
        junegunn
      &lt;/a&gt; / &lt;a href="https://github.com/junegunn/gv.vim"&gt;
        gv.vim
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A git commit browser in Vim
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
gv.vim&lt;/h1&gt;
&lt;p&gt;A git commit browser.&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://cloud.githubusercontent.com/assets/700826/12355378/8bbf0834-bbdf-11e5-9389-1aba7cd1fec1.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--c5CH6eZ8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cloud.githubusercontent.com/assets/700826/12355378/8bbf0834-bbdf-11e5-9389-1aba7cd1fec1.png" alt="gv"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/gregsexton/gitv"&gt;gitv&lt;/a&gt; is nice. But I needed a faster, and
possibly simpler alternative that I can use with a project with thousands of
commits.&lt;/p&gt;
&lt;h2&gt;
Installation&lt;/h2&gt;
&lt;p&gt;Requires fugitive.&lt;/p&gt;
&lt;p&gt;Using &lt;a href="https://github.com/junegunn/vim-plug"&gt;vim-plug&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight highlight-source-viml js-code-highlight"&gt;
&lt;pre&gt;Plug &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;tpope/vim-fugitive&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt;
Plug &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;junegunn/gv.vim&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
Usage&lt;/h2&gt;
&lt;h3&gt;
Commands&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;:GV&lt;/code&gt; to open commit browser
&lt;ul&gt;
&lt;li&gt;You can pass &lt;code&gt;git log&lt;/code&gt; options to the command, e.g. &lt;code&gt;:GV -S foobar -- plugins&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;:GV!&lt;/code&gt; will only list commits that affected the current file&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;:GV?&lt;/code&gt; fills the location list with the revisions of the current file&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;:GV&lt;/code&gt; or &lt;code&gt;:GV?&lt;/code&gt; can be used in visual mode to track the changes in the
selected lines.&lt;/p&gt;
&lt;h3&gt;
Mappings&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;o&lt;/code&gt; or &lt;code&gt;&amp;lt;cr&amp;gt;&lt;/code&gt; on a commit to display the content of it&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;o&lt;/code&gt; or &lt;code&gt;&amp;lt;cr&amp;gt;&lt;/code&gt; on commits to display the diff in the range&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;O&lt;/code&gt; opens a new tab instead&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;gb&lt;/code&gt; for &lt;code&gt;:Gbrowse&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;]]&lt;/code&gt; and &lt;code&gt;[[&lt;/code&gt; to move between commits&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.&lt;/code&gt; to start command-line with…&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/junegunn/gv.vim"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;From 2 of my favorite vim plugin authors. &lt;a href="https://github.com/tpope"&gt;Tim Pope&lt;/a&gt; and &lt;a href="https://github.com/junegunn"&gt;Junegunn Choi&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Learn how to navigate the help.
&lt;/h2&gt;

&lt;p&gt;Vim's help is great. Not only that, most plugins you install come with a very well crafted help. Understanding how to navigate it makes your life easier. It is pretty easy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;:help&lt;/code&gt; to see the global vim help (yeah, that's pretty obvious)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;:help command/topic/shortcut&lt;/code&gt; to see its help. E.g. &lt;code&gt;:help :Gstatus&lt;/code&gt;, &lt;code&gt;:help CTRL-W&lt;/code&gt; or &lt;code&gt;:help sort&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;You'll see some words on the help are highlighted. Those are links and you can follow them with &lt;code&gt;CTRL+]&lt;/code&gt;. If you want to go back to where you were you can use &lt;code&gt;CTRL+o&lt;/code&gt;
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--epeszX1b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/rfe9aig6mzcy0p2ie5wi.png" alt="Link tag on vim help"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Bonus: You don't know what you don't know...
&lt;/h2&gt;

&lt;p&gt;Let me explain that: Vim can do A LOT, you don't know how much (and neither do I). The only way to do it is to research and play with it. Many of the things I do on my &lt;code&gt;.vimrc&lt;/code&gt; come from other people's dotfiles.&lt;/p&gt;

&lt;p&gt;There are literally thousands of dotfiles out there, people shares them (I do share mines!). If you are interested on improving your Vim's workflow go check them. Find famous Vim authors and check what they do. You'll be amazed on how much you will learn!&lt;/p&gt;

</description>
      <category>vim</category>
    </item>
    <item>
      <title>How to have HTTPs on development with Docker, Traefik v2 and mkcert</title>
      <dc:creator>Fran C.</dc:creator>
      <pubDate>Sun, 13 Oct 2019 16:09:21 +0000</pubDate>
      <link>https://forem.com/nflamel/how-to-have-https-on-development-with-docker-traefik-v2-and-mkcert-2jh3</link>
      <guid>https://forem.com/nflamel/how-to-have-https-on-development-with-docker-traefik-v2-and-mkcert-2jh3</guid>
      <description>&lt;h2&gt;
  
  
  Docker is cool
&lt;/h2&gt;

&lt;p&gt;I've discovered Docker recently. I know... it's been there for a while, but I've never added it to my workflow until very recently and I'm quite happy with the solutions it gives me to the problems I have. I'm still a newbie with it and enjoying a lot what I'm learning. &lt;/p&gt;

&lt;p&gt;One of the things I like about Docker is that it allows me to carry the stack definition I want for my project between different computers and reduces a lot the amount of effort I need to setup my dev env when I'm playing with some side projects.&lt;/p&gt;

&lt;p&gt;This article is meant for Docker newbies like myself who need to solve this fairly common  web development problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  HTTPs and domain names in development are important
&lt;/h2&gt;

&lt;p&gt;Making sure that your development environment looks similar to your production one is important. It helps reducing unexpected issues when going live.&lt;/p&gt;

&lt;p&gt;I've used nginx in the past for this and it is still a very solid solution. But in development and just for a simple development reverse proxy I prefer to use &lt;a href="https://traefik.io" rel="noopener noreferrer"&gt;traefik&lt;/a&gt; these days. Mainly because it works pretty well with Docker.&lt;/p&gt;

&lt;p&gt;In addition to that, to simply generate signed certificates in development I use &lt;a href="https://mkcert.dev" rel="noopener noreferrer"&gt;mkcert&lt;/a&gt;, which is super simple to use. Many also propose and use &lt;a href="https://letsencrypt.org" rel="noopener noreferrer"&gt;Let's Encrypt&lt;/a&gt; and traefik itself has some support for it, but we won't use in this example.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stop it already! what do I need?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;You need an application of some sort. Ours is going to be &lt;code&gt;ruby -run -e httpd . -p 3000&lt;/code&gt; which is a server showing the current folder's contents. Note as well that I don't run my apps inside Docker itself during development. I don't do it because I run things like linters, test suites, etc from my editor and running the app inside Docker is usually a barrier for that. &lt;/p&gt;

&lt;p&gt;If you run the app inside docker check the &lt;a href="https://traefik.io" rel="noopener noreferrer"&gt;traefik&lt;/a&gt; documentation because having this same proxy in your case is even easier!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You need Docker running on your machine.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Some way to resolve the domain you want to your app. In my case I just add the domain I need to my &lt;code&gt;/etc/hosts&lt;/code&gt; but you might prefer other solutions like using dnsmasq.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The config!
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;You need something like this in your &lt;code&gt;docker-compose.yml&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;You don't need to have only that. I typically declare other stuff there like databases or other infrastructure pieces that I need in development.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;This is the static configuration for traefik.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;And this is the dynamic one, which defines the routing between the different parts.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Last but not least you need to install &lt;a href="https://mkcert.dev" rel="noopener noreferrer"&gt;mkcert&lt;/a&gt; and run it to generate a couple of mock certs for you. What I usually do is that I keep a &lt;code&gt;devcerts&lt;/code&gt; folder in my projects that I ignore. And then I generate a new cert on each new dev machine. In this case with:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mkcert mkcert my-app.com &lt;span class="s2"&gt;"*.my-app.com"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;To have *.my-app.com available.&lt;/p&gt;

&lt;p&gt;Note however that you could avoid that by using &lt;a href="https://letsencrypt.org" rel="noopener noreferrer"&gt;Let's Encrypt&lt;/a&gt;, but I've not needed it, so I don't use it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Put it all together! This is how I organize the code in this example:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;example
├── devcerts
│   ├── my-app.com+1-key.pem
│   └── my-app.com+1.pem
├── docker-compose.yml
├── traefik.config.toml
└── traefik.toml

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

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run your app (&lt;code&gt;ruby -run -e httpd . -p 3000&lt;/code&gt; or whatever your app incantation is!)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run &lt;code&gt;docker-compose up&lt;/code&gt; and see the magic happen!&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can now go go &lt;code&gt;http://my-app.com&lt;/code&gt; and see how you're automatically redirected to &lt;code&gt;https://my-app.com&lt;/code&gt; and have your app working there :D&lt;/p&gt;

&lt;p&gt;Remember to check &lt;code&gt;http://my-app.com:8080&lt;/code&gt; to see traefik's dashboard.&lt;/p&gt;

&lt;p&gt;Finally kudos to my mate gtrias for showing me what I can do with Docker!&lt;/p&gt;

&lt;p&gt;(Spoiler, he's on dev.to too!)&lt;/p&gt;


&lt;div class="ltag__user ltag__user__id__162886"&gt;
    &lt;a href="/gtrias" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F162886%2F8ca5bc0a-5bf1-477e-91d4-d1aac3b9d497.jpeg" alt="gtrias image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/gtrias"&gt;Genar Trias Ortiz&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/gtrias"&gt;/gtrias&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
 

</description>
      <category>docker</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
