Today I Learned

A Hashrocket project

301 posts by jakeworth @jwworth

Download/Upload Redux Store In Chrome DevTools

People explaining the value of Redux as a JS state solution often point out that it’s designed to support great developer tools. Today I got a better understanding of what that means.

Chrome DevTools currently includes the toolbar shown below. The upload and download buttons, fourth and third from right, allow you to download, inspect (and edit), and upload the Redux store as a JSON file.

This is seems like a fantastic way to debug situations that might be difficult to reproduce through user interactions.

Python and Neovim

Some Vim plugins require Python, and if you’re using NeoVim, you’ll need to do a bit of extra work to get them working. An error message like this, seen when Python is definitely installed on your machine, is a hint you’re in this predicament:

$ vim
MatchTagAlways unavailable: requires python

Neovim needs its own Python support. Solve the problem with this library, specifically one of the following commands depending on your Python version:

$ pip2 install neovim
$ pip3 install neovim

CircleCI Build Forked Pull Requests

Today I learned that CircleCI does not build against forked pull requests by default. You have to enable it under ‘Advanced Settings’.

This is important if your .circleci/config.yml contains build steps like running an automated test suite, linter, or autoformatter. With this setting enabled, every PR goes through the same motions before human review, whether coming from inside or outside the project organization.

autocmd on a List of Extensions

Yesterday I was VimScripting and learned that the autocmd function can execute against multiple file extensions in a single line of setup. Here’s a contrived example:

" ~/.vimrc
autocmd BufWritePost *.exs,*.ex :! git add %

In this code, after every buffer write on files matching .ex and .exs, add the current buffer to our Git staging area. Learning this helped me reduce duplication in my configuration.

Execute Remote Commands with SSH

Today I switched workstations. As a Vim user this means copying some local dotfiles around, appending a few here, deleting a few there. It was a good reminder that executing remote commands is part of SSH.

Here’s how I’ve been appending old custom configurations on my old workstation, to others’ already existing (shared) configurations on the new machine. The quoted command is executed on the remote machine:

$ ssh jake@oldworkstation "cat ~/.vimrc.local" >> ~/.vimrc.local

List Tmux Keys

Want to see all the mapped shortcuts for your Tmux session? Try this, assuming a Tmux leader of <CRTL-Z>:

<CTRL-Z> ?

This produces a list like the following:

bind-key    -T prefix       :                 command-prompt
bind-key    -T prefix       ;                 last-pane
bind-key    -T prefix       =                 choose-buffer
bind-key    -T prefix       ?                 list-keys
bind-key    -T prefix       D                 choose-client

Chrome DevTools Audit Panel

One highlight of the Chrome 63 update was the addition of four new audits to DevTools.

‘Audits’ are one of the many DevTools panels lurking in the background, waiting to make your application better; I hadn’t noticed them until today. They will analyze and provide a downloadable report on your application’s Progressiveness, performance, accessibility, and best practices.

‘Today I Learned’ scored 91 out of 100 on accessibilty. That’s something I’d like to improve, and this panel could help direct that journey.

Limiting Mock API Restarts with Rerun

On a recent project, we built a Sinatra mock API. A feature we added early on was hot code reloading via the rerun gem. Every time a file in the API changes, Sinatra automatically restarts.

It’s a nice system but not perfect, because the server restarts on changes to any file ending in .rb, .html, .md, and number of other extensions. This captures the README, integration tests, and other undesirables, slowing everything down for no particular reason.

rerun’s --dir flag scopes it to just files in the given directory. We chose the src/ directory, which includes the API, mock database, and helpers.

$ rerun --dir src "ruby src/mock_api.rb"

Import All Exports As Object

Here’s a technique for importing constants from a file:

import * as routes from './routes'

This wraps all the exports from routes.js in the object routes. We can access any of those constants like this:

<Route path={routes.exportedPath} />

I like this technique for this use case, because it keeps our import to one line and adds a meaningful namespace.

Vi + Imitation

It’s understood in the Vim community that the name ‘Vim’ stands for ‘Vi + Improved’, because this tool improves upon the classic Vi text editor.

Last night at the Vim Chicago Meetup, I learned that ‘Vim’ once stood for ‘Vi + Imitation.’ Bram Moolenaar, the creator of Vim, changed the name when the feature surpassed the tool it was originally built to imitate.

This was one of many facts I learned during from a fantastic lightning talk on the history of Vim. We recorded it and plan to post it online soon.

Page and Search Through MySQL

Need to explore results in the MySQL REPL? The pager command can help.

Let’s set our pager of choice (we’ll use Less):

mysql> pager less
PAGER set to 'less'

Then, execute the query:

mysql> select * from users;

The result will be loaded in the Less pager. From here, we can navigate or search through the results.

Leave the custom pager with \n:

mysql> \n
PAGER set to stdout

Toggle Mirror Display (OSX)

When using a separate display like a projector, I often switch between screen mirroring (my screen matches the secondary display screen) and not mirroring. Especially during a presentation that uses both slides and live-coding in the terminal.

Instead of navigating through ‘System Preferences’ > ‘Displays’ > ‘Arrangement’, and checking or unchecking the ‘Mirror Displays’ checkbox, I can toggle between the two with ⌘ + F1.

Slow Down, Sinatra

Right now we’re using Sinatra to mock an API. An important consideration for our frontend experience: what happens when the API takes a long time to respond? How do the pages look when they are waiting on a slow, or absent, server?

Sinatra’s support of before blocks allow us to gauge this:

before do

get 'some/endpoint' do

get 'some/other/endpoint' do

With this block, every mocked endpoint will wait three seconds before responding, giving us plenty of time to consider what, in development, would otherwise be an instantaneous delay.

Chrome Dev Tools Selection Variable

Highlight a few HTML elements in the Chrome Developer Tools Elements inspector, and you’ll have a traversable history. The selected element is stored in a variable called $0. We can manipulate it like so:

> $;

Try this when the selected element is hidden or difficult to click. There are four more variables representing your most recently selected elements: $1, $2, $3, and $4.

h/t Josh Branchaud

Compare Form Values with Yup

We’ve been using yup to validate a JavaScript form, and found ourselves facing a common problem when a user signs up for a service:

How do we ensure a user’s email matches their email confirmation?

yup’s test function helped us find a solution. It’s documented like this:

mixed.test(name: string, message: string, test: function)

test takes a name, a message to show on failure, and a function that returns a boolean. We paired this with the email we get from our parent.

var schema = yup.object().shape({
  email: yup
  emailConfirmation: yup
      'emails do not match', 
       function(emailConfirmation) { 
         return emailConfirmation ===; 

Vim Projectionist Default File of Type

When setting up vim-projectionist, we can add a directory and filetype like this:

  "src/components/*.js": {
    "command": "component"

With this in place, :Ecomponent will tab-complete to any JavaScript file in src/components, and :Ecomponent navbar will jump straight to the navbar.js component.

Let’s add a second key that includes a hard-coded file name.

"src/components/*.js": {
    "command": "component"
  "src/components/App.js": { "type": "component" }

This pair tells vim-projectionist to jump to App.js if no argument is provided to :Ecomponent.

Replace App.js with your root component, and you have a shortcut to the top of your component hierarchy.

Catchall in a React Router Switch

Today we built a 404 page for a React app using React Router, via a Switch statement with no specified path. Like a default clause, it catches if none of the other routes match:

  <Route path="/about" component={About}/>
  <Route component={NoMatch}/>

On any other path besides /about, we’ll render our NoMatch component.

Search Github Faster with Shortcuts

Last year, I wrote about Github repository shortcuts for code, issues, and pull requests.

Now Github has a projects tab on each repository. Ever the completist, here’s the shortcut for that tab: gb. Typing this on a Github repo’s page loads the projects tab.

Researching this led me to an even better shortcut, s. This is site-wide and it focuses the Github search bar.

Here’s the impressive full list of Github hotkeys.

Elixir Maps With String/Colon Keys Become Atoms

While running the Elixir 1.6 formatter against Today I Learned, this change caught my eye. The formatter changes maps like this:

%{ "short_name": "TIL" }

To this:

%{ short_name: "TIL" }

This change makes sense because Elixir automatically coerces strings keys in a map, when followed by colons:

iex(1)> %{"foo": "bar"}
%{foo: "bar"}

And so, the conversion is implied. Elixir 1.6’s formatter forces us to be explicit and skip the conversion.

Turn Off HTML5 Form Validations

HTML5 added a variety of input types such as date, email, and tel (telephone number). These make entering certain kinds of information easier by providing tools such as a datepickers, range sliders, and optimized keyboards on mobile devices.

These input types also introduce custom validations on some browsers, which are useful, but can potentially clash with your application’s look and feel.

To keep the input type, but disable the validations, add novalidate to your form tag:

<form novalidate />

h/t Dillon Hafer


Install a Homebrew Formula at Master

We’ve been testing out the forthcoming Elixir 1.6 formatter on Tilex’s codebase, which requires a version of the langage that has not yet been officially released.

There’s a few ways to do this. Since Elixir is installed with Homebrew on my machine, here’s how to do it with Homebrew:

$ brew install elixir --HEAD

From the Homebrew man page:

If --HEAD is passed, and formula defines it, install the HEAD version, aka master, trunk, unstable.

Welcome to the bleeding edge!

h/t Brian Dunn

Clean Up Autojump

autojump is a command-line tool for faster directory changing. It’s a must-have on my workstation, because it lets me jump to deeply nested directories like this:

:~/$ j cli

There are two ways we can clean up autojump once it’s been running for a while. First, purge non-existant directories from the jump database:

$ j --purge
Purged 8 entries.

Second, edit the file ~/Library/autojump/autojump.txt (OSX), which stores the jump database. Here you can remove directories that should never be jumped to, or are weighted too highly because of frequent use in the past.

Happy jumping!

Tidy your Reducers with `combineReducers()`

Today I learned by necessity the value of the Redux combineReducers(reducers) function.

combineReducers() supports, in a pretty neat way, the crucial Redux task of delegating to reducing functions their own slice of the state.

The documentation example looks like this:

combineReducers({ todos: myTodosReducer, counter: myCounterReducer });

Which we can improve by naming the reducer functions after the state slices they manage, allowing ES6 shorthand notation:

combineReducers({ counter, todos });

This creates a state object like so:

  counter: ...,
  todos: ...,

Print Information about an Elixir Data Type

IEx ships with a neat feature, def i(term \\ v(-1)), which provides information about an argument. Here are two examples:

iex(1)> i ["one", "two"]
  ["one", "two"]
Data type
Reference modules
Implemented protocols
  IEx.Info, Collectable, Enumerable, Inspect, List.Chars, String.Chars
iex(1)> i "three"
Data type
Byte size
  This is a string: a UTF-8 encoded binary. It's printed surrounded by
  "double quotes" because all UTF-8 encoded codepoints in it are printable.
Raw representation
  <<116, 104, 114, 101, 101>>
Reference modules
  String, :binary
Implemented protocols
  IEx.Info, Collectable, Inspect, List.Chars, String.Chars

Use this to inspect an item, or learn more about Elixir.

Environmental Variables and Chaining with Postman

Postman is a tool for building APIs. We’ve been digging into it today; it’s got some great features.

Today I learned we can chain requests, passing the result from one API interaction to all subsequent interactions.

Let’s say one API call gets a token on success, a token that all other calls require. When we run the first request, we can add a test that pulls out and sets the token:

var data = JSON.parse(responseBody);
postman.setEnvironmentVariable("token", data.token);

Now, other tests can reference {{token}} in their headers. We can even chain calls in Postman’s automated test runner, ensuring that the token-getting request always runs first.

more info

Exit IEx Gracefully with `respawn()`

I love a debugger in my Elixir code. A pattern I follow is to load and call IEx in a Phoenix template or controller with:

require IEx; IEx.pry;

Then, I call functions and check data in the middle of an action, by starting my Phoenix server with the following command:

$ iex -S mix phx.server

Once finished, I usually end up just killing the server with CTRL-C.

Today I learned there’s a better way: respawn().

respawn() respawns the current shell by starting a new shell process. Which I think is a good thing. It lets me back out of my IEx session without killing my server, a much more graceful development experience.

Hub CI Status

hub is a command-line client for Github. It lets you manage pull requests, forks, issues, and more from the command line. I regularly find new ways to integrate it into my open-source gardening.

Today I learned hub can report on your CI integration. We recently switched TIL to Circle CI, are iterating toward a stable test build, so CI status is important and not always predictable.

I check the status of a commit with the following command:

$ hub ci-status 7aa1316fe8665ef8cab5dd10cc80da024625ba20
$ hub ci-status HEAD

List Commits That Change a File

Today I’m wrapping a PR with a large Git rebase. There are many commits on my branch that change the same file (.circleci/config.yml) and aren’t valuable on their own. In the end, I want them all squashed into a single commit. The challenge is that I changed other files in between; it’s kind of a mess. How can I squash the branch down to something manageable?

One technique is to view just changes to my file:

$ git log --follow --oneline .circleci/config.yml

c9f7108 Try to decode file before unzipping
87c8092 Quick push
327d419 Try this!

Using this list, I can execute a rebase that just squashes the commits that touch the file, leaving everything else intact.

Visualize Your Elixir Dependencies

To visualize your Elixir dependencies, try this:

$ mix deps.tree

This prints a tree showing your dependencies (and their dependencies):

$ mix deps.tree
├── gettext ~> 0.13 (Hex package)
├── hackney 1.8.0 (Hex package)
│   ├── certifi 1.1.0 (Hex package)
│   ├── idna 4.0.0 (Hex package)
│   ├── metrics 1.0.1 (Hex package)
│   ├── mimerl 1.0.2 (Hex package)
│   └── ssl_verify_fun 1.1.1 (Hex package)

This is really handy when trying to track down where a deprecation warning or error is coming from.

h/t Dorian Karter

Conditional Variables in Phoenix Templates

A common Ruby on Rails technique is setting instance variables in a controller action, then using them in the view layer:

# app/controllers/users_controller.rb
def show
  @show_button = true
# app/views/users/show.html.haml
- if @show_button

Doing the same thing in Elixir/Phoenix is a little different.

Since Phoenix 0.14.0, the framework raises on missing assigns (link). Thus our conditional will fail on any loaded template whose controller function that does not define the variable.

One solution is to check if the variable is assigned:

# lib/my_app_web/templates/users/show.html.eex
<%= if assigns[:show_button] do %>
  <div class="button"></div>

If show_button is assigned in your controller function (via assign), the button will be displayed. If not, the button will not be displayed, and the application will not raise an error.

Rails Ignore Pending Migrations

Ruby on Rails gives us a nice warning in development when we haven’t run a pending database migration. But what if we’re iterating on a migration, and the results can best be viewed in the browser? We might want to temporarily disable this warning.

Here’s how to do it:

# config/environments/development.rb
config.active_record.migration_error = false

Don’t forget to turn it back on when you’re finished.

Better Rails SQL Migrations

Some people on our team, including me, write raw SQL in Ruby on Rails migrations. But they can get unwieldy when iterating on a complex migration that does multiple things.

Mitigate this is to break up your statements into separate HERDOCs, like so:

def up
  execute <<-SQL
    update pixaxes set metal = 'diamond' where metal = 'iron';
    -- many things...

  execute <<-SQL
    update swords set metal = 'diamond' where metal = 'iron';
    -- many more things...

If the migration fails, we’ll get an error pointing to the specific problematic HEREDOC, instead of essentially ‘the entire statement is invalid’. You then put a debugger between any HEREDOC to iterate on the issue.

h/t Jack Christensen

Elixir Static Code Analysis in Vim

Today I learned how to set up Credo, a static analysis tool for Elixir, to run on every Vim buffer write, using Neomake.

To start, I added Credo to my project:

# mix.exs
defp deps do
  {:credo, "~> 0.8", only: [:dev, :test], runtime: false}

Including it with:

$ mix deps.get

Next, I loaded and sourced the Neomake plugin with Pathogen:

" ~/.vimbundle

Next, I told Neomake to run on every file, enabling Credo for Elixir files:

" ~/.vimrc
let g:neomake_elixir_enabled_makers = ['credo']
autocmd! BufWritePost * Neomake

Now I have Credo style recommendations right in my text editor.

Complete a Whole Line in Vim

This week I picked up an excellent Vim command: CTRL-X CTRL-L. This command searches backwards through your project and inserts a matching line after the cursor.

So, if there’s a line in your project like this:

defimpl Phoenix.Param, for: Tilex.Developer do

And I type defimpl (which is unique enough to match just a few lines of code in my project), Vim will suggest matching options, letting me choose a match to complete it:

defimpl Phoenix.Param, for: Tilex.Developer do
defimpl Phoenix.Param, for: Tilex.Developer do

This is useful when writing code in a framework like React.js, where the head of many files often includes a group of repetitive import statements.

See ‘Insert mode completion’ inside insert.txt in the Vim help for more information.

h/t Dorian Karter

Screengrab to Clipboard on Mac

If you’ve ever taken a screengrab on a Mac with CMD + Shift + 4, then pasted or dragged that image into a text area such as a Github issue description, there is a better way: CMD + CTRL + Shift + 4. This captures your screengrab right to the clipboard, ready to paste wherever.

The equivalent command with 3– take a screenshot– also works as expected.

This isn’t a particularly ergonomic key combination, but it helps when adding visuals to bug reports and feature requests.

h/t Dorian Karter

List Merged Branches

Today I learned a new Git trick: to show branches already merged into a branch, try this command:

$ git branch --merged master

For an open source project like Today I Learned, this is an interesting way to get a sense of the project.

Authenticate With Username or Email

Today I learned a way to implement a login form that accepts email or username as the login. I’ve been on the other side of a form like this many times, but had never written one myself.

Here’s one solution, with ActiveRecord:

User.where('username = ? or email = ?', "jwworth", "")

title or slug are represented by the same parameter, and either can be nil.

login = params.fetch('username_or_email')
User.where('username = ? or email = ?', login, login)